summaryrefslogtreecommitdiff
path: root/src/pal/src/libunwind
diff options
context:
space:
mode:
Diffstat (limited to 'src/pal/src/libunwind')
-rw-r--r--src/pal/src/libunwind/.gitignore79
-rw-r--r--src/pal/src/libunwind/.travis.yml18
-rw-r--r--src/pal/src/libunwind/AUTHORS1
-rw-r--r--src/pal/src/libunwind/CMakeLists.txt22
-rw-r--r--src/pal/src/libunwind/COPYING20
-rw-r--r--src/pal/src/libunwind/ChangeLog55
-rw-r--r--src/pal/src/libunwind/LICENSE18
-rw-r--r--src/pal/src/libunwind/Makefile.am106
-rw-r--r--src/pal/src/libunwind/NEWS247
-rw-r--r--src/pal/src/libunwind/README207
l---------src/pal/src/libunwind/README.md1
-rw-r--r--src/pal/src/libunwind/TODO97
-rw-r--r--src/pal/src/libunwind/acinclude.m432
-rwxr-xr-xsrc/pal/src/libunwind/autogen.sh9
-rw-r--r--src/pal/src/libunwind/aux_/config.guess1321
-rw-r--r--src/pal/src/libunwind/aux_/config.sub1443
-rw-r--r--src/pal/src/libunwind/aux_/ltmain.sh5107
-rw-r--r--src/pal/src/libunwind/configure.ac445
-rw-r--r--src/pal/src/libunwind/doc/Makefile.am80
-rw-r--r--src/pal/src/libunwind/doc/NOTES127
-rw-r--r--src/pal/src/libunwind/doc/_U_dyn_cancel.man66
-rw-r--r--src/pal/src/libunwind/doc/_U_dyn_cancel.tex46
-rw-r--r--src/pal/src/libunwind/doc/_U_dyn_register.man68
-rw-r--r--src/pal/src/libunwind/doc/_U_dyn_register.tex47
-rw-r--r--src/pal/src/libunwind/doc/common.tex.in11
-rw-r--r--src/pal/src/libunwind/doc/libunwind-dynamic.man538
-rw-r--r--src/pal/src/libunwind/doc/libunwind-dynamic.tex401
-rw-r--r--src/pal/src/libunwind/doc/libunwind-ia64.man314
-rw-r--r--src/pal/src/libunwind/doc/libunwind-ia64.tex216
-rw-r--r--src/pal/src/libunwind/doc/libunwind-ptrace.man220
-rw-r--r--src/pal/src/libunwind/doc/libunwind-ptrace.tex134
-rw-r--r--src/pal/src/libunwind/doc/libunwind-setjmp.man132
-rw-r--r--src/pal/src/libunwind/doc/libunwind-setjmp.tex87
-rw-r--r--src/pal/src/libunwind/doc/libunwind.man508
-rw-r--r--src/pal/src/libunwind/doc/libunwind.tex359
-rw-r--r--src/pal/src/libunwind/doc/libunwind.trans34
-rw-r--r--src/pal/src/libunwind/doc/unw_apply_reg_state.man90
-rw-r--r--src/pal/src/libunwind/doc/unw_apply_reg_state.tex63
-rw-r--r--src/pal/src/libunwind/doc/unw_backtrace.man86
-rw-r--r--src/pal/src/libunwind/doc/unw_backtrace.tex54
-rw-r--r--src/pal/src/libunwind/doc/unw_create_addr_space.man457
-rw-r--r--src/pal/src/libunwind/doc/unw_create_addr_space.tex265
-rw-r--r--src/pal/src/libunwind/doc/unw_destroy_addr_space.man57
-rw-r--r--src/pal/src/libunwind/doc/unw_destroy_addr_space.tex40
-rw-r--r--src/pal/src/libunwind/doc/unw_flush_cache.man93
-rw-r--r--src/pal/src/libunwind/doc/unw_flush_cache.tex58
-rw-r--r--src/pal/src/libunwind/doc/unw_get_accessors.man79
-rw-r--r--src/pal/src/libunwind/doc/unw_get_accessors.tex55
-rw-r--r--src/pal/src/libunwind/doc/unw_get_fpreg.man111
-rw-r--r--src/pal/src/libunwind/doc/unw_get_fpreg.tex77
-rw-r--r--src/pal/src/libunwind/doc/unw_get_proc_info.man203
-rw-r--r--src/pal/src/libunwind/doc/unw_get_proc_info.tex123
-rw-r--r--src/pal/src/libunwind/doc/unw_get_proc_info_by_ip.man134
-rw-r--r--src/pal/src/libunwind/doc/unw_get_proc_info_by_ip.tex91
-rw-r--r--src/pal/src/libunwind/doc/unw_get_proc_name.man123
-rw-r--r--src/pal/src/libunwind/doc/unw_get_proc_name.tex82
-rw-r--r--src/pal/src/libunwind/doc/unw_get_reg.man112
-rw-r--r--src/pal/src/libunwind/doc/unw_get_reg.tex77
-rw-r--r--src/pal/src/libunwind/doc/unw_getcontext.man93
-rw-r--r--src/pal/src/libunwind/doc/unw_getcontext.tex63
-rw-r--r--src/pal/src/libunwind/doc/unw_init_local.man124
-rw-r--r--src/pal/src/libunwind/doc/unw_init_local.tex80
-rw-r--r--src/pal/src/libunwind/doc/unw_init_local2.man1
-rw-r--r--src/pal/src/libunwind/doc/unw_init_remote.man123
-rw-r--r--src/pal/src/libunwind/doc/unw_init_remote.tex79
-rw-r--r--src/pal/src/libunwind/doc/unw_is_fpreg.man73
-rw-r--r--src/pal/src/libunwind/doc/unw_is_fpreg.tex52
-rw-r--r--src/pal/src/libunwind/doc/unw_is_signal_frame.man88
-rw-r--r--src/pal/src/libunwind/doc/unw_is_signal_frame.tex67
-rw-r--r--src/pal/src/libunwind/doc/unw_reg_states_iterate.man137
-rw-r--r--src/pal/src/libunwind/doc/unw_reg_states_iterate.tex83
-rw-r--r--src/pal/src/libunwind/doc/unw_regname.man68
-rw-r--r--src/pal/src/libunwind/doc/unw_regname.tex47
-rw-r--r--src/pal/src/libunwind/doc/unw_resume.man146
-rw-r--r--src/pal/src/libunwind/doc/unw_resume.tex99
-rw-r--r--src/pal/src/libunwind/doc/unw_set_cache_size.man88
-rw-r--r--src/pal/src/libunwind/doc/unw_set_cache_size.tex59
-rw-r--r--src/pal/src/libunwind/doc/unw_set_caching_policy.man119
-rw-r--r--src/pal/src/libunwind/doc/unw_set_caching_policy.tex81
-rw-r--r--src/pal/src/libunwind/doc/unw_set_fpreg.man117
-rw-r--r--src/pal/src/libunwind/doc/unw_set_fpreg.tex79
-rw-r--r--src/pal/src/libunwind/doc/unw_set_reg.man117
-rw-r--r--src/pal/src/libunwind/doc/unw_set_reg.tex79
-rw-r--r--src/pal/src/libunwind/doc/unw_step.man106
-rw-r--r--src/pal/src/libunwind/doc/unw_step.tex68
-rw-r--r--src/pal/src/libunwind/doc/unw_strerror.man63
-rw-r--r--src/pal/src/libunwind/doc/unw_strerror.tex42
-rw-r--r--src/pal/src/libunwind/include/compiler.h72
-rw-r--r--src/pal/src/libunwind/include/dwarf-eh.h128
-rw-r--r--src/pal/src/libunwind/include/dwarf.h450
-rw-r--r--src/pal/src/libunwind/include/dwarf_i.h490
-rw-r--r--src/pal/src/libunwind/include/libunwind-aarch64.h210
-rw-r--r--src/pal/src/libunwind/include/libunwind-arm.h303
-rw-r--r--src/pal/src/libunwind/include/libunwind-common.h.in281
-rw-r--r--src/pal/src/libunwind/include/libunwind-coredump.h73
-rw-r--r--src/pal/src/libunwind/include/libunwind-dynamic.h214
-rw-r--r--src/pal/src/libunwind/include/libunwind-hppa.h125
-rw-r--r--src/pal/src/libunwind/include/libunwind-ia64.h194
-rw-r--r--src/pal/src/libunwind/include/libunwind-mips.h160
-rw-r--r--src/pal/src/libunwind/include/libunwind-ppc32.h207
-rw-r--r--src/pal/src/libunwind/include/libunwind-ppc64.h271
-rw-r--r--src/pal/src/libunwind/include/libunwind-ptrace.h63
-rw-r--r--src/pal/src/libunwind/include/libunwind-sh.h114
-rw-r--r--src/pal/src/libunwind/include/libunwind-tilegx.h161
-rw-r--r--src/pal/src/libunwind/include/libunwind-x86.h187
-rw-r--r--src/pal/src/libunwind/include/libunwind-x86_64.h141
-rw-r--r--src/pal/src/libunwind/include/libunwind.h.in36
-rw-r--r--src/pal/src/libunwind/include/libunwind_i.h366
-rw-r--r--src/pal/src/libunwind/include/mempool.h89
-rw-r--r--src/pal/src/libunwind/include/remote.h129
-rw-r--r--src/pal/src/libunwind/include/tdep-aarch64/dwarf-config.h52
-rw-r--r--src/pal/src/libunwind/include/tdep-aarch64/jmpbuf.h33
-rw-r--r--src/pal/src/libunwind/include/tdep-aarch64/libunwind_i.h320
-rw-r--r--src/pal/src/libunwind/include/tdep-arm/dwarf-config.h51
-rw-r--r--src/pal/src/libunwind/include/tdep-arm/ex_tables.h55
-rw-r--r--src/pal/src/libunwind/include/tdep-arm/jmpbuf.h32
-rw-r--r--src/pal/src/libunwind/include/tdep-arm/libunwind_i.h326
-rw-r--r--src/pal/src/libunwind/include/tdep-hppa/dwarf-config.h54
-rw-r--r--src/pal/src/libunwind/include/tdep-hppa/jmpbuf.h33
-rw-r--r--src/pal/src/libunwind/include/tdep-hppa/libunwind_i.h279
-rw-r--r--src/pal/src/libunwind/include/tdep-ia64/jmpbuf.h32
-rw-r--r--src/pal/src/libunwind/include/tdep-ia64/libunwind_i.h281
-rw-r--r--src/pal/src/libunwind/include/tdep-ia64/rse.h67
-rw-r--r--src/pal/src/libunwind/include/tdep-ia64/script.h85
-rw-r--r--src/pal/src/libunwind/include/tdep-mips/dwarf-config.h54
-rw-r--r--src/pal/src/libunwind/include/tdep-mips/jmpbuf.h32
-rw-r--r--src/pal/src/libunwind/include/tdep-mips/libunwind_i.h331
-rw-r--r--src/pal/src/libunwind/include/tdep-ppc32/dwarf-config.h56
-rw-r--r--src/pal/src/libunwind/include/tdep-ppc32/jmpbuf.h37
-rw-r--r--src/pal/src/libunwind/include/tdep-ppc32/libunwind_i.h314
-rw-r--r--src/pal/src/libunwind/include/tdep-ppc64/dwarf-config.h56
-rw-r--r--src/pal/src/libunwind/include/tdep-ppc64/jmpbuf.h37
-rw-r--r--src/pal/src/libunwind/include/tdep-ppc64/libunwind_i.h369
-rw-r--r--src/pal/src/libunwind/include/tdep-sh/dwarf-config.h49
-rw-r--r--src/pal/src/libunwind/include/tdep-sh/jmpbuf.h48
-rw-r--r--src/pal/src/libunwind/include/tdep-sh/libunwind_i.h280
-rw-r--r--src/pal/src/libunwind/include/tdep-tilegx/dwarf-config.h50
-rw-r--r--src/pal/src/libunwind/include/tdep-tilegx/jmpbuf.h33
-rw-r--r--src/pal/src/libunwind/include/tdep-tilegx/libunwind_i.h263
-rw-r--r--src/pal/src/libunwind/include/tdep-x86/dwarf-config.h52
-rw-r--r--src/pal/src/libunwind/include/tdep-x86/jmpbuf.h42
-rw-r--r--src/pal/src/libunwind/include/tdep-x86/libunwind_i.h293
-rw-r--r--src/pal/src/libunwind/include/tdep-x86_64/dwarf-config.h57
-rw-r--r--src/pal/src/libunwind/include/tdep-x86_64/jmpbuf.h43
-rw-r--r--src/pal/src/libunwind/include/tdep-x86_64/libunwind_i.h264
-rw-r--r--src/pal/src/libunwind/include/tdep/dwarf-config.h28
-rw-r--r--src/pal/src/libunwind/include/tdep/jmpbuf.h30
-rw-r--r--src/pal/src/libunwind/include/tdep/libunwind_i.h.in37
-rw-r--r--src/pal/src/libunwind/include/unwind.h154
-rw-r--r--src/pal/src/libunwind/include/x86/jmpbuf.h31
-rwxr-xr-xsrc/pal/src/libunwind/scripts/kernel-diff.sh10
-rw-r--r--src/pal/src/libunwind/scripts/kernel-files.txt19
-rwxr-xr-xsrc/pal/src/libunwind/scripts/make-L-files30
-rw-r--r--src/pal/src/libunwind/src/CMakeLists.txt337
-rw-r--r--src/pal/src/libunwind/src/Makefile.am750
-rw-r--r--src/pal/src/libunwind/src/aarch64/Gapply_reg_state.c37
-rw-r--r--src/pal/src/libunwind/src/aarch64/Gcreate_addr_space.c60
-rw-r--r--src/pal/src/libunwind/src/aarch64/Gget_proc_info.c39
-rw-r--r--src/pal/src/libunwind/src/aarch64/Gget_save_loc.c100
-rw-r--r--src/pal/src/libunwind/src/aarch64/Gglobal.c57
-rw-r--r--src/pal/src/libunwind/src/aarch64/Ginit.c190
-rw-r--r--src/pal/src/libunwind/src/aarch64/Ginit_local.c78
-rw-r--r--src/pal/src/libunwind/src/aarch64/Ginit_remote.c45
-rw-r--r--src/pal/src/libunwind/src/aarch64/Gis_signal_frame.c64
-rw-r--r--src/pal/src/libunwind/src/aarch64/Greg_states_iterate.c37
-rw-r--r--src/pal/src/libunwind/src/aarch64/Gregs.c118
-rw-r--r--src/pal/src/libunwind/src/aarch64/Gresume.c198
-rw-r--r--src/pal/src/libunwind/src/aarch64/Gstash_frame.c89
-rw-r--r--src/pal/src/libunwind/src/aarch64/Gstep.c189
-rw-r--r--src/pal/src/libunwind/src/aarch64/Gtrace.c548
-rw-r--r--src/pal/src/libunwind/src/aarch64/Lapply_reg_state.c5
-rw-r--r--src/pal/src/libunwind/src/aarch64/Lcreate_addr_space.c5
-rw-r--r--src/pal/src/libunwind/src/aarch64/Lget_proc_info.c5
-rw-r--r--src/pal/src/libunwind/src/aarch64/Lget_save_loc.c5
-rw-r--r--src/pal/src/libunwind/src/aarch64/Lglobal.c5
-rw-r--r--src/pal/src/libunwind/src/aarch64/Linit.c5
-rw-r--r--src/pal/src/libunwind/src/aarch64/Linit_local.c5
-rw-r--r--src/pal/src/libunwind/src/aarch64/Linit_remote.c5
-rw-r--r--src/pal/src/libunwind/src/aarch64/Lis_signal_frame.c5
-rw-r--r--src/pal/src/libunwind/src/aarch64/Lreg_states_iterate.c5
-rw-r--r--src/pal/src/libunwind/src/aarch64/Lregs.c5
-rw-r--r--src/pal/src/libunwind/src/aarch64/Lresume.c5
-rw-r--r--src/pal/src/libunwind/src/aarch64/Lstash_frame.c5
-rw-r--r--src/pal/src/libunwind/src/aarch64/Lstep.c5
-rw-r--r--src/pal/src/libunwind/src/aarch64/Ltrace.c5
-rw-r--r--src/pal/src/libunwind/src/aarch64/gen-offsets.c68
-rw-r--r--src/pal/src/libunwind/src/aarch64/getcontext.S52
-rw-r--r--src/pal/src/libunwind/src/aarch64/init.h126
-rw-r--r--src/pal/src/libunwind/src/aarch64/is_fpreg.c32
-rw-r--r--src/pal/src/libunwind/src/aarch64/offsets.h49
-rw-r--r--src/pal/src/libunwind/src/aarch64/regname.c106
-rw-r--r--src/pal/src/libunwind/src/aarch64/siglongjmp.S12
-rw-r--r--src/pal/src/libunwind/src/aarch64/unwind_i.h64
-rw-r--r--src/pal/src/libunwind/src/arm/Gapply_reg_state.c37
-rw-r--r--src/pal/src/libunwind/src/arm/Gcreate_addr_space.c60
-rw-r--r--src/pal/src/libunwind/src/arm/Gex_tables.c549
-rw-r--r--src/pal/src/libunwind/src/arm/Gget_proc_info.c41
-rw-r--r--src/pal/src/libunwind/src/arm/Gget_save_loc.c81
-rw-r--r--src/pal/src/libunwind/src/arm/Gglobal.c65
-rw-r--r--src/pal/src/libunwind/src/arm/Ginit.c235
-rw-r--r--src/pal/src/libunwind/src/arm/Ginit_local.c78
-rw-r--r--src/pal/src/libunwind/src/arm/Ginit_remote.c45
-rw-r--r--src/pal/src/libunwind/src/arm/Gos-freebsd.c129
-rw-r--r--src/pal/src/libunwind/src/arm/Gos-linux.c182
-rw-r--r--src/pal/src/libunwind/src/arm/Gos-other.c48
-rw-r--r--src/pal/src/libunwind/src/arm/Greg_states_iterate.c37
-rw-r--r--src/pal/src/libunwind/src/arm/Gregs.c83
-rw-r--r--src/pal/src/libunwind/src/arm/Gresume.c154
-rw-r--r--src/pal/src/libunwind/src/arm/Gstash_frame.c90
-rw-r--r--src/pal/src/libunwind/src/arm/Gstep.c192
-rw-r--r--src/pal/src/libunwind/src/arm/Gtrace.c557
-rw-r--r--src/pal/src/libunwind/src/arm/Lapply_reg_state.c5
-rw-r--r--src/pal/src/libunwind/src/arm/Lcreate_addr_space.c5
-rw-r--r--src/pal/src/libunwind/src/arm/Lex_tables.c5
-rw-r--r--src/pal/src/libunwind/src/arm/Lget_proc_info.c5
-rw-r--r--src/pal/src/libunwind/src/arm/Lget_save_loc.c5
-rw-r--r--src/pal/src/libunwind/src/arm/Lglobal.c5
-rw-r--r--src/pal/src/libunwind/src/arm/Linit.c5
-rw-r--r--src/pal/src/libunwind/src/arm/Linit_local.c5
-rw-r--r--src/pal/src/libunwind/src/arm/Linit_remote.c5
-rw-r--r--src/pal/src/libunwind/src/arm/Lis_signal_frame.c5
-rw-r--r--src/pal/src/libunwind/src/arm/Los-freebsd.c5
-rw-r--r--src/pal/src/libunwind/src/arm/Los-linux.c5
-rw-r--r--src/pal/src/libunwind/src/arm/Los-other.c5
-rw-r--r--src/pal/src/libunwind/src/arm/Lreg_states_iterate.c5
-rw-r--r--src/pal/src/libunwind/src/arm/Lregs.c5
-rw-r--r--src/pal/src/libunwind/src/arm/Lresume.c5
-rw-r--r--src/pal/src/libunwind/src/arm/Lstash_frame.c5
-rw-r--r--src/pal/src/libunwind/src/arm/Lstep.c5
-rw-r--r--src/pal/src/libunwind/src/arm/Ltrace.c6
-rw-r--r--src/pal/src/libunwind/src/arm/gen-offsets.c54
-rw-r--r--src/pal/src/libunwind/src/arm/getcontext.S63
-rw-r--r--src/pal/src/libunwind/src/arm/init.h77
-rw-r--r--src/pal/src/libunwind/src/arm/is_fpreg.c39
-rw-r--r--src/pal/src/libunwind/src/arm/offsets.h42
-rw-r--r--src/pal/src/libunwind/src/arm/regname.c90
-rw-r--r--src/pal/src/libunwind/src/arm/siglongjmp.S12
-rw-r--r--src/pal/src/libunwind/src/arm/unwind_i.h62
-rw-r--r--src/pal/src/libunwind/src/config.h.in16
-rw-r--r--src/pal/src/libunwind/src/configure.cmake31
-rw-r--r--src/pal/src/libunwind/src/coredump/README8
-rw-r--r--src/pal/src/libunwind/src/coredump/_UCD_access_mem.c98
-rw-r--r--src/pal/src/libunwind/src/coredump/_UCD_access_reg_freebsd.c137
-rw-r--r--src/pal/src/libunwind/src/coredump/_UCD_access_reg_linux.c146
-rw-r--r--src/pal/src/libunwind/src/coredump/_UCD_accessors.c36
-rw-r--r--src/pal/src/libunwind/src/coredump/_UCD_create.c417
-rw-r--r--src/pal/src/libunwind/src/coredump/_UCD_destroy.c52
-rw-r--r--src/pal/src/libunwind/src/coredump/_UCD_elf_map_image.c98
-rw-r--r--src/pal/src/libunwind/src/coredump/_UCD_find_proc_info.c163
-rw-r--r--src/pal/src/libunwind/src/coredump/_UCD_get_proc_name.c70
-rw-r--r--src/pal/src/libunwind/src/coredump/_UCD_internal.h105
-rw-r--r--src/pal/src/libunwind/src/coredump/_UCD_lib.h57
-rw-r--r--src/pal/src/libunwind/src/coredump/_UPT_access_fpreg.c34
-rw-r--r--src/pal/src/libunwind/src/coredump/_UPT_elf.c5
-rw-r--r--src/pal/src/libunwind/src/coredump/_UPT_get_dyn_info_list_addr.c108
-rw-r--r--src/pal/src/libunwind/src/coredump/_UPT_put_unwind_info.c36
-rw-r--r--src/pal/src/libunwind/src/coredump/_UPT_resume.c35
-rw-r--r--src/pal/src/libunwind/src/coredump/libunwind-coredump.pc.in11
-rw-r--r--src/pal/src/libunwind/src/dwarf/Gexpr.c696
-rw-r--r--src/pal/src/libunwind/src/dwarf/Gfde.c359
-rw-r--r--src/pal/src/libunwind/src/dwarf/Gfind_proc_info-lsb.c935
-rw-r--r--src/pal/src/libunwind/src/dwarf/Gfind_unwind_table.c230
-rw-r--r--src/pal/src/libunwind/src/dwarf/Gparser.c1059
-rw-r--r--src/pal/src/libunwind/src/dwarf/Gpe.c39
-rw-r--r--src/pal/src/libunwind/src/dwarf/Lexpr.c5
-rw-r--r--src/pal/src/libunwind/src/dwarf/Lfde.c5
-rw-r--r--src/pal/src/libunwind/src/dwarf/Lfind_proc_info-lsb.c5
-rw-r--r--src/pal/src/libunwind/src/dwarf/Lfind_unwind_table.c5
-rw-r--r--src/pal/src/libunwind/src/dwarf/Lparser.c5
-rw-r--r--src/pal/src/libunwind/src/dwarf/Lpe.c5
-rw-r--r--src/pal/src/libunwind/src/dwarf/global.c37
-rw-r--r--src/pal/src/libunwind/src/elf32.c4
-rw-r--r--src/pal/src/libunwind/src/elf32.h9
-rw-r--r--src/pal/src/libunwind/src/elf64.c4
-rw-r--r--src/pal/src/libunwind/src/elf64.h9
-rw-r--r--src/pal/src/libunwind/src/elfxx.c481
-rw-r--r--src/pal/src/libunwind/src/elfxx.h101
-rw-r--r--src/pal/src/libunwind/src/hppa/Gapply_reg_state.c37
-rw-r--r--src/pal/src/libunwind/src/hppa/Gcreate_addr_space.c54
-rw-r--r--src/pal/src/libunwind/src/hppa/Gget_proc_info.c46
-rw-r--r--src/pal/src/libunwind/src/hppa/Gget_save_loc.c59
-rw-r--r--src/pal/src/libunwind/src/hppa/Gglobal.c55
-rw-r--r--src/pal/src/libunwind/src/hppa/Ginit.c194
-rw-r--r--src/pal/src/libunwind/src/hppa/Ginit_local.c77
-rw-r--r--src/pal/src/libunwind/src/hppa/Ginit_remote.c46
-rw-r--r--src/pal/src/libunwind/src/hppa/Gis_signal_frame.c74
-rw-r--r--src/pal/src/libunwind/src/hppa/Greg_states_iterate.c37
-rw-r--r--src/pal/src/libunwind/src/hppa/Gregs.c87
-rw-r--r--src/pal/src/libunwind/src/hppa/Gresume.c145
-rw-r--r--src/pal/src/libunwind/src/hppa/Gstep.c95
-rw-r--r--src/pal/src/libunwind/src/hppa/Lapply_reg_state.c5
-rw-r--r--src/pal/src/libunwind/src/hppa/Lcreate_addr_space.c5
-rw-r--r--src/pal/src/libunwind/src/hppa/Lget_proc_info.c5
-rw-r--r--src/pal/src/libunwind/src/hppa/Lget_save_loc.c5
-rw-r--r--src/pal/src/libunwind/src/hppa/Lglobal.c5
-rw-r--r--src/pal/src/libunwind/src/hppa/Linit.c5
-rw-r--r--src/pal/src/libunwind/src/hppa/Linit_local.c5
-rw-r--r--src/pal/src/libunwind/src/hppa/Linit_remote.c5
-rw-r--r--src/pal/src/libunwind/src/hppa/Lis_signal_frame.c5
-rw-r--r--src/pal/src/libunwind/src/hppa/Lreg_states_iterate.c5
-rw-r--r--src/pal/src/libunwind/src/hppa/Lregs.c5
-rw-r--r--src/pal/src/libunwind/src/hppa/Lresume.c5
-rw-r--r--src/pal/src/libunwind/src/hppa/Lstep.c5
-rw-r--r--src/pal/src/libunwind/src/hppa/get_accessors.c38
-rw-r--r--src/pal/src/libunwind/src/hppa/getcontext.S74
-rw-r--r--src/pal/src/libunwind/src/hppa/init.h47
-rw-r--r--src/pal/src/libunwind/src/hppa/offsets.h17
-rw-r--r--src/pal/src/libunwind/src/hppa/regname.c50
-rw-r--r--src/pal/src/libunwind/src/hppa/setcontext.S77
-rw-r--r--src/pal/src/libunwind/src/hppa/siglongjmp.S16
-rw-r--r--src/pal/src/libunwind/src/hppa/tables.c43
-rw-r--r--src/pal/src/libunwind/src/hppa/unwind_i.h47
-rw-r--r--src/pal/src/libunwind/src/ia64/Gapply_reg_state.c39
-rw-r--r--src/pal/src/libunwind/src/ia64/Gcreate_addr_space.c63
-rw-r--r--src/pal/src/libunwind/src/ia64/Gfind_unwind_table.c143
-rw-r--r--src/pal/src/libunwind/src/ia64/Gget_proc_info.c38
-rw-r--r--src/pal/src/libunwind/src/ia64/Gget_save_loc.c168
-rw-r--r--src/pal/src/libunwind/src/ia64/Gglobal.c122
-rw-r--r--src/pal/src/libunwind/src/ia64/Ginit.c505
-rw-r--r--src/pal/src/libunwind/src/ia64/Ginit_local.c110
-rw-r--r--src/pal/src/libunwind/src/ia64/Ginit_remote.c61
-rw-r--r--src/pal/src/libunwind/src/ia64/Ginstall_cursor.S348
-rw-r--r--src/pal/src/libunwind/src/ia64/Gis_signal_frame.c54
-rw-r--r--src/pal/src/libunwind/src/ia64/Gparser.c1131
-rw-r--r--src/pal/src/libunwind/src/ia64/Grbs.c319
-rw-r--r--src/pal/src/libunwind/src/ia64/Greg_states_iterate.c39
-rw-r--r--src/pal/src/libunwind/src/ia64/Gregs.c612
-rw-r--r--src/pal/src/libunwind/src/ia64/Gresume.c274
-rw-r--r--src/pal/src/libunwind/src/ia64/Gscript.c765
-rw-r--r--src/pal/src/libunwind/src/ia64/Gstep.c359
-rw-r--r--src/pal/src/libunwind/src/ia64/Gtables.c731
-rw-r--r--src/pal/src/libunwind/src/ia64/Lapply_reg_state.c5
-rw-r--r--src/pal/src/libunwind/src/ia64/Lcreate_addr_space.c5
-rw-r--r--src/pal/src/libunwind/src/ia64/Lfind_unwind_table.c5
-rw-r--r--src/pal/src/libunwind/src/ia64/Lget_proc_info.c5
-rw-r--r--src/pal/src/libunwind/src/ia64/Lget_save_loc.c5
-rw-r--r--src/pal/src/libunwind/src/ia64/Lglobal.c5
-rw-r--r--src/pal/src/libunwind/src/ia64/Linit.c5
-rw-r--r--src/pal/src/libunwind/src/ia64/Linit_local.c5
-rw-r--r--src/pal/src/libunwind/src/ia64/Linit_remote.c5
-rw-r--r--src/pal/src/libunwind/src/ia64/Linstall_cursor.S6
-rw-r--r--src/pal/src/libunwind/src/ia64/Lis_signal_frame.c5
-rw-r--r--src/pal/src/libunwind/src/ia64/Lparser.c5
-rw-r--r--src/pal/src/libunwind/src/ia64/Lrbs.c5
-rw-r--r--src/pal/src/libunwind/src/ia64/Lreg_states_iterate.c5
-rw-r--r--src/pal/src/libunwind/src/ia64/Lregs.c5
-rw-r--r--src/pal/src/libunwind/src/ia64/Lresume.c5
-rw-r--r--src/pal/src/libunwind/src/ia64/Lscript.c5
-rw-r--r--src/pal/src/libunwind/src/ia64/Lstep.c5
-rw-r--r--src/pal/src/libunwind/src/ia64/Ltables.c5
-rw-r--r--src/pal/src/libunwind/src/ia64/NOTES65
-rw-r--r--src/pal/src/libunwind/src/ia64/dyn_info_list.S26
-rw-r--r--src/pal/src/libunwind/src/ia64/getcontext.S177
-rw-r--r--src/pal/src/libunwind/src/ia64/init.h132
-rw-r--r--src/pal/src/libunwind/src/ia64/longjmp.S42
-rwxr-xr-xsrc/pal/src/libunwind/src/ia64/mk_cursor_i7
-rw-r--r--src/pal/src/libunwind/src/ia64/offsets.h137
-rw-r--r--src/pal/src/libunwind/src/ia64/regname.c189
-rw-r--r--src/pal/src/libunwind/src/ia64/regs.h73
-rw-r--r--src/pal/src/libunwind/src/ia64/setjmp.S51
-rw-r--r--src/pal/src/libunwind/src/ia64/siglongjmp.S69
-rw-r--r--src/pal/src/libunwind/src/ia64/sigsetjmp.S69
-rw-r--r--src/pal/src/libunwind/src/ia64/ucontext_i.h68
-rw-r--r--src/pal/src/libunwind/src/ia64/unwind_decoder.h477
-rw-r--r--src/pal/src/libunwind/src/ia64/unwind_i.h633
-rw-r--r--src/pal/src/libunwind/src/libunwind-generic.pc.in11
-rw-r--r--src/pal/src/libunwind/src/mi/Gdestroy_addr_space.c37
-rw-r--r--src/pal/src/libunwind/src/mi/Gdyn-extract.c64
-rw-r--r--src/pal/src/libunwind/src/mi/Gdyn-remote.c326
-rw-r--r--src/pal/src/libunwind/src/mi/Gfind_dynamic_proc_info.c91
-rw-r--r--src/pal/src/libunwind/src/mi/Gget_accessors.c37
-rw-r--r--src/pal/src/libunwind/src/mi/Gget_fpreg.c34
-rw-r--r--src/pal/src/libunwind/src/mi/Gget_proc_info_by_ip.c39
-rw-r--r--src/pal/src/libunwind/src/mi/Gget_proc_name.c118
-rw-r--r--src/pal/src/libunwind/src/mi/Gget_reg.c41
-rw-r--r--src/pal/src/libunwind/src/mi/Gput_dynamic_unwind_info.c55
-rw-r--r--src/pal/src/libunwind/src/mi/Gset_cache_size.c72
-rw-r--r--src/pal/src/libunwind/src/mi/Gset_caching_policy.c46
-rw-r--r--src/pal/src/libunwind/src/mi/Gset_fpreg.c34
-rw-r--r--src/pal/src/libunwind/src/mi/Gset_reg.c34
-rw-r--r--src/pal/src/libunwind/src/mi/Ldestroy_addr_space.c5
-rw-r--r--src/pal/src/libunwind/src/mi/Ldyn-extract.c5
-rw-r--r--src/pal/src/libunwind/src/mi/Ldyn-remote.c5
-rw-r--r--src/pal/src/libunwind/src/mi/Lfind_dynamic_proc_info.c5
-rw-r--r--src/pal/src/libunwind/src/mi/Lget_accessors.c5
-rw-r--r--src/pal/src/libunwind/src/mi/Lget_fpreg.c5
-rw-r--r--src/pal/src/libunwind/src/mi/Lget_proc_info_by_ip.c5
-rw-r--r--src/pal/src/libunwind/src/mi/Lget_proc_name.c5
-rw-r--r--src/pal/src/libunwind/src/mi/Lget_reg.c5
-rw-r--r--src/pal/src/libunwind/src/mi/Lput_dynamic_unwind_info.c5
-rw-r--r--src/pal/src/libunwind/src/mi/Lset_cache_size.c5
-rw-r--r--src/pal/src/libunwind/src/mi/Lset_caching_policy.c5
-rw-r--r--src/pal/src/libunwind/src/mi/Lset_fpreg.c5
-rw-r--r--src/pal/src/libunwind/src/mi/Lset_reg.c5
-rw-r--r--src/pal/src/libunwind/src/mi/_ReadSLEB.c25
-rw-r--r--src/pal/src/libunwind/src/mi/_ReadULEB.c20
-rw-r--r--src/pal/src/libunwind/src/mi/backtrace.c81
-rw-r--r--src/pal/src/libunwind/src/mi/dyn-cancel.c46
-rw-r--r--src/pal/src/libunwind/src/mi/dyn-info-list.c34
-rw-r--r--src/pal/src/libunwind/src/mi/dyn-register.c44
-rw-r--r--src/pal/src/libunwind/src/mi/flush_cache.c59
-rw-r--r--src/pal/src/libunwind/src/mi/init.c60
-rw-r--r--src/pal/src/libunwind/src/mi/mempool.c184
-rw-r--r--src/pal/src/libunwind/src/mi/strerror.c51
-rw-r--r--src/pal/src/libunwind/src/mips/Gapply_reg_state.c37
-rw-r--r--src/pal/src/libunwind/src/mips/Gcreate_addr_space.c66
-rw-r--r--src/pal/src/libunwind/src/mips/Gget_proc_info.c41
-rw-r--r--src/pal/src/libunwind/src/mips/Gget_save_loc.c100
-rw-r--r--src/pal/src/libunwind/src/mips/Gglobal.c55
-rw-r--r--src/pal/src/libunwind/src/mips/Ginit.c210
-rw-r--r--src/pal/src/libunwind/src/mips/Ginit_local.c76
-rw-r--r--src/pal/src/libunwind/src/mips/Ginit_remote.c45
-rw-r--r--src/pal/src/libunwind/src/mips/Gis_signal_frame.c78
-rw-r--r--src/pal/src/libunwind/src/mips/Greg_states_iterate.c37
-rw-r--r--src/pal/src/libunwind/src/mips/Gregs.c105
-rw-r--r--src/pal/src/libunwind/src/mips/Gresume.c45
-rw-r--r--src/pal/src/libunwind/src/mips/Gstep.c132
-rw-r--r--src/pal/src/libunwind/src/mips/Lapply_reg_state.c5
-rw-r--r--src/pal/src/libunwind/src/mips/Lcreate_addr_space.c5
-rw-r--r--src/pal/src/libunwind/src/mips/Lget_proc_info.c5
-rw-r--r--src/pal/src/libunwind/src/mips/Lget_save_loc.c5
-rw-r--r--src/pal/src/libunwind/src/mips/Lglobal.c5
-rw-r--r--src/pal/src/libunwind/src/mips/Linit.c5
-rw-r--r--src/pal/src/libunwind/src/mips/Linit_local.c5
-rw-r--r--src/pal/src/libunwind/src/mips/Linit_remote.c5
-rw-r--r--src/pal/src/libunwind/src/mips/Lis_signal_frame.c5
-rw-r--r--src/pal/src/libunwind/src/mips/Lreg_states_iterate.c5
-rw-r--r--src/pal/src/libunwind/src/mips/Lregs.c5
-rw-r--r--src/pal/src/libunwind/src/mips/Lresume.c5
-rw-r--r--src/pal/src/libunwind/src/mips/Lstep.c5
-rw-r--r--src/pal/src/libunwind/src/mips/elfxx.c27
-rw-r--r--src/pal/src/libunwind/src/mips/gen-offsets.c30
-rw-r--r--src/pal/src/libunwind/src/mips/getcontext.S93
-rw-r--r--src/pal/src/libunwind/src/mips/init.h59
-rw-r--r--src/pal/src/libunwind/src/mips/is_fpreg.c35
-rw-r--r--src/pal/src/libunwind/src/mips/offsets.h86
-rw-r--r--src/pal/src/libunwind/src/mips/regname.c48
-rw-r--r--src/pal/src/libunwind/src/mips/siglongjmp.S8
-rw-r--r--src/pal/src/libunwind/src/mips/unwind_i.h43
-rw-r--r--src/pal/src/libunwind/src/os-freebsd.c166
-rw-r--r--src/pal/src/libunwind/src/os-hpux.c78
-rw-r--r--src/pal/src/libunwind/src/os-linux.c73
-rw-r--r--src/pal/src/libunwind/src/os-linux.h297
-rw-r--r--src/pal/src/libunwind/src/os-qnx.c117
-rw-r--r--src/pal/src/libunwind/src/ppc/Gapply_reg_state.c37
-rw-r--r--src/pal/src/libunwind/src/ppc/Gget_proc_info.c41
-rw-r--r--src/pal/src/libunwind/src/ppc/Gget_save_loc.c34
-rw-r--r--src/pal/src/libunwind/src/ppc/Ginit_local.c88
-rw-r--r--src/pal/src/libunwind/src/ppc/Ginit_remote.c60
-rw-r--r--src/pal/src/libunwind/src/ppc/Gis_signal_frame.c78
-rw-r--r--src/pal/src/libunwind/src/ppc/Greg_states_iterate.c37
-rw-r--r--src/pal/src/libunwind/src/ppc/Lapply_reg_state.c5
-rw-r--r--src/pal/src/libunwind/src/ppc/Lget_proc_info.c5
-rw-r--r--src/pal/src/libunwind/src/ppc/Lget_save_loc.c5
-rw-r--r--src/pal/src/libunwind/src/ppc/Linit_local.c5
-rw-r--r--src/pal/src/libunwind/src/ppc/Linit_remote.c5
-rw-r--r--src/pal/src/libunwind/src/ppc/Lis_signal_frame.c5
-rw-r--r--src/pal/src/libunwind/src/ppc/Lreg_states_iterate.c5
-rw-r--r--src/pal/src/libunwind/src/ppc/longjmp.S36
-rw-r--r--src/pal/src/libunwind/src/ppc/siglongjmp.S31
-rw-r--r--src/pal/src/libunwind/src/ppc32/Gapply_reg_state.c37
-rw-r--r--src/pal/src/libunwind/src/ppc32/Gcreate_addr_space.c56
-rw-r--r--src/pal/src/libunwind/src/ppc32/Gglobal.c135
-rw-r--r--src/pal/src/libunwind/src/ppc32/Ginit.c216
-rw-r--r--src/pal/src/libunwind/src/ppc32/Greg_states_iterate.c37
-rw-r--r--src/pal/src/libunwind/src/ppc32/Gregs.c90
-rw-r--r--src/pal/src/libunwind/src/ppc32/Gresume.c77
-rw-r--r--src/pal/src/libunwind/src/ppc32/Gstep.c309
-rw-r--r--src/pal/src/libunwind/src/ppc32/Lapply_reg_state.c5
-rw-r--r--src/pal/src/libunwind/src/ppc32/Lcreate_addr_space.c5
-rw-r--r--src/pal/src/libunwind/src/ppc32/Lglobal.c5
-rw-r--r--src/pal/src/libunwind/src/ppc32/Linit.c5
-rw-r--r--src/pal/src/libunwind/src/ppc32/Lreg_states_iterate.c5
-rw-r--r--src/pal/src/libunwind/src/ppc32/Lregs.c5
-rw-r--r--src/pal/src/libunwind/src/ppc32/Lresume.c5
-rw-r--r--src/pal/src/libunwind/src/ppc32/Lstep.c5
-rw-r--r--src/pal/src/libunwind/src/ppc32/Make-arch.in11
-rw-r--r--src/pal/src/libunwind/src/ppc32/get_func_addr.c36
-rw-r--r--src/pal/src/libunwind/src/ppc32/init.h72
-rw-r--r--src/pal/src/libunwind/src/ppc32/is_fpreg.c34
-rw-r--r--src/pal/src/libunwind/src/ppc32/regname.c112
-rw-r--r--src/pal/src/libunwind/src/ppc32/setcontext.S9
-rw-r--r--src/pal/src/libunwind/src/ppc32/ucontext_i.h128
-rw-r--r--src/pal/src/libunwind/src/ppc32/unwind_i.h46
-rw-r--r--src/pal/src/libunwind/src/ppc64/Gapply_reg_state.c37
-rw-r--r--src/pal/src/libunwind/src/ppc64/Gcreate_addr_space.c71
-rw-r--r--src/pal/src/libunwind/src/ppc64/Gglobal.c182
-rw-r--r--src/pal/src/libunwind/src/ppc64/Ginit.c229
-rw-r--r--src/pal/src/libunwind/src/ppc64/Greg_states_iterate.c37
-rw-r--r--src/pal/src/libunwind/src/ppc64/Gregs.c141
-rw-r--r--src/pal/src/libunwind/src/ppc64/Gresume.c111
-rw-r--r--src/pal/src/libunwind/src/ppc64/Gstep.c466
-rw-r--r--src/pal/src/libunwind/src/ppc64/Lapply_reg_state.c5
-rw-r--r--src/pal/src/libunwind/src/ppc64/Lcreate_addr_space.c5
-rw-r--r--src/pal/src/libunwind/src/ppc64/Lglobal.c5
-rw-r--r--src/pal/src/libunwind/src/ppc64/Linit.c5
-rw-r--r--src/pal/src/libunwind/src/ppc64/Lreg_states_iterate.c5
-rw-r--r--src/pal/src/libunwind/src/ppc64/Lregs.c5
-rw-r--r--src/pal/src/libunwind/src/ppc64/Lresume.c5
-rw-r--r--src/pal/src/libunwind/src/ppc64/Lstep.c5
-rw-r--r--src/pal/src/libunwind/src/ppc64/get_func_addr.c51
-rw-r--r--src/pal/src/libunwind/src/ppc64/init.h82
-rw-r--r--src/pal/src/libunwind/src/ppc64/is_fpreg.c34
-rw-r--r--src/pal/src/libunwind/src/ppc64/regname.c164
-rw-r--r--src/pal/src/libunwind/src/ppc64/setcontext.S9
-rw-r--r--src/pal/src/libunwind/src/ppc64/ucontext_i.h173
-rw-r--r--src/pal/src/libunwind/src/ppc64/unwind_i.h52
-rw-r--r--src/pal/src/libunwind/src/ptrace/_UPT_access_fpreg.c121
-rw-r--r--src/pal/src/libunwind/src/ptrace/_UPT_access_mem.c123
-rw-r--r--src/pal/src/libunwind/src/ptrace/_UPT_access_reg.c352
-rw-r--r--src/pal/src/libunwind/src/ptrace/_UPT_accessors.c38
-rw-r--r--src/pal/src/libunwind/src/ptrace/_UPT_create.c46
-rw-r--r--src/pal/src/libunwind/src/ptrace/_UPT_destroy.c34
-rw-r--r--src/pal/src/libunwind/src/ptrace/_UPT_elf.c5
-rw-r--r--src/pal/src/libunwind/src/ptrace/_UPT_find_proc_info.c145
-rw-r--r--src/pal/src/libunwind/src/ptrace/_UPT_get_dyn_info_list_addr.c105
-rw-r--r--src/pal/src/libunwind/src/ptrace/_UPT_get_proc_name.c42
-rw-r--r--src/pal/src/libunwind/src/ptrace/_UPT_internal.h59
-rw-r--r--src/pal/src/libunwind/src/ptrace/_UPT_put_unwind_info.c35
-rw-r--r--src/pal/src/libunwind/src/ptrace/_UPT_reg_offset.c638
-rw-r--r--src/pal/src/libunwind/src/ptrace/_UPT_resume.c40
-rw-r--r--src/pal/src/libunwind/src/ptrace/libunwind-ptrace.pc.in11
-rw-r--r--src/pal/src/libunwind/src/setjmp/libunwind-setjmp.pc.in11
-rw-r--r--src/pal/src/libunwind/src/setjmp/longjmp.c115
-rw-r--r--src/pal/src/libunwind/src/setjmp/setjmp.c49
-rw-r--r--src/pal/src/libunwind/src/setjmp/setjmp_i.h118
-rw-r--r--src/pal/src/libunwind/src/setjmp/siglongjmp.c127
-rw-r--r--src/pal/src/libunwind/src/setjmp/sigsetjmp.c50
-rw-r--r--src/pal/src/libunwind/src/sh/Gapply_reg_state.c37
-rw-r--r--src/pal/src/libunwind/src/sh/Gcreate_addr_space.c59
-rw-r--r--src/pal/src/libunwind/src/sh/Gget_proc_info.c39
-rw-r--r--src/pal/src/libunwind/src/sh/Gget_save_loc.c83
-rw-r--r--src/pal/src/libunwind/src/sh/Gglobal.c56
-rw-r--r--src/pal/src/libunwind/src/sh/Ginit.c186
-rw-r--r--src/pal/src/libunwind/src/sh/Ginit_local.c78
-rw-r--r--src/pal/src/libunwind/src/sh/Ginit_remote.c45
-rw-r--r--src/pal/src/libunwind/src/sh/Gis_signal_frame.c119
-rw-r--r--src/pal/src/libunwind/src/sh/Greg_states_iterate.c37
-rw-r--r--src/pal/src/libunwind/src/sh/Gregs.c81
-rw-r--r--src/pal/src/libunwind/src/sh/Gresume.c165
-rw-r--r--src/pal/src/libunwind/src/sh/Gstep.c117
-rw-r--r--src/pal/src/libunwind/src/sh/Lapply_reg_state.c5
-rw-r--r--src/pal/src/libunwind/src/sh/Lcreate_addr_space.c5
-rw-r--r--src/pal/src/libunwind/src/sh/Lget_proc_info.c5
-rw-r--r--src/pal/src/libunwind/src/sh/Lget_save_loc.c5
-rw-r--r--src/pal/src/libunwind/src/sh/Lglobal.c5
-rw-r--r--src/pal/src/libunwind/src/sh/Linit.c5
-rw-r--r--src/pal/src/libunwind/src/sh/Linit_local.c5
-rw-r--r--src/pal/src/libunwind/src/sh/Linit_remote.c5
-rw-r--r--src/pal/src/libunwind/src/sh/Lis_signal_frame.c5
-rw-r--r--src/pal/src/libunwind/src/sh/Lreg_states_iterate.c5
-rw-r--r--src/pal/src/libunwind/src/sh/Lregs.c5
-rw-r--r--src/pal/src/libunwind/src/sh/Lresume.c5
-rw-r--r--src/pal/src/libunwind/src/sh/Lstep.c5
-rw-r--r--src/pal/src/libunwind/src/sh/gen-offsets.c51
-rw-r--r--src/pal/src/libunwind/src/sh/init.h73
-rw-r--r--src/pal/src/libunwind/src/sh/is_fpreg.c32
-rw-r--r--src/pal/src/libunwind/src/sh/offsets.h32
-rw-r--r--src/pal/src/libunwind/src/sh/regname.c56
-rw-r--r--src/pal/src/libunwind/src/sh/siglongjmp.S8
-rw-r--r--src/pal/src/libunwind/src/sh/unwind_i.h40
-rw-r--r--src/pal/src/libunwind/src/tilegx/Gapply_reg_state.c37
-rw-r--r--src/pal/src/libunwind/src/tilegx/Gcreate_addr_space.c65
-rw-r--r--src/pal/src/libunwind/src/tilegx/Gget_proc_info.c48
-rw-r--r--src/pal/src/libunwind/src/tilegx/Gget_save_loc.c62
-rw-r--r--src/pal/src/libunwind/src/tilegx/Gglobal.c64
-rw-r--r--src/pal/src/libunwind/src/tilegx/Ginit.c167
-rw-r--r--src/pal/src/libunwind/src/tilegx/Ginit_local.c80
-rw-r--r--src/pal/src/libunwind/src/tilegx/Ginit_remote.c47
-rw-r--r--src/pal/src/libunwind/src/tilegx/Gis_signal_frame.c115
-rw-r--r--src/pal/src/libunwind/src/tilegx/Greg_states_iterate.c37
-rw-r--r--src/pal/src/libunwind/src/tilegx/Gregs.c76
-rw-r--r--src/pal/src/libunwind/src/tilegx/Gresume.c94
-rw-r--r--src/pal/src/libunwind/src/tilegx/Gstep.c53
-rw-r--r--src/pal/src/libunwind/src/tilegx/Lapply_reg_state.c5
-rw-r--r--src/pal/src/libunwind/src/tilegx/Lcreate_addr_space.c5
-rw-r--r--src/pal/src/libunwind/src/tilegx/Lget_proc_info.c5
-rw-r--r--src/pal/src/libunwind/src/tilegx/Lget_save_loc.c5
-rw-r--r--src/pal/src/libunwind/src/tilegx/Lglobal.c5
-rw-r--r--src/pal/src/libunwind/src/tilegx/Linit.c5
-rw-r--r--src/pal/src/libunwind/src/tilegx/Linit_local.c5
-rw-r--r--src/pal/src/libunwind/src/tilegx/Linit_remote.c5
-rw-r--r--src/pal/src/libunwind/src/tilegx/Lis_signal_frame.c5
-rw-r--r--src/pal/src/libunwind/src/tilegx/Lreg_states_iterate.c5
-rw-r--r--src/pal/src/libunwind/src/tilegx/Lregs.c5
-rw-r--r--src/pal/src/libunwind/src/tilegx/Lresume.c5
-rw-r--r--src/pal/src/libunwind/src/tilegx/Lstep.c5
-rw-r--r--src/pal/src/libunwind/src/tilegx/elfxx.c27
-rw-r--r--src/pal/src/libunwind/src/tilegx/gen-offsets.c30
-rw-r--r--src/pal/src/libunwind/src/tilegx/getcontext.S36
-rw-r--r--src/pal/src/libunwind/src/tilegx/init.h63
-rw-r--r--src/pal/src/libunwind/src/tilegx/is_fpreg.c33
-rw-r--r--src/pal/src/libunwind/src/tilegx/offsets.h12
-rw-r--r--src/pal/src/libunwind/src/tilegx/regname.c55
-rw-r--r--src/pal/src/libunwind/src/tilegx/siglongjmp.S7
-rw-r--r--src/pal/src/libunwind/src/tilegx/unwind_i.h46
-rw-r--r--src/pal/src/libunwind/src/unwind/Backtrace.c56
-rw-r--r--src/pal/src/libunwind/src/unwind/DeleteException.c38
-rw-r--r--src/pal/src/libunwind/src/unwind/FindEnclosingFunction.c42
-rw-r--r--src/pal/src/libunwind/src/unwind/ForcedUnwind.c52
-rw-r--r--src/pal/src/libunwind/src/unwind/GetBSP.c42
-rw-r--r--src/pal/src/libunwind/src/unwind/GetCFA.c38
-rw-r--r--src/pal/src/libunwind/src/unwind/GetDataRelBase.c39
-rw-r--r--src/pal/src/libunwind/src/unwind/GetGR.c43
-rw-r--r--src/pal/src/libunwind/src/unwind/GetIP.c38
-rw-r--r--src/pal/src/libunwind/src/unwind/GetIPInfo.c42
-rw-r--r--src/pal/src/libunwind/src/unwind/GetLanguageSpecificData.c40
-rw-r--r--src/pal/src/libunwind/src/unwind/GetRegionStart.c39
-rw-r--r--src/pal/src/libunwind/src/unwind/GetTextRelBase.c35
-rw-r--r--src/pal/src/libunwind/src/unwind/RaiseException.c103
-rw-r--r--src/pal/src/libunwind/src/unwind/Resume.c42
-rw-r--r--src/pal/src/libunwind/src/unwind/Resume_or_Rethrow.c47
-rw-r--r--src/pal/src/libunwind/src/unwind/SetGR.c47
-rw-r--r--src/pal/src/libunwind/src/unwind/SetIP.c35
-rw-r--r--src/pal/src/libunwind/src/unwind/libunwind.pc.in11
-rw-r--r--src/pal/src/libunwind/src/unwind/unwind-internal.h140
-rw-r--r--src/pal/src/libunwind/src/x86/Gapply_reg_state.c37
-rw-r--r--src/pal/src/libunwind/src/x86/Gcreate_addr_space.c58
-rw-r--r--src/pal/src/libunwind/src/x86/Gget_proc_info.c45
-rw-r--r--src/pal/src/libunwind/src/x86/Gget_save_loc.c133
-rw-r--r--src/pal/src/libunwind/src/x86/Gglobal.c67
-rw-r--r--src/pal/src/libunwind/src/x86/Ginit.c243
-rw-r--r--src/pal/src/libunwind/src/x86/Ginit_local.c79
-rw-r--r--src/pal/src/libunwind/src/x86/Ginit_remote.c56
-rw-r--r--src/pal/src/libunwind/src/x86/Gos-freebsd.c374
-rw-r--r--src/pal/src/libunwind/src/x86/Gos-linux.c331
-rw-r--r--src/pal/src/libunwind/src/x86/Greg_states_iterate.c37
-rw-r--r--src/pal/src/libunwind/src/x86/Gregs.c178
-rw-r--r--src/pal/src/libunwind/src/x86/Gresume.c91
-rw-r--r--src/pal/src/libunwind/src/x86/Gstep.c115
-rw-r--r--src/pal/src/libunwind/src/x86/Lapply_reg_state.c5
-rw-r--r--src/pal/src/libunwind/src/x86/Lcreate_addr_space.c5
-rw-r--r--src/pal/src/libunwind/src/x86/Lget_proc_info.c5
-rw-r--r--src/pal/src/libunwind/src/x86/Lget_save_loc.c5
-rw-r--r--src/pal/src/libunwind/src/x86/Lglobal.c5
-rw-r--r--src/pal/src/libunwind/src/x86/Linit.c5
-rw-r--r--src/pal/src/libunwind/src/x86/Linit_local.c5
-rw-r--r--src/pal/src/libunwind/src/x86/Linit_remote.c5
-rw-r--r--src/pal/src/libunwind/src/x86/Los-freebsd.c5
-rw-r--r--src/pal/src/libunwind/src/x86/Los-linux.c5
-rw-r--r--src/pal/src/libunwind/src/x86/Lreg_states_iterate.c5
-rw-r--r--src/pal/src/libunwind/src/x86/Lregs.c5
-rw-r--r--src/pal/src/libunwind/src/x86/Lresume.c5
-rw-r--r--src/pal/src/libunwind/src/x86/Lstep.c5
-rw-r--r--src/pal/src/libunwind/src/x86/getcontext-freebsd.S112
-rw-r--r--src/pal/src/libunwind/src/x86/getcontext-linux.S74
-rw-r--r--src/pal/src/libunwind/src/x86/init.h69
-rw-r--r--src/pal/src/libunwind/src/x86/is_fpreg.c34
-rw-r--r--src/pal/src/libunwind/src/x86/longjmp.S39
-rw-r--r--src/pal/src/libunwind/src/x86/offsets.h140
-rw-r--r--src/pal/src/libunwind/src/x86/regname.c27
-rw-r--r--src/pal/src/libunwind/src/x86/siglongjmp.S92
-rw-r--r--src/pal/src/libunwind/src/x86/unwind_i.h68
-rw-r--r--src/pal/src/libunwind/src/x86_64/Gapply_reg_state.c37
-rw-r--r--src/pal/src/libunwind/src/x86_64/Gcreate_addr_space.c61
-rw-r--r--src/pal/src/libunwind/src/x86_64/Gget_proc_info.c48
-rw-r--r--src/pal/src/libunwind/src/x86_64/Gget_save_loc.c73
-rw-r--r--src/pal/src/libunwind/src/x86_64/Gglobal.c102
-rw-r--r--src/pal/src/libunwind/src/x86_64/Ginit.c342
-rw-r--r--src/pal/src/libunwind/src/x86_64/Ginit_local.c81
-rw-r--r--src/pal/src/libunwind/src/x86_64/Ginit_remote.c57
-rw-r--r--src/pal/src/libunwind/src/x86_64/Gos-freebsd.c218
-rw-r--r--src/pal/src/libunwind/src/x86_64/Gos-linux.c156
-rw-r--r--src/pal/src/libunwind/src/x86_64/Greg_states_iterate.c37
-rw-r--r--src/pal/src/libunwind/src/x86_64/Gregs.c138
-rw-r--r--src/pal/src/libunwind/src/x86_64/Gresume.c123
-rw-r--r--src/pal/src/libunwind/src/x86_64/Gstash_frame.c119
-rw-r--r--src/pal/src/libunwind/src/x86_64/Gstep.c227
-rw-r--r--src/pal/src/libunwind/src/x86_64/Gtrace.c551
-rw-r--r--src/pal/src/libunwind/src/x86_64/Lapply_reg_state.c5
-rw-r--r--src/pal/src/libunwind/src/x86_64/Lcreate_addr_space.c5
-rw-r--r--src/pal/src/libunwind/src/x86_64/Lget_proc_info.c5
-rw-r--r--src/pal/src/libunwind/src/x86_64/Lget_save_loc.c5
-rw-r--r--src/pal/src/libunwind/src/x86_64/Lglobal.c6
-rw-r--r--src/pal/src/libunwind/src/x86_64/Linit.c5
-rw-r--r--src/pal/src/libunwind/src/x86_64/Linit_local.c5
-rw-r--r--src/pal/src/libunwind/src/x86_64/Linit_remote.c5
-rw-r--r--src/pal/src/libunwind/src/x86_64/Los-freebsd.c5
-rw-r--r--src/pal/src/libunwind/src/x86_64/Los-linux.c5
-rw-r--r--src/pal/src/libunwind/src/x86_64/Lreg_states_iterate.c5
-rw-r--r--src/pal/src/libunwind/src/x86_64/Lregs.c5
-rw-r--r--src/pal/src/libunwind/src/x86_64/Lresume.c5
-rw-r--r--src/pal/src/libunwind/src/x86_64/Lstash_frame.c5
-rw-r--r--src/pal/src/libunwind/src/x86_64/Lstep.c5
-rw-r--r--src/pal/src/libunwind/src/x86_64/Ltrace.c5
-rw-r--r--src/pal/src/libunwind/src/x86_64/getcontext.S134
-rw-r--r--src/pal/src/libunwind/src/x86_64/init.h89
-rw-r--r--src/pal/src/libunwind/src/x86_64/is_fpreg.c38
-rw-r--r--src/pal/src/libunwind/src/x86_64/longjmp.S34
-rw-r--r--src/pal/src/libunwind/src/x86_64/offsets.h3
-rw-r--r--src/pal/src/libunwind/src/x86_64/regname.c56
-rw-r--r--src/pal/src/libunwind/src/x86_64/setcontext.S83
-rw-r--r--src/pal/src/libunwind/src/x86_64/siglongjmp.S32
-rw-r--r--src/pal/src/libunwind/src/x86_64/ucontext_i.h82
-rw-r--r--src/pal/src/libunwind/src/x86_64/unwind_i.h93
-rw-r--r--src/pal/src/libunwind/tests/Gia64-test-nat.c626
-rw-r--r--src/pal/src/libunwind/tests/Gia64-test-rbs.c193
-rw-r--r--src/pal/src/libunwind/tests/Gia64-test-readonly.c89
-rw-r--r--src/pal/src/libunwind/tests/Gia64-test-stack.c176
-rw-r--r--src/pal/src/libunwind/tests/Gperf-simple.c264
-rw-r--r--src/pal/src/libunwind/tests/Gperf-trace.c250
-rw-r--r--src/pal/src/libunwind/tests/Gtest-bt.c263
-rw-r--r--src/pal/src/libunwind/tests/Gtest-concurrent.c136
-rw-r--r--src/pal/src/libunwind/tests/Gtest-dyn1.c223
-rw-r--r--src/pal/src/libunwind/tests/Gtest-exc.c162
-rw-r--r--src/pal/src/libunwind/tests/Gtest-init.cxx107
-rw-r--r--src/pal/src/libunwind/tests/Gtest-nomalloc.c110
-rw-r--r--src/pal/src/libunwind/tests/Gtest-resume-sig-rt.c31
-rw-r--r--src/pal/src/libunwind/tests/Gtest-resume-sig.c200
-rw-r--r--src/pal/src/libunwind/tests/Gtest-trace.c282
-rw-r--r--src/pal/src/libunwind/tests/Lia64-test-nat.c5
-rw-r--r--src/pal/src/libunwind/tests/Lia64-test-rbs.c5
-rw-r--r--src/pal/src/libunwind/tests/Lia64-test-readonly.c5
-rw-r--r--src/pal/src/libunwind/tests/Lia64-test-stack.c5
-rw-r--r--src/pal/src/libunwind/tests/Lperf-simple.c5
-rw-r--r--src/pal/src/libunwind/tests/Lperf-trace.c5
-rw-r--r--src/pal/src/libunwind/tests/Lrs-race.c1514
-rw-r--r--src/pal/src/libunwind/tests/Ltest-bt.c5
-rw-r--r--src/pal/src/libunwind/tests/Ltest-concurrent.c5
-rw-r--r--src/pal/src/libunwind/tests/Ltest-cxx-exceptions.cxx80
-rw-r--r--src/pal/src/libunwind/tests/Ltest-dyn1.c5
-rw-r--r--src/pal/src/libunwind/tests/Ltest-exc.c5
-rw-r--r--src/pal/src/libunwind/tests/Ltest-init-local-signal-lib.c6
-rw-r--r--src/pal/src/libunwind/tests/Ltest-init-local-signal.c60
-rw-r--r--src/pal/src/libunwind/tests/Ltest-init.cxx5
-rw-r--r--src/pal/src/libunwind/tests/Ltest-mem-validate.c143
-rw-r--r--src/pal/src/libunwind/tests/Ltest-nocalloc.c137
-rw-r--r--src/pal/src/libunwind/tests/Ltest-nomalloc.c5
-rw-r--r--src/pal/src/libunwind/tests/Ltest-resume-sig-rt.c5
-rw-r--r--src/pal/src/libunwind/tests/Ltest-resume-sig.c5
-rw-r--r--src/pal/src/libunwind/tests/Ltest-trace.c5
-rw-r--r--src/pal/src/libunwind/tests/Ltest-varargs.c84
-rw-r--r--src/pal/src/libunwind/tests/Makefile.am234
-rw-r--r--src/pal/src/libunwind/tests/check-namespace.sh.in367
-rw-r--r--src/pal/src/libunwind/tests/crasher.c124
-rw-r--r--src/pal/src/libunwind/tests/flush-cache.S104
-rw-r--r--src/pal/src/libunwind/tests/flush-cache.h38
-rw-r--r--src/pal/src/libunwind/tests/forker.c76
-rw-r--r--src/pal/src/libunwind/tests/ia64-dyn-asm.S102
-rw-r--r--src/pal/src/libunwind/tests/ia64-test-dyn1.c223
-rw-r--r--src/pal/src/libunwind/tests/ia64-test-nat-asm.S508
-rw-r--r--src/pal/src/libunwind/tests/ia64-test-rbs-asm.S275
-rw-r--r--src/pal/src/libunwind/tests/ia64-test-rbs.h3
-rw-r--r--src/pal/src/libunwind/tests/ia64-test-readonly-asm.S55
-rw-r--r--src/pal/src/libunwind/tests/ia64-test-setjmp.c155
-rw-r--r--src/pal/src/libunwind/tests/ia64-test-sig.c102
-rw-r--r--src/pal/src/libunwind/tests/ia64-test-stack-asm.S183
-rw-r--r--src/pal/src/libunwind/tests/ia64-test-stack.h3
-rw-r--r--src/pal/src/libunwind/tests/ident.c5
-rw-r--r--src/pal/src/libunwind/tests/mapper.c78
-rwxr-xr-xsrc/pal/src/libunwind/tests/perf-startup19
-rw-r--r--src/pal/src/libunwind/tests/ppc64-test-altivec-utils.c32
-rw-r--r--src/pal/src/libunwind/tests/ppc64-test-altivec.c177
-rwxr-xr-xsrc/pal/src/libunwind/tests/run-check-namespace3
-rwxr-xr-xsrc/pal/src/libunwind/tests/run-coredump-unwind53
-rwxr-xr-xsrc/pal/src/libunwind/tests/run-coredump-unwind-mdi8
-rwxr-xr-xsrc/pal/src/libunwind/tests/run-ia64-test-dyn12
-rwxr-xr-xsrc/pal/src/libunwind/tests/run-ptrace-mapper2
-rwxr-xr-xsrc/pal/src/libunwind/tests/run-ptrace-misc2
-rw-r--r--src/pal/src/libunwind/tests/test-async-sig.c193
-rw-r--r--src/pal/src/libunwind/tests/test-coredump-unwind.c395
-rw-r--r--src/pal/src/libunwind/tests/test-flush-cache.c143
-rw-r--r--src/pal/src/libunwind/tests/test-init-remote.c103
-rw-r--r--src/pal/src/libunwind/tests/test-mem.c103
-rw-r--r--src/pal/src/libunwind/tests/test-proc-info.c171
-rw-r--r--src/pal/src/libunwind/tests/test-ptrace-misc.c120
-rw-r--r--src/pal/src/libunwind/tests/test-ptrace.c370
-rw-r--r--src/pal/src/libunwind/tests/test-reg-state.c133
-rw-r--r--src/pal/src/libunwind/tests/test-setjmp.c285
-rw-r--r--src/pal/src/libunwind/tests/test-static-link-gen.c74
-rw-r--r--src/pal/src/libunwind/tests/test-static-link-loc.c102
-rw-r--r--src/pal/src/libunwind/tests/test-strerror.c18
772 files changed, 78691 insertions, 0 deletions
diff --git a/src/pal/src/libunwind/.gitignore b/src/pal/src/libunwind/.gitignore
new file mode 100644
index 0000000000..7b7905f0d5
--- /dev/null
+++ b/src/pal/src/libunwind/.gitignore
@@ -0,0 +1,79 @@
+*.la
+*.a
+*.o
+*.lo
+*~
+*.pc
+
+.libs/
+.deps/
+
+.dirstamp
+Makefile
+Makefile.in
+
+INSTALL
+aclocal.m4
+autom4te.cache/
+config.log
+config.status
+config/
+configure
+libtool
+
+doc/common.tex
+
+src/[GL]cursor_i.h
+src/mk_[GL]cursor_i.s
+
+include/config.h
+include/config.h.in
+include/libunwind-common.h
+include/stamp-h1
+include/libunwind.h
+include/tdep/libunwind_i.h
+
+tests/[GL]test-bt
+tests/[GL]test-concurrent
+tests/[GL]test-dyn1
+tests/[GL]test-exc
+tests/[GL]test-init
+tests/[GL]test-resume-sig
+tests/[GL]test-resume-sig-rt
+tests/[GL]perf-simple
+tests/Ltest-nomalloc
+tests/Ltest-nocalloc
+tests/Lperf-simple
+tests/Lrs-race
+tests/Ltest-varargs
+tests/check-namespace.sh
+tests/crasher
+tests/forker
+tests/mapper
+tests/rs-race
+tests/test-async-sig
+tests/test-coredump-unwind
+tests/test-flush-cache
+tests/test-init-remote
+tests/test-mem
+tests/test-ptrace
+tests/test-setjmp
+tests/test-strerror
+tests/test-proc-info
+tests/test-ptrace-misc
+tests/test-reg-state
+tests/test-varargs
+tests/test-static-link
+tests/[GL]test-trace
+tests/[GL]perf-trace
+tests/Ltest-cxx-exceptions
+tests/Ltest-init-local-signal
+tests/Ltest-mem-validate
+tests/[GL]ia64-test-nat
+tests/[GL]ia64-test-rbs
+tests/[GL]ia64-test-readonly
+tests/[GL]ia64-test-stack
+tests/ia64-test-dyn1
+tests/ia64-test-sig
+tests/*.log
+tests/*.trs
diff --git a/src/pal/src/libunwind/.travis.yml b/src/pal/src/libunwind/.travis.yml
new file mode 100644
index 0000000000..4a74b4a1bc
--- /dev/null
+++ b/src/pal/src/libunwind/.travis.yml
@@ -0,0 +1,18 @@
+sudo: required
+language: c
+compiler: gcc
+env:
+- TARGET=x86_64-linux-gnu
+- TARGET=x86-linux-gnu
+- TARGET=arm-linux-gnueabihf
+- TARGET=aarch64-linux-gnu
+- TARGET=mipsel-unknown-linux-gnu
+# Currently experiencing build failures here
+#- TARGET=powerpc64-linux-gnu
+script:
+- ./autogen.sh
+- ./configure --target=$TARGET --host=$HOST
+- make -j32
+- sudo bash -c 'echo core.%p.%p > /proc/sys/kernel/core_pattern'
+- ulimit -c unlimited
+- if [ $TARGET == 'x86_64-linux-gnu' ]; then make check -j32; fi
diff --git a/src/pal/src/libunwind/AUTHORS b/src/pal/src/libunwind/AUTHORS
new file mode 100644
index 0000000000..719eee5c85
--- /dev/null
+++ b/src/pal/src/libunwind/AUTHORS
@@ -0,0 +1 @@
+David Mosberger <dmosberger@gmail.org>
diff --git a/src/pal/src/libunwind/CMakeLists.txt b/src/pal/src/libunwind/CMakeLists.txt
new file mode 100644
index 0000000000..b33c0ae443
--- /dev/null
+++ b/src/pal/src/libunwind/CMakeLists.txt
@@ -0,0 +1,22 @@
+add_subdirectory(src)
+
+# define variables for the configure_file below
+
+if (CLR_CMAKE_PLATFORM_ARCH_AMD64)
+ set(arch x86_64)
+elseif(CLR_CMAKE_PLATFORM_ARCH_ARM64)
+ set(arch aarch64)
+elseif(CLR_CMAKE_PLATFROM_ARCH_ARM)
+ set(arch arm)
+elseif(CLR_CMAKE_PLATFORM_ARCH_I386)
+ set(arch x86)
+endif()
+
+set(PKG_MAJOR "1")
+set(PKG_MINOR "3")
+set(PKG_EXTRA "-rc1")
+
+configure_file(include/libunwind-common.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/libunwind-common.h)
+configure_file(include/libunwind.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/libunwind.h)
+configure_file(include/tdep/libunwind_i.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/tdep/libunwind_i.h)
+
diff --git a/src/pal/src/libunwind/COPYING b/src/pal/src/libunwind/COPYING
new file mode 100644
index 0000000000..41e7d8a6fd
--- /dev/null
+++ b/src/pal/src/libunwind/COPYING
@@ -0,0 +1,20 @@
+Copyright (c) 2002 Hewlett-Packard Co.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/src/pal/src/libunwind/ChangeLog b/src/pal/src/libunwind/ChangeLog
new file mode 100644
index 0000000000..dfa24b957c
--- /dev/null
+++ b/src/pal/src/libunwind/ChangeLog
@@ -0,0 +1,55 @@
+***********************************************************
+
+ Discontinued. See git log instead at
+
+ http://www.kernel.org/git/gitweb.cgi?p=libs/libunwind/libunwind.git;a=log
+
+***********************************************************
+
+2002-11-08 David Mosberger-Tang <David.Mosberger@acm.org>
+
+ * src/ia64/unwind_i.h (ia64_getfp): Change from macro to inline
+ function. Check "loc" argument for being NULL before dereferencing it.
+ (ia64_putfp): Ditto.
+ (ia64_get): Ditto.
+ (ia64_put): Ditto.
+
+2002-01-18 David Mosberger-Tang <David.Mosberger@acm.org>
+
+ * src/ia64/parser.c (__ia64_unw_create_state_record): Set
+ IA64_FLAG_HAS_HANDLER if the unwind info descriptors indicate that
+ there a handler.
+
+ * src/ia64/regs.c (__ia64_access_reg): Return zero for UNW_REG_HANDLER
+ in frames that don't have a personality routine.
+
+ * src/ia64/unwind_i.h (IA64_FLAG_HAS_HANDLER): New flag.
+
+ * src/ia64/regs.c (__ia64_access_reg): When reading UNW_REG_HANDLER,
+ account for the fact that the personality address is gp-relative.
+
+ * src/ia64/parser.c (__ia64_unw_create_state_record): Fix
+ initialization of segbase and len.
+
+2002-01-17 David Mosberger-Tang <David.Mosberger@acm.org>
+
+ * include/unwind-ia64.h: Include via "unwind.h" to ensure
+ the file is picked up from same directory.
+
+2002-01-16 David Mosberger-Tang <David.Mosberger@acm.org>
+
+ * include/unwind.h: Define UNW_ESTOPUNWIND. This error code may
+ be returned by acquire_unwind_info() to force termination of
+ unwinding. An application may want to do this when encountering a
+ call frame for dynamically generated code, for example.
+
+ * unwind.h: Pass opaque argument pointer to acquire_unwind_info()
+ and release_unwind_info() like we do for access_mem() etc.
+
+2002-01-14 David Mosberger-Tang <David.Mosberger@acm.org>
+
+ * Version 0.0 released.
+
+2002-01-11 David Mosberger-Tang <David.Mosberger@acm.org>
+
+ * ChangeLog created.
diff --git a/src/pal/src/libunwind/LICENSE b/src/pal/src/libunwind/LICENSE
new file mode 100644
index 0000000000..c9b44cb8aa
--- /dev/null
+++ b/src/pal/src/libunwind/LICENSE
@@ -0,0 +1,18 @@
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/src/pal/src/libunwind/Makefile.am b/src/pal/src/libunwind/Makefile.am
new file mode 100644
index 0000000000..711d9100c7
--- /dev/null
+++ b/src/pal/src/libunwind/Makefile.am
@@ -0,0 +1,106 @@
+include_HEADERS = include/libunwind-dynamic.h
+
+if BUILD_PTRACE
+include_HEADERS += include/libunwind-ptrace.h
+endif BUILD_PTRACE
+
+if BUILD_COREDUMP
+include_HEADERS += include/libunwind-coredump.h
+endif BUILD_COREDUMP
+
+if ARCH_AARCH64
+include_HEADERS += include/libunwind-aarch64.h
+endif
+if ARCH_ARM
+include_HEADERS += include/libunwind-arm.h
+endif
+if ARCH_IA64
+include_HEADERS += include/libunwind-ia64.h
+endif
+if ARCH_HPPA
+include_HEADERS += include/libunwind-hppa.h
+endif
+if ARCH_MIPS
+include_HEADERS += include/libunwind-mips.h
+endif
+if ARCH_TILEGX
+include_HEADERS += include/libunwind-tilegx.h
+endif
+if ARCH_X86
+include_HEADERS += include/libunwind-x86.h
+endif
+if ARCH_X86_64
+include_HEADERS += include/libunwind-x86_64.h
+endif
+if ARCH_PPC32
+include_HEADERS += include/libunwind-ppc32.h
+endif
+if ARCH_PPC64
+include_HEADERS += include/libunwind-ppc64.h
+endif
+if ARCH_SH
+include_HEADERS += include/libunwind-sh.h
+endif
+
+if !REMOTE_ONLY
+include_HEADERS += include/libunwind.h include/unwind.h
+endif
+
+nodist_include_HEADERS = include/libunwind-common.h
+
+SUBDIRS = src
+
+if CONFIG_TESTS
+SUBDIRS += tests
+endif
+
+if CONFIG_DOCS
+SUBDIRS += doc
+endif
+
+noinst_HEADERS = include/dwarf.h include/dwarf_i.h include/dwarf-eh.h \
+ include/compiler.h include/libunwind_i.h include/mempool.h \
+ include/remote.h \
+ include/tdep-aarch64/dwarf-config.h \
+ include/tdep-aarch64/jmpbuf.h \
+ include/tdep-aarch64/libunwind_i.h \
+ include/tdep-arm/dwarf-config.h include/tdep-arm/ex_tables.h \
+ include/tdep-arm/jmpbuf.h include/tdep-arm/libunwind_i.h \
+ include/tdep-ia64/jmpbuf.h include/tdep-ia64/rse.h \
+ include/tdep-ia64/libunwind_i.h include/tdep-ia64/script.h \
+ include/tdep-hppa/libunwind_i.h \
+ include/tdep-hppa/jmpbuf.h include/tdep-hppa/dwarf-config.h \
+ include/tdep-mips/libunwind_i.h \
+ include/tdep-mips/jmpbuf.h include/tdep-mips/dwarf-config.h \
+ include/tdep-tilegx/libunwind_i.h \
+ include/tdep-tilegx/jmpbuf.h include/tdep-tilegx/dwarf-config.h \
+ include/tdep-x86/libunwind_i.h \
+ include/tdep-x86/jmpbuf.h include/tdep-x86/dwarf-config.h \
+ include/tdep-x86_64/libunwind_i.h \
+ include/tdep-x86_64/jmpbuf.h include/tdep-x86_64/dwarf-config.h \
+ include/tdep-ppc32/dwarf-config.h \
+ include/tdep-ppc32/jmpbuf.h include/tdep-ppc32/libunwind_i.h \
+ include/tdep-ppc64/dwarf-config.h \
+ include/tdep-ppc64/jmpbuf.h include/tdep-ppc64/libunwind_i.h \
+ include/tdep-sh/dwarf-config.h \
+ include/tdep-sh/jmpbuf.h include/tdep-sh/libunwind_i.h \
+ include/tdep/libunwind_i.h \
+ include/tdep/jmpbuf.h include/tdep/dwarf-config.h
+
+EXTRA_DIST = include/libunwind-common.h.in
+
+MAINTAINERCLEANFILES = \
+ Makefile.in \
+ INSTALL \
+ aclocal.m4 \
+ configure \
+ config/compile \
+ config/config.guess \
+ config/config.sub \
+ config/depcomp \
+ config/install-sh \
+ config/ltmain.sh \
+ config/missing \
+ include/config.h.in \
+ include/config.h.in~
+
diff --git a/src/pal/src/libunwind/NEWS b/src/pal/src/libunwind/NEWS
new file mode 100644
index 0000000000..ae6cbcfb0b
--- /dev/null
+++ b/src/pal/src/libunwind/NEWS
@@ -0,0 +1,247 @@
+-*-Mode: outline-*-
+
+* News for v1.3:
+
+** Iteration of unwind register states support
+ Doug Moore <dougm@rice.edu>
+** Freebsd/Armv6 support
+ Konstantin Belousov <kib@freebsd.org>
+** Many, many dwarf bugfixes
+** Mips remote unwind support
+** aarch64 ptrace support
+
+* News for v1.2:
+
+** aarch64 port
+** dwarf parsing improvements
+** Fast stacktraces for aarch64 & arm
+** tilegx port
+** powerpc64 port
+
+* News for v1.1:
+
+** coredump unwind support
+** New arch: SuperH
+** Improved support for PowerPC, ARM
+** Lots of cleanups, perf tweaks
+** pkg-config support
+
+* News for v1.0:
+
+** Fast unwind (rbp, rsp, rip only) on x86_64 with a fallback to
+ slow code path (Lassi Tuura)
+** Improved local and remote unwinding on ARM (Ken Werner)
+** Testing, stability and many fixes on x86 (Paul Pluzhnikov)
+** FreeBSD port and clean separation of OS specific bits
+ (Konstantin Belousov)
+** Thanks for all the bug reports, contributions and testing!
+
+* News for v0.99:
+
+** Greatly improved x86-64 support thanks to Arun Sharma.
+** Support for PPC64 added by Jose Flavio Aguilar Paulino.
+
+* News for v0.98.6:
+
+** Fix address-leak triggered by invalid byte-order. Fixed by Andreas Schwab.
+** On ia64, get_static_proc_name() no longer uses a weak reference to
+ _Uelf64_get_proc_name(), since that was causing problems with archive
+ libraries and no longer served any apparent purpose. Fixed by
+ Curt Wohlgemuth.
+
+* News for v0.98.5:
+
+** Fix a typo in the man-page of unw_create_addr_space().
+** Fix an off-by-1 bug in the handling of the dynamic ALIAS directive
+ for ia64. Reported by Todd L. Miller.
+** Fix a bug in libunwind-ptrace which could cause crash due to extraneous
+ munmap() calls.
+
+* News for v0.98.4:
+
+** Fix a typo in _ReadSLEB.c which caused hangs when throwing exceptions
+ from Intel ICC-compiled programs. Reported by Tommy Hoffner.
+
+* News for v0.98.3:
+
+** Make it possible to link against libunwind-ia64.a only (i.e., without
+ requiring libunwind.a as well). This keeps apps which need only
+ remote unwinding cleaner, since they logically have no dependency
+ on libunwind.a.
+** Dont link against libatomic_ops for now. Due to a packaging bug on
+ Debian, linking against this library causes libunwind.so to get
+ a dependency on libatomic_ops.so, which is not at all what we want.
+ Fortunately, we don't have to link against that library on x86 or
+ ia64 since the library is strictly needed only for platforms with
+ poor atomic operation support. Once the libatomic_ops package is fixed,
+ we can re-enable linking against libatomic_ops.
+
+* News for v0.98.2:
+
+** Fixed bug which caused _UPT_get_dyn_info_list_addr() to sometimes fail
+ needlessly. Found by Todd L. Miller.
+
+** When using GCC to build libunwind on ia64, libunwind.so had an
+ unresolved reference to __divdi3. This is undesirable since it
+ creates an implicit dependency on libgcc. This problem has been
+ fixed in the 0.98.2 release by explicitly linking against libgcc.a
+ when building libunwind.
+
+* News for v0.98.1:
+
+** Fixed a bug which caused "make install" to install libunwind-common.h.in
+ instead of libunwind-common.h.
+** Fixed a bug in the ia64 {sig,}longjmp() which showed on
+ SuSE Linux 9 because it's using a newer compiler & the EPC-based system
+ call stubs.
+** Fixed incorrect offsets in tests/ia64-test-nat-asm.S.
+ Warning: you'll need a GNU assembler dated later than 21-Sep-2004 to
+ get this file translated correctly. With an old assembler, "make check"
+ will get lots of failures when running Gia64-test-nat or Lia64-test-nat!
+** Convert tests/bt into a full-blown test-case. It's designed to
+ trigger a (rarely-encountered) bug in the GNU assembler on ia64.
+ The assembler has been fixed and once the libraries (libc etc)
+ have been rebuilt, this test will pass.
+** Added test-case tests/run-ptrace-misc which, on ia64, triggers a bug in
+ current GCC (including v3.4.2) which causes bad unwind info.
+
+* News for v0.98:
+
+** Update libunwind to be compliant with the updated/expanded
+ ia64 unwind specificiation by HJ Lu [1]. This is needed for
+ GCC 3.4 compatibility.
+
+ [1] http://www.kernel.org/pub/linux/devel/gcc/unwind/
+
+** Initial support for x86-64 has been added courtesy of Max Asbock.
+ Along with this came a bunch of DWARF2 unwinder fixes.
+
+** A new rountine unw_strerror() has been added courtesy of
+ Thomas Hallgren.
+
+** Including <libunwind.h> now defines 4 macros that can be used
+ to determine the version number of libunwind. Specifically,
+ UNW_VERSION_MAJOR, UNW_VERSION_MINOR, UNW_VERSION, and
+ UNW_VERSION_CODE are defined by the header now.
+
+** Bug fixes
+*** Fix a memory-leak in _UPT_get_dyn_info_list_addr() courtesy of Ed Connell.
+*** Fix a crash in libunwind-ptrace courtesy of Mark Young.
+*** Fix a bug in ia64-version of unw_init_remote() which prevented
+ it from working correctly for the local address space. Reported by
+ Troy Heber.
+*** Many other small and not so small fixes.
+
+* News for v0.97:
+
+** unw_get_proc_name() may now be called from signal-handler.
+
+** The ptrace-helper routines are now declared in libunwind-ptrace.h.
+ Applications which use ptrace-based unwinding should include
+ <libunwind-ptrace.h> to get the _UPT_*() routines declared.
+
+** libunwind has been split into a "local-only" and a "generic" versions.
+ The former is optimized for local unwinding (within a process) and
+ is called libunwind.so (shared version) or libunwind.a (archive
+ version). The generic version is not limited to unwinding within a
+ process and is called libunwind-generic.so (shared version)
+ libunwind-generic.a (archive version). Similarly, the ptrace()
+ support has been separated out into a convenience library called
+ libunwind-ptrace.a. For the most part, backwards-compatibility
+ is retained. However, when building an application which uses
+ libunwind, it may be necessary to change the linker command-line
+ as shown in the table below:
+
+ Application which does: Before v0.97: With v0.97:
+ ----------------------- ------------- -----------
+ local unwinding only: -lunwind -lunwind
+ remote unwinding: -lunwind -lunwind-generic
+ cross unwinding: -lunwind-PLAT -lunwind-PLAT
+ ptrace-based unwinding: -lunwind -lunwind-ptrace -lunwind-generic
+
+ The motivation for this splitting is to keep libunwind.so as minimal
+ as possible. This library will eventually be loaded by most (if not
+ all) executables and hence it is important to ensure that it can
+ be loaded as quickly as possible.
+
+** unw_getcontext() tuned on IA-64.
+
+ The unw_getcontext() routine used to be provided by (GNU) libc
+ (getcontext()). This caused unnecessary overhead (e.g., an
+ unnecessary system-call to sigprocmask()). The new
+ unw_getcontext() only does the work really needed for libunwind and
+ hence performs much better. However, this change implies that
+ programs linked against libunwind v0.97 won't be
+ backwards-compatible with earlier versions (there would be an
+ unresolved symbol for _Uia64_getcontext()).
+
+** Fix NaT-bit handling on IA-64.
+
+ New test-cases have been added to test the handling of the NaT bit
+ (and floating-point NaT values) and all discovered/known bugs have
+ been fixed.
+
+** Initial DWARF-based unwinder for x86.
+
+ There is a beginning for a DWARF-based unwinder for x86. Work for
+ x86-64-support based on this DWARF unwinder is currently underway
+ at IBM and it is expected that this support will be merged into the
+ official tree soon.
+
+
+* News for v0.96:
+
+** _Unwind_*() routines defined by the C++ ABI are now included in
+ libunwind.
+
+
+* News for v0.95:
+
+** Bigger, better, faster, or so the theory goes.
+
+
+* News for v0.93:
+
+** More bug-fixes & improved HP-UX support.
+
+
+* News for v0.92:
+
+** Bug-fix release. IA-64 unwinder can now be built with Intel compiler (ECC).
+
+
+* News for v0.91:
+
+** Lots of documentation updates
+** Some portability fixes.
+
+
+* News for v0.9:
+
+** The libunwind API is mostly feature-complete at this point (hence the
+ version jump from v0.2 to v0.9).
+
+
+* News for v0.2:
+
+** Automated configuration/build with autoconf and automake.
+** Added support for building libunwind as a shared library.
+** Added support for remote unwinding.
+** Added support for cross-building.
+** Added two new routines to the API:
+ - unw_is_fpreg()
+ - unw_get_save_loc()
+** Added multi-architecture supports (lets a single application use
+ the unwind libraries for multiple target architectures; this is useful,
+ e.g., useful for building a debugger that can support multiple targets
+ such as x86, ia64, etc.)
+
+
+* News for v0.1:
+
+** Added support for exception handling.
+
+
+* News for v0.0:
+
+** It's a brand new package.
diff --git a/src/pal/src/libunwind/README b/src/pal/src/libunwind/README
new file mode 100644
index 0000000000..694f600b06
--- /dev/null
+++ b/src/pal/src/libunwind/README
@@ -0,0 +1,207 @@
+-*- mode: Outline -*-
+
+[![Build Status](https://travis-ci.org/libunwind/libunwind.svg?branch=master)](https://travis-ci.org/libunwind/libunwind)
+
+This is version 1.3 of the unwind library. This library supports
+several architecture/operating-system combinations:
+
+ Linux/x86-64: Works well.
+ Linux/x86: Works well.
+ Linux/ARM: Works well.
+ Linux/IA-64: Works well.
+ Linux/PARISC: Works well, but C library missing unwind-info.
+ HP-UX/IA-64: Mostly works but known to have some serious limitations.
+ MIPS: Newly added.
+ Linux/AArch64: Works well.
+ Linux/PPC64: Newly added.
+ Linux/SuperH: Newly added.
+ FreeBSD/i386: Works well.
+ FreeBSD/x86-64: Newly added (FreeBSD architecture is known as amd64).
+ Linux/Tilegx: Newly added (64-bit mode only).
+
+* General Build Instructions
+
+In general, this library can be built and installed with the following
+commands:
+
+ $ ./autogen.sh # Needed only for building from git. Depends on libtool.
+ $ ./configure
+ $ make
+ $ make install prefix=PREFIX
+
+where PREFIX is the installation prefix. By default, a prefix of
+/usr/local is used, such that libunwind.a is installed in
+/usr/local/lib and unwind.h is installed in /usr/local/include. For
+testing, you may want to use a prefix of /usr/local instead.
+
+
+* Building with Intel compiler
+
+** Version 8 and later
+
+Starting with version 8, the preferred name for the IA-64 Intel
+compiler is "icc" (same name as on x86). Thus, the configure-line
+should look like this:
+
+ $ ./configure CC=icc CFLAGS="-g -O3 -ip" CXX=icc CCAS=gcc CCASFLAGS=-g \
+ LDFLAGS="-L$PWD/src/.libs"
+
+
+* Building on HP-UX
+
+For the time being, libunwind must be built with GCC on HP-UX.
+
+libunwind should be configured and installed on HP-UX like this:
+
+ $ ./configure CFLAGS="-g -O2 -mlp64" CXXFLAGS="-g -O2 -mlp64"
+
+Caveat: Unwinding of 32-bit (ILP32) binaries is not supported
+ at the moment.
+
+** Workaround for older versions of GCC
+
+GCC v3.0 and GCC v3.2 ship with a bad version of sys/types.h. The
+workaround is to issue the following commands before running
+"configure":
+
+ $ mkdir $top_dir/include/sys
+ $ cp /usr/include/sys/types.h $top_dir/include/sys
+
+GCC v3.3.2 or later have been fixed and do not require this
+workaround.
+
+* Building for PowerPC64 / Linux
+
+For building for power64 you should use:
+
+ $ ./configure CFLAGS="-g -O2 -m64" CXXFLAGS="-g -O2 -m64"
+
+If your power support altivec registers:
+ $ ./configure CFLAGS="-g -O2 -m64 -maltivec" CXXFLAGS="-g -O2 -m64 -maltivec"
+
+To check if your processor has support for vector registers (altivec):
+ cat /proc/cpuinfo | grep altivec
+and should have something like this:
+ cpu : PPC970, altivec supported
+
+If libunwind seems to not work (backtracing failing), try to compile
+it with -O0, without optimizations. There are some compiler problems
+depending on the version of your gcc.
+
+* Building on FreeBSD
+
+General building instructions apply. To build and execute several tests,
+you need libexecinfo library available in ports as devel/libexecinfo.
+
+Development of the port was done of FreeBSD 8.0-STABLE. The library
+was build with the system compiler that is modified version of gcc 4.2.1,
+as well as the gcc 4.4.3.
+
+* Regression Testing
+
+After building the library, you can run a set of regression tests with:
+
+ $ make check
+
+** Expected results on IA-64 Linux
+
+Unless you have a very recent C library and compiler installed, it is
+currently expected to have the following tests fail on IA-64 Linux:
+
+ Gtest-init (should pass starting with glibc-2.3.x/gcc-3.4)
+ Ltest-init (should pass starting with glibc-2.3.x/gcc-3.4)
+ test-ptrace (should pass starting with glibc-2.3.x/gcc-3.4)
+ run-ia64-test-dyn1 (should pass starting with glibc-2.3.x)
+
+This does not mean that libunwind cannot be used with older compilers
+or C libraries, it just means that for certain corner cases, unwinding
+will fail. Since they're corner cases, it is not likely for
+applications to trigger them.
+
+Note: If you get lots of errors in Gia64-test-nat and Lia64-test-nat, it's
+ almost certainly a sign of an old assembler. The GNU assembler used
+ to encode previous-stack-pointer-relative offsets incorrectly.
+ This bug was fixed on 21-Sep-2004 so any later assembler will be
+ fine.
+
+** Expected results on x86 Linux
+
+The following tests are expected to fail on x86 Linux:
+
+ test-ptrace
+
+** Expected results on x86-64 Linux
+
+The following tests are expected to fail on x86-64 Linux:
+
+ run-ptrace-misc (see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18748
+ and http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18749)
+
+** Expected results on PARISC Linux
+
+Caveat: GCC v3.4 or newer is needed on PA-RISC Linux. Earlier
+versions of the compiler failed to generate the exception-handling
+program header (GNU_EH_FRAME) needed for unwinding.
+
+The following tests are expected to fail on x86-64 Linux:
+
+ Gtest-bt (backtrace truncated at kill() due to lack of unwind-info)
+ Ltest-bt (likewise)
+ Gtest-resume-sig (Gresume.c:my_rt_sigreturn() is wrong somehow)
+ Ltest-resume-sig (likewise)
+ Gtest-init (likewise)
+ Ltest-init (likewise)
+ Gtest-dyn1 (no dynamic unwind info support yet)
+ Ltest-dyn1 (no dynamic unwind info support yet)
+ test-setjmp (longjmp() not implemented yet)
+ run-check-namespace (toolchain doesn't support HIDDEN yet)
+
+** Expected results on HP-UX
+
+"make check" is currently unsupported for HP-UX. You can try to run
+it, but most tests will fail (and some may fail to terminate). The
+only test programs that are known to work at this time are:
+
+ tests/bt
+ tests/Gperf-simple
+ tests/test-proc-info
+ tests/test-static-link
+ tests/Gtest-init
+ tests/Ltest-init
+ tests/Gtest-resume-sig
+ tests/Ltest-resume-sig
+
+** Expected results on PPC64 Linux
+
+"make check" should run with no more than 10 out of 24 tests failed.
+
+
+* Performance Testing
+
+This distribution includes a few simple performance tests which give
+some idea of the basic cost of various libunwind operations. After
+building the library, you can run these tests with the following
+commands:
+
+ $ cd tests
+ $ make perf
+
+* Contacting the Developers
+
+Please direct all questions regarding this library to:
+
+ libunwind-devel@nongnu.org
+
+You can do this by sending a mail to libunwind-request@nongnu.org with
+a body of:
+
+ subscribe libunwind-devel
+
+or you can subscribe and manage your subscription via the
+web-interface at:
+
+ https://savannah.nongnu.org/mail/?group=libunwind
+
+Or interact at the gihub page:
+
+ https://github.com/libunwind/libunwind
diff --git a/src/pal/src/libunwind/README.md b/src/pal/src/libunwind/README.md
new file mode 120000
index 0000000000..100b93820a
--- /dev/null
+++ b/src/pal/src/libunwind/README.md
@@ -0,0 +1 @@
+README \ No newline at end of file
diff --git a/src/pal/src/libunwind/TODO b/src/pal/src/libunwind/TODO
new file mode 100644
index 0000000000..8b2e0262b0
--- /dev/null
+++ b/src/pal/src/libunwind/TODO
@@ -0,0 +1,97 @@
+- Update the libunwind man page for the new/fixed cache-flushing behavior.
+ Effectively, that unw_flush_cache() doesn't have to be called by
+ applications except for extraordinary circumstances (e.g., if application
+ implements its own runtime loader).
+- document split local-only/generic libraries and separate libunwind-ptrace.a
+ convenience-library
+- document new "tdep" member in unw_proc_info_t structure
+- for DWARF 2, use a dummy CIE entry with an augmentation that
+ provides the dyn-info-list-address
+
+=== taken care of:
+
+Testing:
+ + ensure that saving r4-r7 in a stacked register properly preserves
+ the NaT bit, even in the face of register-rotation
+ + ensure that IA64_INSN_MOVE_STACKED works correctly in the face of
+ register rotation
+ + on Linux, test access to f32-f127 in a signal handler (e.g., verify
+ that fph partition gets initialized properly)
++ According to Nicholas S. Wourms <nwourms@netscape.net>, adding this to the
+ Makefile.am:
+ AUTOMAKE_OPTIONS = 1.6 subdir-objects
+ ensures that object-files are build in separate subdirectories and that
+ in turn makes it possible for source files in different directories to
+ have the same filename, thus avoiding the need for those ugly -x86, -ia64,
+ etc., postfixes.
++ Switch ia64 (and rest over) to using Debug() instead of debug()
++ implement non-local versions of dwarf_readXX()
++ consolidate mostly architecture-independent code such as
+ unw_get_accessors() into shared files
++ caching is pretty fundamentally broken, what should happen is this:
+ o On unw_init_local()/unw_init_remote(), libunwind should validate
+ that the cached information is still valid and, if not, flush the
+ cache on its own. Rationale: once unw_init_local() has been
+ called, it is clear that the unwind info for the calling thread
+ cannot change (otherwise the program would be buggy anyhow) and
+ hence it is sufficient to validate the cache at this point.
+ Similarly, once unw_init_remote() has been called, the target
+ address space must have been stopped, because the unwinding would
+ otherwise be unreliable anyhow.
+ o glibc currently lacks a feature for dl_iterate_phdr() to support
+ safe caching; I proposed on 12/16/2003 that glibc maintain two
+ atomic counters which get inremented whenever something is added
+ to/removed from the dl_iterate_phdr-list. Once we have such counters,
+ we can use them in libunwind to implement an efficient version of a
+ cache-validation routine.
+ Once this has been fixed, update the libunwind man page accordingly.
+ Effectively, what this means is that unw_flush_cache() doesn't have
+ to be called by applications except for extraordinary circumstances
+ (e.g., if application implements its own runtime loader).
++ man-page for unw_is_fpreg()
++ man-page for _U_dyn_cancel()
++ man-page for _U_dyn_register()
++ global data is not protected by a lock; causes problems if two threads
+ call ia64_init() at almost the same time
++ cache the value of *cfm_loc; each rotate_FOO() call needs it!
++ implement the remote-lookup of the dynamic registration list
++ when doing sigreturn, must restore fp regs (and perhaps other regs) the same
+ way as the (user-level) gate.S sigreturn path does!
++ unw_resume() must at least restore gp (r1)! consider restoring all
+ scratch regs (but what's the performance impact on exception handling?);
+ alternative: restore scratch regs that may be used during procedure
+ call/return (e.g., r8-r11, f8-f11)
++ implement unw_resume() for the case where the current register frame is split
+ across multiple backing stores
++ document restricions on using unw_resume():
++ implement remote cases of unw_resume()
++ test both with UNW_LOCAL_ONLY and without where this makes sense
++ allow region-length (insn_count) in unw_dyn_region_info_t to be negative
+ to indicate counting from the end of the procedure (to make it possible
+ for differently-sized procedures to share the same region list if they
+ share the same prologue/epilogue).
++ it appears that it is currently not possible to read register UNW_IA64_TP;
+ fix that => no, attempts to access r13 will result in access_reg() callbacks,
+ as desired; for local-case, access to r13 will fail though (since
+ getcontext() doesn't, and shouldn't, capture r13)
++ document the special nature of UNW_IA64_GP: read-only, but adjusted
+ automatically if the IP is changed
++ use pthread-mutexes where necessary, atomic ops where possible
++ man-page for unw_init_local()
++ man-page for unw_init_remote()
++ man-page for unw_create_addr_space()
++ man-page for unw_destroy_addr_space()
++ man-page for unw_get_proc_info()
++ man-page for unw_get_proc_name()
++ man-page for unw_get_accessors()
++ man-page for unw_regname()
++ man-page for unw_flush_cache()
++ man-page for unw_set_caching_policy()
++ man-page for unw_getcontext()
++ man-page for unw_is_signal_frame()
++ man-page for unw_step()
++ man-page for unw_get_reg()
++ man-page for unw_set_reg()
++ man-page for unw_get_fpreg()
++ man-page for unw_set_fpreg()
++ test with Intel compiler
diff --git a/src/pal/src/libunwind/acinclude.m4 b/src/pal/src/libunwind/acinclude.m4
new file mode 100644
index 0000000000..497f7c2f21
--- /dev/null
+++ b/src/pal/src/libunwind/acinclude.m4
@@ -0,0 +1,32 @@
+AC_DEFUN([LIBUNWIND___THREAD],
+[dnl Check whether the compiler supports the __thread keyword.
+if test "x$enable___thread" != xno; then
+ AC_CACHE_CHECK([for __thread], libc_cv_gcc___thread,
+ [cat > conftest.c <<\EOF
+ __thread int a = 42;
+EOF
+ if AC_TRY_COMMAND([${CC-cc} $CFLAGS -c conftest.c >&AS_MESSAGE_LOG_FD]); then
+ libc_cv_gcc___thread=yes
+ else
+ libc_cv_gcc___thread=no
+ fi
+ rm -f conftest*])
+ if test "$libc_cv_gcc___thread" = yes; then
+ AC_DEFINE(HAVE___THREAD, 1,
+ [Define to 1 if __thread keyword is supported by the C compiler.])
+ fi
+else
+ libc_cv_gcc___thread=no
+fi])
+
+AC_DEFUN([CHECK_ATOMIC_OPS],
+[dnl Check whether the system has the atomic_ops package installed.
+ AC_CHECK_HEADERS(atomic_ops.h)
+#
+# Don't link against libatomic_ops for now. We don't want libunwind
+# to depend on libatomic_ops.so. Fortunately, none of the platforms
+# we care about so far need libatomic_ops.a (everything is done via
+# inline macros).
+#
+# AC_CHECK_LIB(atomic_ops, main)
+])
diff --git a/src/pal/src/libunwind/autogen.sh b/src/pal/src/libunwind/autogen.sh
new file mode 100755
index 0000000000..b08bc831f6
--- /dev/null
+++ b/src/pal/src/libunwind/autogen.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+test -n "$srcdir" || srcdir=`dirname "$0"`
+test -n "$srcdir" || srcdir=.
+(
+ cd "$srcdir" &&
+ autoreconf --force -v --install
+) || exit
+test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"
diff --git a/src/pal/src/libunwind/aux_/config.guess b/src/pal/src/libunwind/aux_/config.guess
new file mode 100644
index 0000000000..ed2e03b7f2
--- /dev/null
+++ b/src/pal/src/libunwind/aux_/config.guess
@@ -0,0 +1,1321 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002 Free Software Foundation, Inc.
+
+timestamp='2002-03-20'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+
+dummy=dummy-$$
+trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script.
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int dummy(){}" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ;
+ if test $? = 0 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ rm -f $dummy.c $dummy.o $dummy.rel ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvmeppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ pmax:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mipseb-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ wgrisc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ alpha:OSF1:*:*)
+ if test $UNAME_RELEASE = "V4.0"; then
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ fi
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ cat <<EOF >$dummy.s
+ .data
+\$Lformat:
+ .byte 37,100,45,37,120,10,0 # "%d-%x\n"
+
+ .text
+ .globl main
+ .align 4
+ .ent main
+main:
+ .frame \$30,16,\$26,0
+ ldgp \$29,0(\$27)
+ .prologue 1
+ .long 0x47e03d80 # implver \$0
+ lda \$2,-1
+ .long 0x47e20c21 # amask \$2,\$1
+ lda \$16,\$Lformat
+ mov \$0,\$17
+ not \$1,\$18
+ jsr \$26,printf
+ ldgp \$29,0(\$26)
+ mov 0,\$16
+ jsr \$26,exit
+ .end main
+EOF
+ eval $set_cc_for_build
+ $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ case `./$dummy` in
+ 0-0)
+ UNAME_MACHINE="alpha"
+ ;;
+ 1-0)
+ UNAME_MACHINE="alphaev5"
+ ;;
+ 1-1)
+ UNAME_MACHINE="alphaev56"
+ ;;
+ 1-101)
+ UNAME_MACHINE="alphapca56"
+ ;;
+ 2-303)
+ UNAME_MACHINE="alphaev6"
+ ;;
+ 2-307)
+ UNAME_MACHINE="alphaev67"
+ ;;
+ 2-1307)
+ UNAME_MACHINE="alphaev68"
+ ;;
+ esac
+ fi
+ rm -f $dummy.s $dummy
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit 0;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit 0 ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit 0 ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy \
+ && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && rm -f $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy`
+ if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
+ rm -f $dummy.c $dummy
+ fi ;;
+ esac
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3D:*:*:*)
+ echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit 0 ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit 0 ;;
+ x86:Interix*:3*)
+ echo i386-pc-interix3
+ exit 0 ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i386-pc-interix
+ exit 0 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit 0 ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ rm -f $dummy.c
+ test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0
+ ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit 0 ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit 0 ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit 0 ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit 0 ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit 0 ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit 0 ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit 0 ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit 0 ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit 0 ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit 0 ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ rm -f $dummy.c
+ test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+ test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit 0 ;;
+ i*86:*:5:[78]*)
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit 0 ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit 0 ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ M68*:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Darwin:*:*)
+ echo `uname -p`-apple-darwin${UNAME_RELEASE}
+ exit 0 ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit 0 ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit 0 ;;
+ NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit 0 ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit 0 ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit 0 ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit 0 ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit 0 ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit 0 ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit 0 ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit 0 ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit 0 ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit 0 ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit 0 ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit 0 ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0
+rm -f $dummy.c $dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/src/pal/src/libunwind/aux_/config.sub b/src/pal/src/libunwind/aux_/config.sub
new file mode 100644
index 0000000000..f3657978c7
--- /dev/null
+++ b/src/pal/src/libunwind/aux_/config.sub
@@ -0,0 +1,1443 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002 Free Software Foundation, Inc.
+
+timestamp='2002-03-07'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit 0;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | c4x | clipper \
+ | d10v | d30v | dsp16xx \
+ | fr30 \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | m32r | m68000 | m68k | m88k | mcore \
+ | mips | mips16 | mips64 | mips64el | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el | mips64vr4300 \
+ | mips64vr4300el | mips64vr5000 | mips64vr5000el \
+ | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \
+ | mipsisa32 | mipsisa64 \
+ | mn10200 | mn10300 \
+ | ns16k | ns32k \
+ | openrisc | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[34] | sh[34]eb | shbe | shle | sh64 \
+ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armv*-* \
+ | avr-* \
+ | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c54x-* \
+ | clipper-* | cydra-* \
+ | d10v-* | d30v-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | m32r-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | mcore-* \
+ | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \
+ | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \
+ | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* | sh64-* \
+ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+ | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ mmix*)
+ basic_machine=mmix-knuth
+ os=-mmixware
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ or32 | or32-*)
+ basic_machine=or32-unknown
+ os=-coff
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2)
+ basic_machine=i686-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3d)
+ basic_machine=alpha-cray
+ os=-unicos
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ windows32)
+ basic_machine=i386-pc
+ os=-windows32-msvcrt
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh3 | sh4 | sh3eb | sh4eb)
+ basic_machine=sh-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparc | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ c4x*)
+ basic_machine=c4x-none
+ os=-coff
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto*)
+ os=-nto-qnx
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -vxsim* | -vxworks*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/src/pal/src/libunwind/aux_/ltmain.sh b/src/pal/src/libunwind/aux_/ltmain.sh
new file mode 100644
index 0000000000..6fc690018e
--- /dev/null
+++ b/src/pal/src/libunwind/aux_/ltmain.sh
@@ -0,0 +1,5107 @@
+# ltmain.sh - Provide generalized library-building support services.
+# NOTE: Changing this file will not affect anything until you rerun configure.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Check that we have a working $echo.
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell, and then maybe $echo will work.
+ exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit 0
+fi
+
+# The name of this program.
+progname=`$echo "$0" | ${SED} 's%^.*/%%'`
+modename="$progname"
+
+# Constants.
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.4.3
+TIMESTAMP=" (1.922.2.111 2002/10/23 02:54:36)"
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+# test EBCDIC or ASCII
+case `echo A|od -x` in
+ *[Cc]1*) # EBCDIC based system
+ SP2NL="tr '\100' '\n'"
+ NL2SP="tr '\r\n' '\100\100'"
+ ;;
+ *) # Assume ASCII based system
+ SP2NL="tr '\040' '\012'"
+ NL2SP="tr '\015\012' '\040\040'"
+ ;;
+esac
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+# We save the old values to restore during execute mode.
+if test "${LC_ALL+set}" = set; then
+ save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
+fi
+if test "${LANG+set}" = set; then
+ save_LANG="$LANG"; LANG=C; export LANG
+fi
+
+# Make sure IFS has a sensible default
+: ${IFS=" "}
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+ echo "$modename: not configured to build any kind of library" 1>&2
+ echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+
+# Parse our command line options once, thoroughly.
+while test $# -gt 0
+do
+ arg="$1"
+ shift
+
+ case $arg in
+ -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case $prev in
+ execute_dlfiles)
+ execute_dlfiles="$execute_dlfiles $arg"
+ ;;
+ *)
+ eval "$prev=\$arg"
+ ;;
+ esac
+
+ prev=
+ prevopt=
+ continue
+ fi
+
+ # Have we seen a non-optional argument yet?
+ case $arg in
+ --help)
+ show_help=yes
+ ;;
+
+ --version)
+ echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
+ exit 0
+ ;;
+
+ --config)
+ ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0
+ exit 0
+ ;;
+
+ --debug)
+ echo "$progname: enabling shell trace mode"
+ set -x
+ ;;
+
+ --dry-run | -n)
+ run=:
+ ;;
+
+ --features)
+ echo "host: $host"
+ if test "$build_libtool_libs" = yes; then
+ echo "enable shared libraries"
+ else
+ echo "disable shared libraries"
+ fi
+ if test "$build_old_libs" = yes; then
+ echo "enable static libraries"
+ else
+ echo "disable static libraries"
+ fi
+ exit 0
+ ;;
+
+ --finish) mode="finish" ;;
+
+ --mode) prevopt="--mode" prev=mode ;;
+ --mode=*) mode="$optarg" ;;
+
+ --preserve-dup-deps) duplicate_deps="yes" ;;
+
+ --quiet | --silent)
+ show=:
+ ;;
+
+ -dlopen)
+ prevopt="-dlopen"
+ prev=execute_dlfiles
+ ;;
+
+ -*)
+ $echo "$modename: unrecognized option \`$arg'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+
+ *)
+ nonopt="$arg"
+ break
+ ;;
+ esac
+done
+
+if test -n "$prevopt"; then
+ $echo "$modename: option \`$prevopt' requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+fi
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end. This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+if test -z "$show_help"; then
+
+ # Infer the operation mode.
+ if test -z "$mode"; then
+ case $nonopt in
+ *cc | *++ | gcc* | *-gcc* | g++* | xlc*)
+ mode=link
+ for arg
+ do
+ case $arg in
+ -c)
+ mode=compile
+ break
+ ;;
+ esac
+ done
+ ;;
+ *db | *dbx | *strace | *truss)
+ mode=execute
+ ;;
+ *install*|cp|mv)
+ mode=install
+ ;;
+ *rm)
+ mode=uninstall
+ ;;
+ *)
+ # If we have no mode, but dlfiles were specified, then do execute mode.
+ test -n "$execute_dlfiles" && mode=execute
+
+ # Just use the default operation mode.
+ if test -z "$mode"; then
+ if test -n "$nonopt"; then
+ $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+ else
+ $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+ fi
+ fi
+ ;;
+ esac
+ fi
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$execute_dlfiles" && test "$mode" != execute; then
+ $echo "$modename: unrecognized option \`-dlopen'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Change the help message to a mode-specific one.
+ generic_help="$help"
+ help="Try \`$modename --help --mode=$mode' for more information."
+
+ # These modes are in order of execution frequency so that they run quickly.
+ case $mode in
+ # libtool compile mode
+ compile)
+ modename="$modename: compile"
+ # Get the compilation command and the source file.
+ base_compile=
+ prev=
+ lastarg=
+ srcfile="$nonopt"
+ suppress_output=
+
+ user_target=no
+ for arg
+ do
+ case $prev in
+ "") ;;
+ xcompiler)
+ # Aesthetically quote the previous argument.
+ prev=
+ lastarg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+
+ case $arg in
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+
+ # Add the previous argument to base_compile.
+ if test -z "$base_compile"; then
+ base_compile="$lastarg"
+ else
+ base_compile="$base_compile $lastarg"
+ fi
+ continue
+ ;;
+ esac
+
+ # Accept any command-line options.
+ case $arg in
+ -o)
+ if test "$user_target" != "no"; then
+ $echo "$modename: you cannot specify \`-o' more than once" 1>&2
+ exit 1
+ fi
+ user_target=next
+ ;;
+
+ -static)
+ build_old_libs=yes
+ continue
+ ;;
+
+ -prefer-pic)
+ pic_mode=yes
+ continue
+ ;;
+
+ -prefer-non-pic)
+ pic_mode=no
+ continue
+ ;;
+
+ -Xcompiler)
+ prev=xcompiler
+ continue
+ ;;
+
+ -Wc,*)
+ args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
+ lastarg=
+ save_ifs="$IFS"; IFS=','
+ for arg in $args; do
+ IFS="$save_ifs"
+
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ lastarg="$lastarg $arg"
+ done
+ IFS="$save_ifs"
+ lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
+
+ # Add the arguments to base_compile.
+ if test -z "$base_compile"; then
+ base_compile="$lastarg"
+ else
+ base_compile="$base_compile $lastarg"
+ fi
+ continue
+ ;;
+ esac
+
+ case $user_target in
+ next)
+ # The next one is the -o target name
+ user_target=yes
+ continue
+ ;;
+ yes)
+ # We got the output file
+ user_target=set
+ libobj="$arg"
+ continue
+ ;;
+ esac
+
+ # Accept the current argument as the source file.
+ lastarg="$srcfile"
+ srcfile="$arg"
+
+ # Aesthetically quote the previous argument.
+
+ # Backslashify any backslashes, double quotes, and dollar signs.
+ # These are the only characters that are still specially
+ # interpreted inside of double-quoted scrings.
+ lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
+
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ case $lastarg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ lastarg="\"$lastarg\""
+ ;;
+ esac
+
+ # Add the previous argument to base_compile.
+ if test -z "$base_compile"; then
+ base_compile="$lastarg"
+ else
+ base_compile="$base_compile $lastarg"
+ fi
+ done
+
+ case $user_target in
+ set)
+ ;;
+ no)
+ # Get the name of the library object.
+ libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
+ ;;
+ *)
+ $echo "$modename: you must specify a target with \`-o'" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Recognize several different file suffixes.
+ # If the user specifies -o file.o, it is replaced with file.lo
+ xform='[cCFSfmso]'
+ case $libobj in
+ *.ada) xform=ada ;;
+ *.adb) xform=adb ;;
+ *.ads) xform=ads ;;
+ *.asm) xform=asm ;;
+ *.c++) xform=c++ ;;
+ *.cc) xform=cc ;;
+ *.cpp) xform=cpp ;;
+ *.cxx) xform=cxx ;;
+ *.f90) xform=f90 ;;
+ *.for) xform=for ;;
+ esac
+
+ libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
+
+ case $libobj in
+ *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
+ *)
+ $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
+ exit 1
+ ;;
+ esac
+
+ if test -z "$base_compile"; then
+ $echo "$modename: you must specify a compilation command" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Delete any leftover library objects.
+ if test "$build_old_libs" = yes; then
+ removelist="$obj $libobj"
+ else
+ removelist="$libobj"
+ fi
+
+ $run $rm $removelist
+ trap "$run $rm $removelist; exit 1" 1 2 15
+
+ # On Cygwin there's no "real" PIC flag so we must build both object types
+ case $host_os in
+ cygwin* | mingw* | pw32* | os2*)
+ pic_mode=default
+ ;;
+ esac
+ if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+ # non-PIC code in shared libraries is not supported
+ pic_mode=default
+ fi
+
+ # Calculate the filename of the output object if compiler does
+ # not support -o with -c
+ if test "$compiler_c_o" = no; then
+ output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
+ lockfile="$output_obj.lock"
+ removelist="$removelist $output_obj $lockfile"
+ trap "$run $rm $removelist; exit 1" 1 2 15
+ else
+ need_locks=no
+ lockfile=
+ fi
+
+ # Lock this critical section if it is needed
+ # We use this script file to make the link, it avoids creating a new file
+ if test "$need_locks" = yes; then
+ until $run ln "$0" "$lockfile" 2>/dev/null; do
+ $show "Waiting for $lockfile to be removed"
+ sleep 2
+ done
+ elif test "$need_locks" = warn; then
+ if test -f "$lockfile"; then
+ echo "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit 1
+ fi
+ echo $srcfile > "$lockfile"
+ fi
+
+ if test -n "$fix_srcfile_path"; then
+ eval srcfile=\"$fix_srcfile_path\"
+ fi
+
+ # Only build a PIC object if we are building libtool libraries.
+ if test "$build_libtool_libs" = yes; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ if test "$pic_mode" != no; then
+ # All platforms use -DPIC, to notify preprocessed assembler code.
+ command="$base_compile $srcfile $pic_flag -DPIC"
+ else
+ # Don't build PIC code
+ command="$base_compile $srcfile"
+ fi
+ if test "$build_old_libs" = yes; then
+ lo_libobj="$libobj"
+ dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$dir" = "X$libobj"; then
+ dir="$objdir"
+ else
+ dir="$dir/$objdir"
+ fi
+ libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
+
+ if test -d "$dir"; then
+ $show "$rm $libobj"
+ $run $rm $libobj
+ else
+ $show "$mkdir $dir"
+ $run $mkdir $dir
+ status=$?
+ if test $status -ne 0 && test ! -d $dir; then
+ exit $status
+ fi
+ fi
+ fi
+ if test "$compiler_o_lo" = yes; then
+ output_obj="$libobj"
+ command="$command -o $output_obj"
+ elif test "$compiler_c_o" = yes; then
+ output_obj="$obj"
+ command="$command -o $output_obj"
+ fi
+
+ $run $rm "$output_obj"
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ test -n "$output_obj" && $run $rm $removelist
+ exit 1
+ fi
+
+ if test "$need_locks" = warn &&
+ test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
+ echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit 1
+ fi
+
+ # Just move the object if needed, then go on to compile the next one
+ if test x"$output_obj" != x"$libobj"; then
+ $show "$mv $output_obj $libobj"
+ if $run $mv $output_obj $libobj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # If we have no pic_flag, then copy the object into place and finish.
+ if (test -z "$pic_flag" || test "$pic_mode" != default) &&
+ test "$build_old_libs" = yes; then
+ # Rename the .lo from within objdir to obj
+ if test -f $obj; then
+ $show $rm $obj
+ $run $rm $obj
+ fi
+
+ $show "$mv $libobj $obj"
+ if $run $mv $libobj $obj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+
+ xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$obj"; then
+ xdir="."
+ else
+ xdir="$xdir"
+ fi
+ baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"`
+ libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"`
+ # Now arrange that obj and lo_libobj become the same file
+ $show "(cd $xdir && $LN_S $baseobj $libobj)"
+ if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then
+ # Unlock the critical section if it was locked
+ if test "$need_locks" != no; then
+ $run $rm "$lockfile"
+ fi
+ exit 0
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Allow error messages only from the first compilation.
+ suppress_output=' >/dev/null 2>&1'
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test "$build_old_libs" = yes; then
+ if test "$pic_mode" != yes; then
+ # Don't build PIC code
+ command="$base_compile $srcfile"
+ else
+ # All platforms use -DPIC, to notify preprocessed assembler code.
+ command="$base_compile $srcfile $pic_flag -DPIC"
+ fi
+ if test "$compiler_c_o" = yes; then
+ command="$command -o $obj"
+ output_obj="$obj"
+ fi
+
+ # Suppress compiler output if we already did a PIC compilation.
+ command="$command$suppress_output"
+ $run $rm "$output_obj"
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ $run $rm $removelist
+ exit 1
+ fi
+
+ if test "$need_locks" = warn &&
+ test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
+ echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit 1
+ fi
+
+ # Just move the object if needed
+ if test x"$output_obj" != x"$obj"; then
+ $show "$mv $output_obj $obj"
+ if $run $mv $output_obj $obj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we do not
+ # accidentally link it into a program.
+ if test "$build_libtool_libs" != yes; then
+ $show "echo timestamp > $libobj"
+ $run eval "echo timestamp > \$libobj" || exit $?
+ else
+ # Move the .lo from within objdir
+ $show "$mv $libobj $lo_libobj"
+ if $run $mv $libobj $lo_libobj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+ fi
+
+ # Unlock the critical section if it was locked
+ if test "$need_locks" != no; then
+ $run $rm "$lockfile"
+ fi
+
+ exit 0
+ ;;
+
+ # libtool link mode
+ link | relink)
+ modename="$modename: link"
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ # It is impossible to link a dll without this setting, and
+ # we shouldn't force the makefile maintainer to figure out
+ # which system we are compiling for in order to pass an extra
+ # flag for every libtool invokation.
+ # allow_undefined=no
+
+ # FIXME: Unfortunately, there are problems with the above when trying
+ # to make a dll which has undefined symbols, in which case not
+ # even a static library is built. For now, we need to specify
+ # -no-undefined on the libtool link line when we can be certain
+ # that all symbols are satisfied, otherwise we get a static library.
+ allow_undefined=yes
+ ;;
+ *)
+ allow_undefined=yes
+ ;;
+ esac
+ libtool_args="$nonopt"
+ compile_command="$nonopt"
+ finalize_command="$nonopt"
+
+ compile_rpath=
+ finalize_rpath=
+ compile_shlibpath=
+ finalize_shlibpath=
+ convenience=
+ old_convenience=
+ deplibs=
+ old_deplibs=
+ compiler_flags=
+ linker_flags=
+ dllsearchpath=
+ lib_search_path=`pwd`
+ inst_prefix_dir=
+
+ avoid_version=no
+ dlfiles=
+ dlprefiles=
+ dlself=no
+ export_dynamic=no
+ export_symbols=
+ export_symbols_regex=
+ generated=
+ libobjs=
+ ltlibs=
+ module=no
+ no_install=no
+ objs=
+ prefer_static_libs=no
+ preload=no
+ prev=
+ prevarg=
+ release=
+ rpath=
+ xrpath=
+ perm_rpath=
+ temp_rpath=
+ thread_safe=no
+ vinfo=
+
+ # We need to know -static, to get the right output filenames.
+ for arg
+ do
+ case $arg in
+ -all-static | -static)
+ if test "X$arg" = "X-all-static"; then
+ if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+ $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
+ fi
+ if test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ else
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ fi
+ build_libtool_libs=no
+ build_old_libs=yes
+ prefer_static_libs=yes
+ break
+ ;;
+ esac
+ done
+
+ # See if our shared archives depend on static archives.
+ test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+ # Go through the arguments, transforming them on the way.
+ while test $# -gt 0; do
+ arg="$1"
+ shift
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test
+ ;;
+ *) qarg=$arg ;;
+ esac
+ libtool_args="$libtool_args $qarg"
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case $prev in
+ output)
+ compile_command="$compile_command @OUTPUT@"
+ finalize_command="$finalize_command @OUTPUT@"
+ ;;
+ esac
+
+ case $prev in
+ dlfiles|dlprefiles)
+ if test "$preload" = no; then
+ # Add the symbol object into the linking commands.
+ compile_command="$compile_command @SYMFILE@"
+ finalize_command="$finalize_command @SYMFILE@"
+ preload=yes
+ fi
+ case $arg in
+ *.la | *.lo) ;; # We handle these cases below.
+ force)
+ if test "$dlself" = no; then
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ self)
+ if test "$prev" = dlprefiles; then
+ dlself=yes
+ elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+ dlself=yes
+ else
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ else
+ dlprefiles="$dlprefiles $arg"
+ fi
+ prev=
+ continue
+ ;;
+ esac
+ ;;
+ expsyms)
+ export_symbols="$arg"
+ if test ! -f "$arg"; then
+ $echo "$modename: symbol file \`$arg' does not exist"
+ exit 1
+ fi
+ prev=
+ continue
+ ;;
+ expsyms_regex)
+ export_symbols_regex="$arg"
+ prev=
+ continue
+ ;;
+ inst_prefix)
+ inst_prefix_dir="$arg"
+ prev=
+ continue
+ ;;
+ release)
+ release="-$arg"
+ prev=
+ continue
+ ;;
+ rpath | xrpath)
+ # We need an absolute path.
+ case $arg in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit 1
+ ;;
+ esac
+ if test "$prev" = rpath; then
+ case "$rpath " in
+ *" $arg "*) ;;
+ *) rpath="$rpath $arg" ;;
+ esac
+ else
+ case "$xrpath " in
+ *" $arg "*) ;;
+ *) xrpath="$xrpath $arg" ;;
+ esac
+ fi
+ prev=
+ continue
+ ;;
+ xcompiler)
+ compiler_flags="$compiler_flags $qarg"
+ prev=
+ compile_command="$compile_command $qarg"
+ finalize_command="$finalize_command $qarg"
+ continue
+ ;;
+ xlinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$compiler_flags $wl$qarg"
+ prev=
+ compile_command="$compile_command $wl$qarg"
+ finalize_command="$finalize_command $wl$qarg"
+ continue
+ ;;
+ *)
+ eval "$prev=\"\$arg\""
+ prev=
+ continue
+ ;;
+ esac
+ fi # test -n $prev
+
+ prevarg="$arg"
+
+ case $arg in
+ -all-static)
+ if test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -allow-undefined)
+ # FIXME: remove this flag sometime in the future.
+ $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
+ continue
+ ;;
+
+ -avoid-version)
+ avoid_version=yes
+ continue
+ ;;
+
+ -dlopen)
+ prev=dlfiles
+ continue
+ ;;
+
+ -dlpreopen)
+ prev=dlprefiles
+ continue
+ ;;
+
+ -export-dynamic)
+ export_dynamic=yes
+ continue
+ ;;
+
+ -export-symbols | -export-symbols-regex)
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: more than one -exported-symbols argument is not allowed"
+ exit 1
+ fi
+ if test "X$arg" = "X-export-symbols"; then
+ prev=expsyms
+ else
+ prev=expsyms_regex
+ fi
+ continue
+ ;;
+
+ -inst-prefix-dir)
+ prev=inst_prefix
+ continue
+ ;;
+
+ # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+ # so, if we see these flags be careful not to treat them like -L
+ -L[A-Z][A-Z]*:*)
+ case $with_gcc/$host in
+ no/*-*-irix* | no/*-*-nonstopux*)
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ ;;
+ esac
+ continue
+ ;;
+
+ -L*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
+ exit 1
+ fi
+ dir="$absdir"
+ ;;
+ esac
+ case "$deplibs " in
+ *" -L$dir "*) ;;
+ *)
+ deplibs="$deplibs -L$dir"
+ lib_search_path="$lib_search_path $dir"
+ ;;
+ esac
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ case :$dllsearchpath: in
+ *":$dir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$dir";;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+
+ -l*)
+ if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+ case $host in
+ *-*-cygwin* | *-*-pw32* | *-*-beos*)
+ # These systems don't actually have a C or math library (as such)
+ continue
+ ;;
+ *-*-mingw* | *-*-os2*)
+ # These systems don't actually have a C library (as such)
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-openbsd* | *-*-freebsd*)
+ # Do not include libc due to us having libc/libc_r.
+ test "X$arg" = "X-lc" && continue
+ ;;
+ esac
+ elif test "X$arg" = "X-lc_r"; then
+ case $host in
+ *-*-openbsd* | *-*-freebsd*)
+ # Do not include libc_r directly, use -pthread flag.
+ continue
+ ;;
+ esac
+ fi
+ deplibs="$deplibs $arg"
+ continue
+ ;;
+
+ -module)
+ module=yes
+ continue
+ ;;
+
+ -no-fast-install)
+ fast_install=no
+ continue
+ ;;
+
+ -no-install)
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ # The PATH hackery in wrapper scripts is required on Windows
+ # in order for the loader to find any dlls it needs.
+ $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2
+ $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2
+ fast_install=no
+ ;;
+ *) no_install=yes ;;
+ esac
+ continue
+ ;;
+
+ -no-undefined)
+ allow_undefined=no
+ continue
+ ;;
+
+ -o) prev=output ;;
+
+ -release)
+ prev=release
+ continue
+ ;;
+
+ -rpath)
+ prev=rpath
+ continue
+ ;;
+
+ -R)
+ prev=xrpath
+ continue
+ ;;
+
+ -R*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit 1
+ ;;
+ esac
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ continue
+ ;;
+
+ -static)
+ # The effects of -static are defined in a previous loop.
+ # We used to do the same as -all-static on platforms that
+ # didn't have a PIC flag, but the assumption that the effects
+ # would be equivalent was wrong. It would break on at least
+ # Digital Unix and AIX.
+ continue
+ ;;
+
+ -thread-safe)
+ thread_safe=yes
+ continue
+ ;;
+
+ -version-info)
+ prev=vinfo
+ continue
+ ;;
+
+ -Wc,*)
+ args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
+ arg=
+ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ case $flag in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ flag="\"$flag\""
+ ;;
+ esac
+ arg="$arg $wl$flag"
+ compiler_flags="$compiler_flags $flag"
+ done
+ IFS="$save_ifs"
+ arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+ ;;
+
+ -Wl,*)
+ args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'`
+ arg=
+ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ case $flag in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ flag="\"$flag\""
+ ;;
+ esac
+ arg="$arg $wl$flag"
+ compiler_flags="$compiler_flags $wl$flag"
+ linker_flags="$linker_flags $flag"
+ done
+ IFS="$save_ifs"
+ arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+ ;;
+
+ -Xcompiler)
+ prev=xcompiler
+ continue
+ ;;
+
+ -Xlinker)
+ prev=xlinker
+ continue
+ ;;
+
+ # Some other compiler flag.
+ -* | +*)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+
+ *.lo | *.$objext)
+ # A library or standard object.
+ if test "$prev" = dlfiles; then
+ # This file was specified with -dlopen.
+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+ dlfiles="$dlfiles $arg"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"`
+ prev=
+ else
+ case $arg in
+ *.lo) libobjs="$libobjs $arg" ;;
+ *) objs="$objs $arg" ;;
+ esac
+ fi
+ ;;
+
+ *.$libext)
+ # An archive.
+ deplibs="$deplibs $arg"
+ old_deplibs="$old_deplibs $arg"
+ continue
+ ;;
+
+ *.la)
+ # A libtool-controlled library.
+
+ if test "$prev" = dlfiles; then
+ # This library was specified with -dlopen.
+ dlfiles="$dlfiles $arg"
+ prev=
+ elif test "$prev" = dlprefiles; then
+ # The library was specified with -dlpreopen.
+ dlprefiles="$dlprefiles $arg"
+ prev=
+ else
+ deplibs="$deplibs $arg"
+ fi
+ continue
+ ;;
+
+ # Some other compiler argument.
+ *)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+ esac # arg
+
+ # Now actually substitute the argument into the commands.
+ if test -n "$arg"; then
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+ done # argument parsing loop
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+ eval arg=\"$export_dynamic_flag_spec\"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+
+ # calculate the name of the file, without its directory
+ outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
+ libobjs_save="$libobjs"
+
+ if test -n "$shlibpath_var"; then
+ # get the directories listed in $shlibpath_var
+ eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+ else
+ shlib_search_path=
+ fi
+ eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+ eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+ output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$output_objdir" = "X$output"; then
+ output_objdir="$objdir"
+ else
+ output_objdir="$output_objdir/$objdir"
+ fi
+ # Create the object directory.
+ if test ! -d $output_objdir; then
+ $show "$mkdir $output_objdir"
+ $run $mkdir $output_objdir
+ status=$?
+ if test $status -ne 0 && test ! -d $output_objdir; then
+ exit $status
+ fi
+ fi
+
+ # Determine the type of output
+ case $output in
+ "")
+ $echo "$modename: you must specify an output file" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+ *.$libext) linkmode=oldlib ;;
+ *.lo | *.$objext) linkmode=obj ;;
+ *.la) linkmode=lib ;;
+ *) linkmode=prog ;; # Anything else should be a program.
+ esac
+
+ specialdeplibs=
+ libs=
+ # Find all interdependent deplibs by searching for libraries
+ # that are linked more than once (e.g. -la -lb -la)
+ for deplib in $deplibs; do
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ libs="$libs $deplib"
+ done
+ deplibs=
+ newdependency_libs=
+ newlib_search_path=
+ need_relink=no # whether we're linking any uninstalled libtool libraries
+ notinst_deplibs= # not-installed libtool libraries
+ notinst_path= # paths that contain not-installed libtool libraries
+ case $linkmode in
+ lib)
+ passes="conv link"
+ for file in $dlfiles $dlprefiles; do
+ case $file in
+ *.la) ;;
+ *)
+ $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+ ;;
+ prog)
+ compile_deplibs=
+ finalize_deplibs=
+ alldeplibs=no
+ newdlfiles=
+ newdlprefiles=
+ passes="conv scan dlopen dlpreopen link"
+ ;;
+ *) passes="conv"
+ ;;
+ esac
+ for pass in $passes; do
+ if test $linkmode = prog; then
+ # Determine which files to process
+ case $pass in
+ dlopen)
+ libs="$dlfiles"
+ save_deplibs="$deplibs" # Collect dlpreopened libraries
+ deplibs=
+ ;;
+ dlpreopen) libs="$dlprefiles" ;;
+ link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+ esac
+ fi
+ for deplib in $libs; do
+ lib=
+ found=no
+ case $deplib in
+ -l*)
+ if test $linkmode = oldlib && test $linkmode = obj; then
+ $echo "$modename: warning: \`-l' is ignored for archives/objects: $deplib" 1>&2
+ continue
+ fi
+ if test $pass = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
+ for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ # Search the libtool library
+ lib="$searchdir/lib${name}.la"
+ if test -f "$lib"; then
+ found=yes
+ break
+ fi
+ done
+ if test "$found" != yes; then
+ # deplib doesn't seem to be a libtool library
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test $linkmode = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+ ;; # -l
+ -L*)
+ case $linkmode in
+ lib)
+ deplibs="$deplib $deplibs"
+ test $pass = conv && continue
+ newdependency_libs="$deplib $newdependency_libs"
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ ;;
+ prog)
+ if test $pass = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ if test $pass = scan; then
+ deplibs="$deplib $deplibs"
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ ;;
+ *)
+ $echo "$modename: warning: \`-L' is ignored for archives/objects: $deplib" 1>&2
+ ;;
+ esac # linkmode
+ continue
+ ;; # -L
+ -R*)
+ if test $pass = link; then
+ dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+ # Make sure the xrpath contains only unique directories.
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ fi
+ deplibs="$deplib $deplibs"
+ continue
+ ;;
+ *.la) lib="$deplib" ;;
+ *.$libext)
+ if test $pass = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ case $linkmode in
+ lib)
+ if test "$deplibs_check_method" != pass_all; then
+ echo
+ echo "*** Warning: Trying to link with static lib archive $deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have"
+ echo "*** because the file extensions .$libext of this argument makes me believe"
+ echo "*** that it is just a static archive that I should not used here."
+ else
+ echo
+ echo "*** Warning: Linking the shared library $output against the"
+ echo "*** static library $deplib is not portable!"
+ deplibs="$deplib $deplibs"
+ fi
+ continue
+ ;;
+ prog)
+ if test $pass != link; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ continue
+ ;;
+ esac # linkmode
+ ;; # *.$libext
+ *.lo | *.$objext)
+ if test $pass = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+ # If there is no dlopen support or we're linking statically,
+ # we need to preload.
+ newdlprefiles="$newdlprefiles $deplib"
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ newdlfiles="$newdlfiles $deplib"
+ fi
+ continue
+ ;;
+ %DEPLIBS%)
+ alldeplibs=yes
+ continue
+ ;;
+ esac # case $deplib
+ if test $found = yes || test -f "$lib"; then :
+ else
+ $echo "$modename: cannot find the library \`$lib'" 1>&2
+ exit 1
+ fi
+
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $lib | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit 1
+ fi
+
+ ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$ladir" = "X$lib" && ladir="."
+
+ dlname=
+ dlopen=
+ dlpreopen=
+ libdir=
+ library_names=
+ old_library=
+ # If the library was installed with an old release of libtool,
+ # it will not redefine variable installed.
+ installed=yes
+
+ # Read the .la file
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+
+ if test "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan" ||
+ { test $linkmode = oldlib && test $linkmode = obj; }; then
+ # Add dl[pre]opened files of deplib
+ test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+ test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+ fi
+
+ if test $pass = conv; then
+ # Only check for convenience libraries
+ deplibs="$lib $deplibs"
+ if test -z "$libdir"; then
+ if test -z "$old_library"; then
+ $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+ exit 1
+ fi
+ # It is a libtool convenience library, so add in its objects.
+ convenience="$convenience $ladir/$objdir/$old_library"
+ old_convenience="$old_convenience $ladir/$objdir/$old_library"
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ deplibs="$deplib $deplibs"
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+ elif test $linkmode != prog && test $linkmode != lib; then
+ $echo "$modename: \`$lib' is not a convenience library" 1>&2
+ exit 1
+ fi
+ continue
+ fi # $pass = conv
+
+ # Get the name of the library we link against.
+ linklib=
+ for l in $old_library $library_names; do
+ linklib="$l"
+ done
+ if test -z "$linklib"; then
+ $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+ exit 1
+ fi
+
+ # This library was specified with -dlopen.
+ if test $pass = dlopen; then
+ if test -z "$libdir"; then
+ $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
+ exit 1
+ fi
+ if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+ # If there is no dlname, no dlopen support or we're linking
+ # statically, we need to preload.
+ dlprefiles="$dlprefiles $lib"
+ else
+ newdlfiles="$newdlfiles $lib"
+ fi
+ continue
+ fi # $pass = dlopen
+
+ # We need an absolute path.
+ case $ladir in
+ [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+ *)
+ abs_ladir=`cd "$ladir" && pwd`
+ if test -z "$abs_ladir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2
+ $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+ abs_ladir="$ladir"
+ fi
+ ;;
+ esac
+ laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+
+ # Find the relevant object directory and library name.
+ if test "X$installed" = Xyes; then
+ if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ $echo "$modename: warning: library \`$lib' was moved." 1>&2
+ dir="$ladir"
+ absdir="$abs_ladir"
+ libdir="$abs_ladir"
+ else
+ dir="$libdir"
+ absdir="$libdir"
+ fi
+ else
+ dir="$ladir/$objdir"
+ absdir="$abs_ladir/$objdir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ fi # $installed = yes
+ name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+
+ # This library was specified with -dlpreopen.
+ if test $pass = dlpreopen; then
+ if test -z "$libdir"; then
+ $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
+ exit 1
+ fi
+ # Prefer using a static library (so that no silly _DYNAMIC symbols
+ # are required to link).
+ if test -n "$old_library"; then
+ newdlprefiles="$newdlprefiles $dir/$old_library"
+ # Otherwise, use the dlname, so that lt_dlopen finds it.
+ elif test -n "$dlname"; then
+ newdlprefiles="$newdlprefiles $dir/$dlname"
+ else
+ newdlprefiles="$newdlprefiles $dir/$linklib"
+ fi
+ fi # $pass = dlpreopen
+
+ if test -z "$libdir"; then
+ # Link the convenience library
+ if test $linkmode = lib; then
+ deplibs="$dir/$old_library $deplibs"
+ elif test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$dir/$old_library $compile_deplibs"
+ finalize_deplibs="$dir/$old_library $finalize_deplibs"
+ else
+ deplibs="$lib $deplibs"
+ fi
+ continue
+ fi
+
+ if test $linkmode = prog && test $pass != link; then
+ newlib_search_path="$newlib_search_path $ladir"
+ deplibs="$lib $deplibs"
+
+ linkalldeplibs=no
+ if test "$link_all_deplibs" != no || test -z "$library_names" ||
+ test "$build_libtool_libs" = no; then
+ linkalldeplibs=yes
+ fi
+
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test
+ esac
+ # Need to link against all dependency_libs?
+ if test $linkalldeplibs = yes; then
+ deplibs="$deplib $deplibs"
+ else
+ # Need to hardcode shared library paths
+ # or/and link against static libraries
+ newdependency_libs="$deplib $newdependency_libs"
+ fi
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done # for deplib
+ continue
+ fi # $linkmode = prog...
+
+ link_static=no # Whether the deplib will be linked statically
+ if test -n "$library_names" &&
+ { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+ # Link against this shared library
+
+ if test "$linkmode,$pass" = "prog,link" ||
+ { test $linkmode = lib && test $hardcode_into_libs = yes; }; then
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+ if test $linkmode = prog; then
+ # We need to hardcode the library path
+ if test -n "$shlibpath_var"; then
+ # Make sure the rpath contains only unique directories.
+ case "$temp_rpath " in
+ *" $dir "*) ;;
+ *" $absdir "*) ;;
+ *) temp_rpath="$temp_rpath $dir" ;;
+ esac
+ fi
+ fi
+ fi # $linkmode,$pass = prog,link...
+
+ if test "$alldeplibs" = yes &&
+ { test "$deplibs_check_method" = pass_all ||
+ { test "$build_libtool_libs" = yes &&
+ test -n "$library_names"; }; }; then
+ # We only need to search for static libraries
+ continue
+ fi
+
+ if test "$installed" = no; then
+ notinst_deplibs="$notinst_deplibs $lib"
+ need_relink=yes
+ fi
+
+ if test -n "$old_archive_from_expsyms_cmds"; then
+ # figure out the soname
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+ libname=`eval \\$echo \"$libname_spec\"`
+ # use dlname if we got it. it's perfectly good, no?
+ if test -n "$dlname"; then
+ soname="$dlname"
+ elif test -n "$soname_spec"; then
+ # bleh windows
+ case $host in
+ *cygwin*)
+ major=`expr $current - $age`
+ versuffix="-$major"
+ ;;
+ esac
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+
+ # Make a new name for the extract_expsyms_cmds to use
+ soroot="$soname"
+ soname=`echo $soroot | ${SED} -e 's/^.*\///'`
+ newlib="libimp-`echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a"
+
+ # If the library has no export list, then create one now
+ if test -f "$output_objdir/$soname-def"; then :
+ else
+ $show "extracting exported symbol list from \`$soname'"
+ save_ifs="$IFS"; IFS='~'
+ eval cmds=\"$extract_expsyms_cmds\"
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Create $newlib
+ if test -f "$output_objdir/$newlib"; then :; else
+ $show "generating import library for \`$soname'"
+ save_ifs="$IFS"; IFS='~'
+ eval cmds=\"$old_archive_from_expsyms_cmds\"
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+ # make sure the library variables are pointing to the new library
+ dir=$output_objdir
+ linklib=$newlib
+ fi # test -n $old_archive_from_expsyms_cmds
+
+ if test $linkmode = prog || test "$mode" != relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ lib_linked=yes
+ case $hardcode_action in
+ immediate | unsupported)
+ if test "$hardcode_direct" = no; then
+ add="$dir/$linklib"
+ elif test "$hardcode_minus_L" = no; then
+ case $host in
+ *-*-sunos*) add_shlibpath="$dir" ;;
+ esac
+ add_dir="-L$dir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = no; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ relink)
+ if test "$hardcode_direct" = yes; then
+ add="$dir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$dir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case "$libdir" in
+ [\/]*)
+ add_dir="-L$inst_prefix_dir$libdir $add_dir"
+ ;;
+ esac
+ fi
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ *) lib_linked=no ;;
+ esac
+
+ if test "$lib_linked" != yes; then
+ $echo "$modename: configuration error: unsupported hardcode properties"
+ exit 1
+ fi
+
+ if test -n "$add_shlibpath"; then
+ case :$compile_shlibpath: in
+ *":$add_shlibpath:"*) ;;
+ *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+ esac
+ fi
+ if test $linkmode = prog; then
+ test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+ test -n "$add" && compile_deplibs="$add $compile_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ if test "$hardcode_direct" != yes && \
+ test "$hardcode_minus_L" != yes && \
+ test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ fi
+ fi
+ fi
+
+ if test $linkmode = prog || test "$mode" = relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ # Finalize command for both is simple: just hardcode it.
+ if test "$hardcode_direct" = yes; then
+ add="$libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$libdir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ add="-l$name"
+ else
+ # We cannot seem to hardcode it, guess we'll fake it.
+ add_dir="-L$libdir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case "$libdir" in
+ [\/]*)
+ add_dir="-L$inst_prefix_dir$libdir $add_dir"
+ ;;
+ esac
+ fi
+ add="-l$name"
+ fi
+
+ if test $linkmode = prog; then
+ test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+ test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ fi
+ fi
+ elif test $linkmode = prog; then
+ if test "$alldeplibs" = yes &&
+ { test "$deplibs_check_method" = pass_all ||
+ { test "$build_libtool_libs" = yes &&
+ test -n "$library_names"; }; }; then
+ # We only need to search for static libraries
+ continue
+ fi
+
+ # Try to link the static library
+ # Here we assume that one of hardcode_direct or hardcode_minus_L
+ # is not unsupported. This is valid on all known static and
+ # shared platforms.
+ if test "$hardcode_direct" != unsupported; then
+ test -n "$old_library" && linklib="$old_library"
+ compile_deplibs="$dir/$linklib $compile_deplibs"
+ finalize_deplibs="$dir/$linklib $finalize_deplibs"
+ else
+ compile_deplibs="-l$name -L$dir $compile_deplibs"
+ finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+ fi
+ elif test "$build_libtool_libs" = yes; then
+ # Not a shared library
+ if test "$deplibs_check_method" != pass_all; then
+ # We're trying link a shared library against a static one
+ # but the system doesn't support it.
+
+ # Just print a warning and add the library to dependency_libs so
+ # that the program can be linked against the static library.
+ echo
+ echo "*** Warning: This system can not link to static lib archive $lib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ if test "$module" = yes; then
+ echo "*** But as you try to build a module library, libtool will still create "
+ echo "*** a static module, that should work as long as the dlopening application"
+ echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+ if test -z "$global_symbol_pipe"; then
+ echo
+ echo "*** However, this would only work if libtool was able to extract symbol"
+ echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ echo "*** not find such a program. So, this module is probably useless."
+ echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ else
+ convenience="$convenience $dir/$old_library"
+ old_convenience="$old_convenience $dir/$old_library"
+ deplibs="$dir/$old_library $deplibs"
+ link_static=yes
+ fi
+ fi # link shared/static library?
+
+ if test $linkmode = lib; then
+ if test -n "$dependency_libs" &&
+ { test $hardcode_into_libs != yes || test $build_old_libs = yes ||
+ test $link_static = yes; }; then
+ # Extract -R from dependency_libs
+ temp_deplibs=
+ for libdir in $dependency_libs; do
+ case $libdir in
+ -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'`
+ case " $xrpath " in
+ *" $temp_xrpath "*) ;;
+ *) xrpath="$xrpath $temp_xrpath";;
+ esac;;
+ *) temp_deplibs="$temp_deplibs $libdir";;
+ esac
+ done
+ dependency_libs="$temp_deplibs"
+ fi
+
+ newlib_search_path="$newlib_search_path $absdir"
+ # Link against this library
+ test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+ # ... and its dependency_libs
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ newdependency_libs="$deplib $newdependency_libs"
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+
+ if test $link_all_deplibs != no; then
+ # Add the search paths of all dependency libraries
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) path="$deplib" ;;
+ *.la)
+ dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$deplib" && dir="."
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+ absdir="$dir"
+ fi
+ ;;
+ esac
+ if grep "^installed=no" $deplib > /dev/null; then
+ path="-L$absdir/$objdir"
+ else
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+ exit 1
+ fi
+ if test "$absdir" != "$libdir"; then
+ $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
+ fi
+ path="-L$absdir"
+ fi
+ ;;
+ *) continue ;;
+ esac
+ case " $deplibs " in
+ *" $path "*) ;;
+ *) deplibs="$deplibs $path" ;;
+ esac
+ done
+ fi # link_all_deplibs != no
+ fi # linkmode = lib
+ done # for deplib in $libs
+ if test $pass = dlpreopen; then
+ # Link the dlpreopened libraries before other libraries
+ for deplib in $save_deplibs; do
+ deplibs="$deplib $deplibs"
+ done
+ fi
+ if test $pass != dlopen; then
+ test $pass != scan && dependency_libs="$newdependency_libs"
+ if test $pass != conv; then
+ # Make sure lib_search_path contains only unique directories.
+ lib_search_path=
+ for dir in $newlib_search_path; do
+ case "$lib_search_path " in
+ *" $dir "*) ;;
+ *) lib_search_path="$lib_search_path $dir" ;;
+ esac
+ done
+ newlib_search_path=
+ fi
+
+ if test "$linkmode,$pass" != "prog,link"; then
+ vars="deplibs"
+ else
+ vars="compile_deplibs finalize_deplibs"
+ fi
+ for var in $vars dependency_libs; do
+ # Add libraries to $var in reverse order
+ eval tmp_libs=\"\$$var\"
+ new_libs=
+ for deplib in $tmp_libs; do
+ case $deplib in
+ -L*) new_libs="$deplib $new_libs" ;;
+ *)
+ case " $specialdeplibs " in
+ *" $deplib "*) new_libs="$deplib $new_libs" ;;
+ *)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$deplib $new_libs" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ tmp_libs=
+ for deplib in $new_libs; do
+ case $deplib in
+ -L*)
+ case " $tmp_libs " in
+ *" $deplib "*) ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ done
+ eval $var=\"$tmp_libs\"
+ done # for var
+ fi
+ if test "$pass" = "conv" &&
+ { test "$linkmode" = "lib" || test "$linkmode" = "prog"; }; then
+ libs="$deplibs" # reset libs
+ deplibs=
+ fi
+ done # for pass
+ if test $linkmode = prog; then
+ dlfiles="$newdlfiles"
+ dlprefiles="$newdlprefiles"
+ fi
+
+ case $linkmode in
+ oldlib)
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
+ fi
+
+ # Now set the variables for building old libraries.
+ build_libtool_libs=no
+ oldlibs="$output"
+ objs="$objs$old_deplibs"
+ ;;
+
+ lib)
+ # Make sure we only generate libraries of the form `libNAME.la'.
+ case $outputname in
+ lib*)
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+ eval libname=\"$libname_spec\"
+ ;;
+ *)
+ if test "$module" = no; then
+ $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+ if test "$need_lib_prefix" != no; then
+ # Add the "lib" prefix for modules if required
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ eval libname=\"$libname_spec\"
+ else
+ libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ fi
+ ;;
+ esac
+
+ if test -n "$objs"; then
+ if test "$deplibs_check_method" != pass_all; then
+ $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
+ exit 1
+ else
+ echo
+ echo "*** Warning: Linking the shared library $output against the non-libtool"
+ echo "*** objects $objs is not portable!"
+ libobjs="$libobjs $objs"
+ fi
+ fi
+
+ if test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2
+ fi
+
+ set dummy $rpath
+ if test $# -gt 2; then
+ $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+ fi
+ install_libdir="$2"
+
+ oldlibs=
+ if test -z "$rpath"; then
+ if test "$build_libtool_libs" = yes; then
+ # Building a libtool convenience library.
+ libext=al
+ oldlibs="$output_objdir/$libname.$libext $oldlibs"
+ build_libtool_libs=convenience
+ build_old_libs=yes
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
+ fi
+ else
+
+ # Parse the version information argument.
+ save_ifs="$IFS"; IFS=':'
+ set dummy $vinfo 0 0 0
+ IFS="$save_ifs"
+
+ if test -n "$8"; then
+ $echo "$modename: too many parameters to \`-version-info'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ current="$2"
+ revision="$3"
+ age="$4"
+
+ # Check that each of the things are valid numbers.
+ case $current in
+ 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case $revision in
+ 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case $age in
+ 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ if test $age -gt $current; then
+ $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ fi
+
+ # Calculate the version variables.
+ major=
+ versuffix=
+ verstring=
+ case $version_type in
+ none) ;;
+
+ darwin)
+ # Like Linux, but with the current version available in
+ # verstring for coding it into the library header
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ # Darwin ld doesn't like 0 for these options...
+ minor_current=`expr $current + 1`
+ verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+ ;;
+
+ freebsd-aout)
+ major=".$current"
+ versuffix=".$current.$revision";
+ ;;
+
+ freebsd-elf)
+ major=".$current"
+ versuffix=".$current";
+ ;;
+
+ irix | nonstopux)
+ major=`expr $current - $age + 1`
+
+ case $version_type in
+ nonstopux) verstring_prefix=nonstopux ;;
+ *) verstring_prefix=sgi ;;
+ esac
+ verstring="$verstring_prefix$major.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$revision
+ while test $loop != 0; do
+ iface=`expr $revision - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring_prefix$major.$iface:$verstring"
+ done
+
+ # Before this point, $major must not contain `.'.
+ major=.$major
+ versuffix="$major.$revision"
+ ;;
+
+ linux)
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ ;;
+
+ osf)
+ major=.`expr $current - $age`
+ versuffix=".$current.$age.$revision"
+ verstring="$current.$age.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$age
+ while test $loop != 0; do
+ iface=`expr $current - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring:${iface}.0"
+ done
+
+ # Make executables depend on our current version.
+ verstring="$verstring:${current}.0"
+ ;;
+
+ sunos)
+ major=".$current"
+ versuffix=".$current.$revision"
+ ;;
+
+ windows)
+ # Use '-' rather than '.', since we only want one
+ # extension on DOS 8.3 filesystems.
+ major=`expr $current - $age`
+ versuffix="-$major"
+ ;;
+
+ *)
+ $echo "$modename: unknown library version type \`$version_type'" 1>&2
+ echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Clear the version info if we defaulted, and they specified a release.
+ if test -z "$vinfo" && test -n "$release"; then
+ major=
+ verstring="0.0"
+ case $version_type in
+ darwin)
+ # we can't check for "0.0" in archive_cmds due to quoting
+ # problems, so we reset it completely
+ verstring=""
+ ;;
+ *)
+ verstring="0.0"
+ ;;
+ esac
+ if test "$need_version" = no; then
+ versuffix=
+ else
+ versuffix=".0.0"
+ fi
+ fi
+
+ # Remove version info from name if versioning should be avoided
+ if test "$avoid_version" = yes && test "$need_version" = no; then
+ major=
+ versuffix=
+ verstring=""
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test "$allow_undefined" = yes; then
+ if test "$allow_undefined_flag" = unsupported; then
+ $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+ build_libtool_libs=no
+ build_old_libs=yes
+ fi
+ else
+ # Don't allow undefined symbols.
+ allow_undefined_flag="$no_undefined_flag"
+ fi
+ fi
+
+ if test "$mode" != relink; then
+ # Remove our outputs.
+ $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*"
+ $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*
+ fi
+
+ # Now set the variables for building old libraries.
+ if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+ oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+ # Transform .lo files to .o files.
+ oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+ fi
+
+ # Eliminate all temporary directories.
+ for path in $notinst_path; do
+ lib_search_path=`echo "$lib_search_path " | ${SED} -e 's% $path % %g'`
+ deplibs=`echo "$deplibs " | ${SED} -e 's% -L$path % %g'`
+ dependency_libs=`echo "$dependency_libs " | ${SED} -e 's% -L$path % %g'`
+ done
+
+ if test -n "$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ temp_xrpath=
+ for libdir in $xrpath; do
+ temp_xrpath="$temp_xrpath -R$libdir"
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ if test $hardcode_into_libs != yes || test $build_old_libs = yes; then
+ dependency_libs="$temp_xrpath $dependency_libs"
+ fi
+ fi
+
+ # Make sure dlfiles contains only unique files that won't be dlpreopened
+ old_dlfiles="$dlfiles"
+ dlfiles=
+ for lib in $old_dlfiles; do
+ case " $dlprefiles $dlfiles " in
+ *" $lib "*) ;;
+ *) dlfiles="$dlfiles $lib" ;;
+ esac
+ done
+
+ # Make sure dlprefiles contains only unique files
+ old_dlprefiles="$dlprefiles"
+ dlprefiles=
+ for lib in $old_dlprefiles; do
+ case "$dlprefiles " in
+ *" $lib "*) ;;
+ *) dlprefiles="$dlprefiles $lib" ;;
+ esac
+ done
+
+ if test "$build_libtool_libs" = yes; then
+ if test -n "$rpath"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*)
+ # these systems don't actually have a c library (as such)!
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C library is in the System framework
+ deplibs="$deplibs -framework System"
+ ;;
+ *-*-netbsd*)
+ # Don't link with libc until the a.out ld.so is fixed.
+ ;;
+ *-*-openbsd* | *-*-freebsd*)
+ # Do not include libc due to us having libc/libc_r.
+ ;;
+ *)
+ # Add libc to deplibs on all other systems if necessary.
+ if test $build_libtool_need_lc = "yes"; then
+ deplibs="$deplibs -lc"
+ fi
+ ;;
+ esac
+ fi
+
+ # Transform deplibs into only deplibs that can be linked in shared.
+ name_save=$name
+ libname_save=$libname
+ release_save=$release
+ versuffix_save=$versuffix
+ major_save=$major
+ # I'm not sure if I'm treating the release correctly. I think
+ # release should show up in the -l (ie -lgmp5) so we don't want to
+ # add it in twice. Is that correct?
+ release=""
+ versuffix=""
+ major=""
+ newdeplibs=
+ droppeddeps=no
+ case $deplibs_check_method in
+ pass_all)
+ # Don't check for shared/static. Everything works.
+ # This might be a little naive. We might want to check
+ # whether the library exists or not. But this is on
+ # osf3 & osf4 and I'm not really sure... Just
+ # implementing what was already the behaviour.
+ newdeplibs=$deplibs
+ ;;
+ test_compile)
+ # This code stresses the "libraries are programs" paradigm to its
+ # limits. Maybe even breaks it. We compile a program, linking it
+ # against the deplibs as a proxy for the library. Then we can check
+ # whether they linked in statically or dynamically with ldd.
+ $rm conftest.c
+ cat > conftest.c <<EOF
+ int main() { return 0; }
+EOF
+ $rm conftest
+ $CC -o conftest conftest.c $deplibs
+ if test $? -eq 0 ; then
+ ldd_output=`ldd conftest`
+ for i in $deplibs; do
+ name="`expr $i : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test -n "$name" && test "$name" != "0"; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ echo
+ echo "*** Warning: dynamic linker does not accept needed library $i."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which I believe you do not have"
+ echo "*** because a test_compile did reveal that the linker did not use it for"
+ echo "*** its dynamic dependency list that programs get resolved with at runtime."
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ else
+ # Error occured in the first compile. Let's try to salvage
+ # the situation: Compile a separate program for each library.
+ for i in $deplibs; do
+ name="`expr $i : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test -n "$name" && test "$name" != "0"; then
+ $rm conftest
+ $CC -o conftest conftest.c $i
+ # Did it work?
+ if test $? -eq 0 ; then
+ ldd_output=`ldd conftest`
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ echo
+ echo "*** Warning: dynamic linker does not accept needed library $i."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have"
+ echo "*** because a test_compile did reveal that the linker did not use this one"
+ echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+ fi
+ else
+ droppeddeps=yes
+ echo
+ echo "*** Warning! Library $i is needed by this library but I was not able to"
+ echo "*** make it link in! You will probably need to install it or some"
+ echo "*** library that it depends on before this library will be fully"
+ echo "*** functional. Installing it before continuing would be even better."
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ fi
+ ;;
+ file_magic*)
+ set dummy $deplibs_check_method
+ file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ for a_deplib in $deplibs; do
+ name="`expr $a_deplib : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test -n "$name" && test "$name" != "0"; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ # Follow soft links.
+ if ls -lLd "$potent_lib" 2>/dev/null \
+ | grep " -> " >/dev/null; then
+ continue
+ fi
+ # The statement above tries to avoid entering an
+ # endless loop below, in case of cyclic links.
+ # We might still enter an endless loop, since a link
+ # loop can be closed while we follow links,
+ # but so what?
+ potlib="$potent_lib"
+ while test -h "$potlib" 2>/dev/null; do
+ potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+ case $potliblink in
+ [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+ *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+ esac
+ done
+ if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
+ | ${SED} 10q \
+ | egrep "$file_magic_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ echo
+ echo "*** Warning: linker path does not have real file for library $a_deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have"
+ echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib" ; then
+ echo "*** with $libname but no candidates were found. (...for file magic test)"
+ else
+ echo "*** with $libname and none of the candidates passed a file format test"
+ echo "*** using a file magic. Last file checked: $potlib"
+ fi
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
+ match_pattern*)
+ set dummy $deplibs_check_method
+ match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ for a_deplib in $deplibs; do
+ name="`expr $a_deplib : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test -n "$name" && test "$name" != "0"; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ potlib="$potent_lib" # see symlink-check below in file_magic test
+ if eval echo \"$potent_lib\" 2>/dev/null \
+ | ${SED} 10q \
+ | egrep "$match_pattern_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ echo
+ echo "*** Warning: linker path does not have real file for library $a_deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have"
+ echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib" ; then
+ echo "*** with $libname but no candidates were found. (...for regex pattern test)"
+ else
+ echo "*** with $libname and none of the candidates passed a file format test"
+ echo "*** using a regex pattern. Last file checked: $potlib"
+ fi
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
+ none | unknown | *)
+ newdeplibs=""
+ if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
+ -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' |
+ grep . >/dev/null; then
+ echo
+ if test "X$deplibs_check_method" = "Xnone"; then
+ echo "*** Warning: inter-library dependencies are not supported in this platform."
+ else
+ echo "*** Warning: inter-library dependencies are not known to be supported."
+ fi
+ echo "*** All declared inter-library dependencies are being dropped."
+ droppeddeps=yes
+ fi
+ ;;
+ esac
+ versuffix=$versuffix_save
+ major=$major_save
+ release=$release_save
+ libname=$libname_save
+ name=$name_save
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ ;;
+ esac
+
+ if test "$droppeddeps" = yes; then
+ if test "$module" = yes; then
+ echo
+ echo "*** Warning: libtool could not satisfy all declared inter-library"
+ echo "*** dependencies of module $libname. Therefore, libtool will create"
+ echo "*** a static module, that should work as long as the dlopening"
+ echo "*** application is linked with the -dlopen flag."
+ if test -z "$global_symbol_pipe"; then
+ echo
+ echo "*** However, this would only work if libtool was able to extract symbol"
+ echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ echo "*** not find such a program. So, this module is probably useless."
+ echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ else
+ echo "*** The inter-library dependencies that have been dropped here will be"
+ echo "*** automatically added whenever a program is linked with this library"
+ echo "*** or is declared to -dlopen it."
+
+ if test $allow_undefined = no; then
+ echo
+ echo "*** Since this library must not contain undefined symbols,"
+ echo "*** because either the platform does not support them or"
+ echo "*** it was explicitly requested with -no-undefined,"
+ echo "*** libtool will only create a static version of it."
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ fi
+ fi
+ # Done checking deplibs!
+ deplibs=$newdeplibs
+ fi
+
+ # All the library-specific variables (install_libdir is set above).
+ library_names=
+ old_library=
+ dlname=
+
+ # Test again, we may have decided not to build it any more
+ if test "$build_libtool_libs" = yes; then
+ if test $hardcode_into_libs = yes; then
+ # Hardcode the library paths
+ hardcode_libdirs=
+ dep_rpath=
+ rpath="$finalize_rpath"
+ test "$mode" != relink && rpath="$compile_rpath$rpath"
+ for libdir in $rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ dep_rpath="$dep_rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+ fi
+ if test -n "$runpath_var" && test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+ fi
+ test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+ fi
+
+ shlibpath="$finalize_shlibpath"
+ test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+ if test -n "$shlibpath"; then
+ eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+ fi
+
+ # Get the real and link names of the library.
+ eval library_names=\"$library_names_spec\"
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+
+ if test -n "$soname_spec"; then
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+ test -z "$dlname" && dlname=$soname
+
+ lib="$output_objdir/$realname"
+ for link
+ do
+ linknames="$linknames $link"
+ done
+
+ # Ensure that we have .o objects for linkers which dislike .lo
+ # (e.g. aix) in case we are running --disable-static
+ for obj in $libobjs; do
+ xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$obj"; then
+ xdir="."
+ else
+ xdir="$xdir"
+ fi
+ baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+ oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"`
+ if test ! -f $xdir/$oldobj; then
+ $show "(cd $xdir && ${LN_S} $baseobj $oldobj)"
+ $run eval '(cd $xdir && ${LN_S} $baseobj $oldobj)' || exit $?
+ fi
+ done
+
+ # Use standard objects if they are pic
+ test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+ $show "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $run $rm $export_symbols
+ eval cmds=\"$export_symbols_cmds\"
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ if test -n "$export_symbols_regex"; then
+ $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
+ $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ $show "$mv \"${export_symbols}T\" \"$export_symbols\""
+ $run eval '$mv "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+ fi
+
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
+ fi
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ else
+ gentop="$output_objdir/${outputname}x"
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "mkdir $gentop"
+ $run mkdir "$gentop"
+ status=$?
+ if test $status -ne 0 && test ! -d "$gentop"; then
+ exit $status
+ fi
+ generated="$generated $gentop"
+
+ for xlib in $convenience; do
+ # Extract the objects.
+ case $xlib in
+ [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+ *) xabs=`pwd`"/$xlib" ;;
+ esac
+ xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+ xdir="$gentop/$xlib"
+
+ $show "${rm}r $xdir"
+ $run ${rm}r "$xdir"
+ $show "mkdir $xdir"
+ $run mkdir "$xdir"
+ status=$?
+ if test $status -ne 0 && test ! -d "$xdir"; then
+ exit $status
+ fi
+ $show "(cd $xdir && $AR x $xabs)"
+ $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+ libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
+ done
+ fi
+ fi
+
+ if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+ eval flag=\"$thread_safe_flag_spec\"
+ linker_flags="$linker_flags $flag"
+ fi
+
+ # Make a backup of the uninstalled library when relinking
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $?
+ fi
+
+ # Do each of the archive commands.
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ eval cmds=\"$archive_expsym_cmds\"
+ else
+ save_deplibs="$deplibs"
+ for conv in $convenience; do
+ tmp_deplibs=
+ for test_deplib in $deplibs; do
+ if test "$test_deplib" != "$conv"; then
+ tmp_deplibs="$tmp_deplibs $test_deplib"
+ fi
+ done
+ deplibs="$tmp_deplibs"
+ done
+ eval cmds=\"$archive_cmds\"
+ deplibs="$save_deplibs"
+ fi
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
+ exit 0
+ fi
+
+ # Create links to the real library.
+ for linkname in $linknames; do
+ if test "$realname" != "$linkname"; then
+ $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
+ $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
+ fi
+ done
+
+ # If -module or -export-dynamic was specified, set the dlname.
+ if test "$module" = yes || test "$export_dynamic" = yes; then
+ # On all known operating systems, these are identical.
+ dlname="$soname"
+ fi
+ fi
+ ;;
+
+ obj)
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
+ fi
+
+ case $output in
+ *.lo)
+ if test -n "$objs$old_deplibs"; then
+ $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
+ exit 1
+ fi
+ libobj="$output"
+ obj=`$echo "X$output" | $Xsed -e "$lo2o"`
+ ;;
+ *)
+ libobj=
+ obj="$output"
+ ;;
+ esac
+
+ # Delete the old objects.
+ $run $rm $obj $libobj
+
+ # Objects from convenience libraries. This assumes
+ # single-version convenience libraries. Whenever we create
+ # different ones for PIC/non-PIC, this we'll have to duplicate
+ # the extraction.
+ reload_conv_objs=
+ gentop=
+ # reload_cmds runs $LD directly, so let us get rid of
+ # -Wl from whole_archive_flag_spec
+ wl=
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
+ else
+ gentop="$output_objdir/${obj}x"
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "mkdir $gentop"
+ $run mkdir "$gentop"
+ status=$?
+ if test $status -ne 0 && test ! -d "$gentop"; then
+ exit $status
+ fi
+ generated="$generated $gentop"
+
+ for xlib in $convenience; do
+ # Extract the objects.
+ case $xlib in
+ [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+ *) xabs=`pwd`"/$xlib" ;;
+ esac
+ xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+ xdir="$gentop/$xlib"
+
+ $show "${rm}r $xdir"
+ $run ${rm}r "$xdir"
+ $show "mkdir $xdir"
+ $run mkdir "$xdir"
+ status=$?
+ if test $status -ne 0 && test ! -d "$xdir"; then
+ exit $status
+ fi
+ $show "(cd $xdir && $AR x $xabs)"
+ $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+ reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
+ done
+ fi
+ fi
+
+ # Create the old-style object.
+ reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+ output="$obj"
+ eval cmds=\"$reload_cmds\"
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Exit if we aren't doing a library object file.
+ if test -z "$libobj"; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit 0
+ fi
+
+ if test "$build_libtool_libs" != yes; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we don't
+ # accidentally link it into a program.
+ $show "echo timestamp > $libobj"
+ $run eval "echo timestamp > $libobj" || exit $?
+ exit 0
+ fi
+
+ if test -n "$pic_flag" || test "$pic_mode" != default; then
+ # Only do commands if we really have different PIC objects.
+ reload_objs="$libobjs $reload_conv_objs"
+ output="$libobj"
+ eval cmds=\"$reload_cmds\"
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ else
+ # Just create a symlink.
+ $show $rm $libobj
+ $run $rm $libobj
+ xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$libobj"; then
+ xdir="."
+ else
+ xdir="$xdir"
+ fi
+ baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
+ oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"`
+ $show "(cd $xdir && $LN_S $oldobj $baseobj)"
+ $run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || exit $?
+ fi
+
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit 0
+ ;;
+
+ prog)
+ case $host in
+ *cygwin*) output=`echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
+ esac
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
+ fi
+
+ if test "$preload" = yes; then
+ if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown &&
+ test "$dlopen_self_static" = unknown; then
+ $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
+ fi
+ fi
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ case $host in
+ *darwin*)
+ # Don't allow lazy linking, it breaks C++ global constructors
+ compile_command="$compile_command ${wl}-bind_at_load"
+ finalize_command="$finalize_command ${wl}-bind_at_load"
+ ;;
+ esac
+ ;;
+ esac
+
+ compile_command="$compile_command $compile_deplibs"
+ finalize_command="$finalize_command $finalize_deplibs"
+
+ if test -n "$rpath$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ for libdir in $rpath $xrpath; do
+ # This is the magic to use -rpath.
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ fi
+
+ # Now hardcode the library paths
+ rpath=
+ hardcode_libdirs=
+ for libdir in $compile_rpath $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ case :$dllsearchpath: in
+ *":$libdir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$libdir";;
+ esac
+ ;;
+ esac
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ compile_rpath="$rpath"
+
+ rpath=
+ hardcode_libdirs=
+ for libdir in $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$finalize_perm_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ finalize_rpath="$rpath"
+
+ if test -n "$libobjs" && test "$build_old_libs" = yes; then
+ # Transform all the library objects into standard objects.
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ fi
+
+ dlsyms=
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ if test -n "$NM" && test -n "$global_symbol_pipe"; then
+ dlsyms="${outputname}S.c"
+ else
+ $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
+ fi
+ fi
+
+ if test -n "$dlsyms"; then
+ case $dlsyms in
+ "") ;;
+ *.c)
+ # Discover the nlist of each of the dlfiles.
+ nlist="$output_objdir/${outputname}.nm"
+
+ $show "$rm $nlist ${nlist}S ${nlist}T"
+ $run $rm "$nlist" "${nlist}S" "${nlist}T"
+
+ # Parse the name list into a source file.
+ $show "creating $output_objdir/$dlsyms"
+
+ test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
+/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define lt_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */\
+"
+
+ if test "$dlself" = yes; then
+ $show "generating symbol list for \`$output'"
+
+ test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
+
+ # Add our own program objects to the symbol list.
+ progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ for arg in $progfiles; do
+ $show "extracting global C symbols from \`$arg'"
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -n "$exclude_expsyms"; then
+ $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ if test -n "$export_symbols_regex"; then
+ $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ export_symbols="$output_objdir/$output.exp"
+ $run $rm $export_symbols
+ $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+ else
+ $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
+ $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
+ $run eval 'mv "$nlist"T "$nlist"'
+ fi
+ fi
+
+ for arg in $dlprefiles; do
+ $show "extracting global C symbols from \`$arg'"
+ name=`echo "$arg" | ${SED} -e 's%^.*/%%'`
+ $run eval 'echo ": $name " >> "$nlist"'
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -z "$run"; then
+ # Make sure we have at least an empty file.
+ test -f "$nlist" || : > "$nlist"
+
+ if test -n "$exclude_expsyms"; then
+ egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+ $mv "$nlist"T "$nlist"
+ fi
+
+ # Try sorting and uniquifying the output.
+ if grep -v "^: " < "$nlist" |
+ if sort -k 3 </dev/null >/dev/null 2>&1; then
+ sort -k 3
+ else
+ sort +2
+ fi |
+ uniq > "$nlist"S; then
+ :
+ else
+ grep -v "^: " < "$nlist" > "$nlist"S
+ fi
+
+ if test -f "$nlist"S; then
+ eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
+ else
+ echo '/* NONE */' >> "$output_objdir/$dlsyms"
+ fi
+
+ $echo >> "$output_objdir/$dlsyms" "\
+
+#undef lt_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define lt_ptr void *
+#else
+# define lt_ptr char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr address;
+}
+lt_preloaded_symbols[] =
+{\
+"
+
+ eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms"
+
+ $echo >> "$output_objdir/$dlsyms" "\
+ {0, (lt_ptr) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+ fi
+
+ pic_flag_for_symtable=
+ case $host in
+ # compiling the symbol table file with pic_flag works around
+ # a FreeBSD bug that causes programs to crash when -lm is
+ # linked before any other PIC object. But we must not use
+ # pic_flag when linking with -static. The problem exists in
+ # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+ *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";;
+ esac;;
+ *-*-hpux*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag -DPIC";;
+ esac
+ esac
+
+ # Now compile the dynamic symbol file.
+ $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+ $run eval '(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+
+ # Clean up the generated files.
+ $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
+ $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
+
+ # Transform the symbol file into the correct name.
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ ;;
+ *)
+ $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
+ exit 1
+ ;;
+ esac
+ else
+ # We keep going just in case the user didn't refer to
+ # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
+ # really was required.
+
+ # Nullify the symbol file.
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+ fi
+
+ if test $need_relink = no || test "$build_libtool_libs" != yes; then
+ # Replace the output file specification.
+ compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ link_command="$compile_command$compile_rpath"
+
+ # We have no uninstalled library dependencies, so finalize right now.
+ $show "$link_command"
+ $run eval "$link_command"
+ status=$?
+
+ # Delete the generated files.
+ if test -n "$dlsyms"; then
+ $show "$rm $output_objdir/${outputname}S.${objext}"
+ $run $rm "$output_objdir/${outputname}S.${objext}"
+ fi
+
+ exit $status
+ fi
+
+ if test -n "$shlibpath_var"; then
+ # We should set the shlibpath_var
+ rpath=
+ for dir in $temp_rpath; do
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*)
+ # Absolute path.
+ rpath="$rpath$dir:"
+ ;;
+ *)
+ # Relative path: add a thisdir entry.
+ rpath="$rpath\$thisdir/$dir:"
+ ;;
+ esac
+ done
+ temp_rpath="$rpath"
+ fi
+
+ if test -n "$compile_shlibpath$finalize_shlibpath"; then
+ compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+ fi
+ if test -n "$finalize_shlibpath"; then
+ finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+ fi
+
+ compile_var=
+ finalize_var=
+ if test -n "$runpath_var"; then
+ if test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ if test -n "$finalize_perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $finalize_perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ fi
+
+ if test "$no_install" = yes; then
+ # We don't need to create a wrapper script.
+ link_command="$compile_var$compile_command$compile_rpath"
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ # Delete the old output file.
+ $run $rm $output
+ # Link the executable and exit
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+ exit 0
+ fi
+
+ if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+ $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
+ $echo "$modename: \`$output' will be relinked during installation" 1>&2
+ else
+ if test "$fast_install" != no; then
+ link_command="$finalize_var$compile_command$finalize_rpath"
+ if test "$fast_install" = yes; then
+ relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+ else
+ # fast_install is set to needless
+ relink_command=
+ fi
+ else
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+ fi
+ fi
+
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+ # Delete the old output files.
+ $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+
+ # Now create the wrapper script.
+ $show "creating $output"
+
+ # Quote the relink command for shipping.
+ if test -n "$relink_command"; then
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+ relink_command="$var=\"$var_value\"; export $var; $relink_command"
+ fi
+ done
+ relink_command="(cd `pwd`; $relink_command)"
+ relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Quote $echo for shipping.
+ if test "X$echo" = "X$SHELL $0 --fallback-echo"; then
+ case $0 in
+ [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";;
+ *) qecho="$SHELL `pwd`/$0 --fallback-echo";;
+ esac
+ qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
+ else
+ qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Only actually do things if our run command is non-null.
+ if test -z "$run"; then
+ # win32 will think the script is a binary if it has
+ # a .exe suffix, so we strip it off here.
+ case $output in
+ *.exe) output=`echo $output|${SED} 's,.exe$,,'` ;;
+ esac
+ # test for cygwin because mv fails w/o .exe extensions
+ case $host in
+ *cygwin*) exeext=.exe ;;
+ *) exeext= ;;
+ esac
+ $rm $output
+ trap "$rm $output; exit 1" 1 2 15
+
+ $echo > $output "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+ # install mode needs the following variable:
+ notinst_deplibs='$notinst_deplibs'
+else
+ # When we are sourced in execute mode, \$file and \$echo are already set.
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ echo=\"$qecho\"
+ file=\"\$0\"
+ # Make sure echo works.
+ if test \"X\$1\" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+ elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
+ # Yippee, \$echo works!
+ :
+ else
+ # Restart under the correct shell, and then maybe \$echo will work.
+ exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+ fi
+ fi\
+"
+ $echo >> $output "\
+
+ # Find the directory that this script lives in.
+ thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+ test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
+ while test -n \"\$file\"; do
+ destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+ # If there was a directory component, then change thisdir.
+ if test \"x\$destdir\" != \"x\$file\"; then
+ case \"\$destdir\" in
+ [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+ *) thisdir=\"\$thisdir/\$destdir\" ;;
+ esac
+ fi
+
+ file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+ file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
+ done
+
+ # Try to get the absolute directory name.
+ absdir=\`cd \"\$thisdir\" && pwd\`
+ test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+ if test "$fast_install" = yes; then
+ echo >> $output "\
+ program=lt-'$outputname'$exeext
+ progdir=\"\$thisdir/$objdir\"
+
+ if test ! -f \"\$progdir/\$program\" || \\
+ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+ test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+ file=\"\$\$-\$program\"
+
+ if test ! -d \"\$progdir\"; then
+ $mkdir \"\$progdir\"
+ else
+ $rm \"\$progdir/\$file\"
+ fi"
+
+ echo >> $output "\
+
+ # relink executable if necessary
+ if test -n \"\$relink_command\"; then
+ if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+ else
+ $echo \"\$relink_command_output\" >&2
+ $rm \"\$progdir/\$file\"
+ exit 1
+ fi
+ fi
+
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+ { $rm \"\$progdir/\$program\";
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+ $rm \"\$progdir/\$file\"
+ fi"
+ else
+ echo >> $output "\
+ program='$outputname'
+ progdir=\"\$thisdir/$objdir\"
+"
+ fi
+
+ echo >> $output "\
+
+ if test -f \"\$progdir/\$program\"; then"
+
+ # Export our shlibpath_var if we have one.
+ if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ $echo >> $output "\
+ # Add our own library path to $shlibpath_var
+ $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+ # Some systems cannot cope with colon-terminated $shlibpath_var
+ # The second colon is a workaround for a bug in BeOS R4 ${SED}
+ $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+ export $shlibpath_var
+"
+ fi
+
+ # fixup the dll searchpath if we need to.
+ if test -n "$dllsearchpath"; then
+ $echo >> $output "\
+ # Add the dll search path components to the executable PATH
+ PATH=$dllsearchpath:\$PATH
+"
+ fi
+
+ $echo >> $output "\
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ # Run the actual program with our arguments.
+"
+ case $host in
+ # win32 systems need to use the prog path for dll
+ # lookup to work
+ *-*-cygwin* | *-*-pw32*)
+ $echo >> $output "\
+ exec \$progdir/\$program \${1+\"\$@\"}
+"
+ ;;
+
+ # Backslashes separate directories on plain windows
+ *-*-mingw | *-*-os2*)
+ $echo >> $output "\
+ exec \$progdir\\\\\$program \${1+\"\$@\"}
+"
+ ;;
+
+ *)
+ $echo >> $output "\
+ # Export the path to the program.
+ PATH=\"\$progdir:\$PATH\"
+ export PATH
+
+ exec \$program \${1+\"\$@\"}
+"
+ ;;
+ esac
+ $echo >> $output "\
+ \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
+ exit 1
+ fi
+ else
+ # The program doesn't exist.
+ \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2
+ \$echo \"This script is just a wrapper for \$program.\" 1>&2
+ echo \"See the $PACKAGE documentation for more information.\" 1>&2
+ exit 1
+ fi
+fi\
+"
+ chmod +x $output
+ fi
+ exit 0
+ ;;
+ esac
+
+ # See if we need to build an old-fashioned archive.
+ for oldlib in $oldlibs; do
+
+ if test "$build_libtool_libs" = convenience; then
+ oldobjs="$libobjs_save"
+ addlibs="$convenience"
+ build_libtool_libs=no
+ else
+ if test "$build_libtool_libs" = module; then
+ oldobjs="$libobjs_save"
+ build_libtool_libs=no
+ else
+ oldobjs="$objs$old_deplibs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`
+ fi
+ addlibs="$old_convenience"
+ fi
+
+ if test -n "$addlibs"; then
+ gentop="$output_objdir/${outputname}x"
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "mkdir $gentop"
+ $run mkdir "$gentop"
+ status=$?
+ if test $status -ne 0 && test ! -d "$gentop"; then
+ exit $status
+ fi
+ generated="$generated $gentop"
+
+ # Add in members from convenience archives.
+ for xlib in $addlibs; do
+ # Extract the objects.
+ case $xlib in
+ [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+ *) xabs=`pwd`"/$xlib" ;;
+ esac
+ xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+ xdir="$gentop/$xlib"
+
+ $show "${rm}r $xdir"
+ $run ${rm}r "$xdir"
+ $show "mkdir $xdir"
+ $run mkdir "$xdir"
+ status=$?
+ if test $status -ne 0 && test ! -d "$xdir"; then
+ exit $status
+ fi
+ $show "(cd $xdir && $AR x $xabs)"
+ $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+ oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP`
+ done
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+ eval cmds=\"$old_archive_from_new_cmds\"
+ else
+ # Ensure that we have .o objects in place in case we decided
+ # not to build a shared library, and have fallen back to building
+ # static libs even though --disable-static was passed!
+ for oldobj in $oldobjs; do
+ if test ! -f $oldobj; then
+ xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$oldobj"; then
+ xdir="."
+ else
+ xdir="$xdir"
+ fi
+ baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'`
+ obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"`
+ $show "(cd $xdir && ${LN_S} $obj $baseobj)"
+ $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || exit $?
+ fi
+ done
+
+ eval cmds=\"$old_archive_cmds\"
+ fi
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$generated"; then
+ $show "${rm}r$generated"
+ $run ${rm}r$generated
+ fi
+
+ # Now create the libtool archive.
+ case $output in
+ *.la)
+ old_library=
+ test "$build_old_libs" = yes && old_library="$libname.$libext"
+ $show "creating $output"
+
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+ relink_command="$var=\"$var_value\"; export $var; $relink_command"
+ fi
+ done
+ # Quote the link command for shipping.
+ relink_command="(cd `pwd`; $SHELL $0 --mode=relink $libtool_args @inst_prefix_dir@)"
+ relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+
+ # Only create the output if not a dry run.
+ if test -z "$run"; then
+ for installed in no yes; do
+ if test "$installed" = yes; then
+ if test -z "$install_libdir"; then
+ break
+ fi
+ output="$output_objdir/$outputname"i
+ # Replace all uninstalled libtool libraries with the installed ones
+ newdependency_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ *.la)
+ name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+ exit 1
+ fi
+ newdependency_libs="$newdependency_libs $libdir/$name"
+ ;;
+ *) newdependency_libs="$newdependency_libs $deplib" ;;
+ esac
+ done
+ dependency_libs="$newdependency_libs"
+ newdlfiles=
+ for lib in $dlfiles; do
+ name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit 1
+ fi
+ newdlfiles="$newdlfiles $libdir/$name"
+ done
+ dlfiles="$newdlfiles"
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit 1
+ fi
+ newdlprefiles="$newdlprefiles $libdir/$name"
+ done
+ dlprefiles="$newdlprefiles"
+ fi
+ $rm $output
+ # place dlname in correct position for cygwin
+ tdlname=$dlname
+ case $host,$output,$installed,$module,$dlname in
+ *cygwin*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+ esac
+ $echo > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+ if test "$installed" = no && test $need_relink = yes; then
+ $echo >> $output "\
+relink_command=\"$relink_command\""
+ fi
+ done
+ fi
+
+ # Do a symbolic link so that the libtool archive can be found in
+ # LD_LIBRARY_PATH before the program is installed.
+ $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
+ $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
+ ;;
+ esac
+ exit 0
+ ;;
+
+ # libtool install mode
+ install)
+ modename="$modename: install"
+
+ # There may be an optional sh(1) argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+ # Allow the use of GNU shtool's install command.
+ $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then
+ # Aesthetically quote it.
+ arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$arg "
+ arg="$1"
+ shift
+ else
+ install_prog=
+ arg="$nonopt"
+ fi
+
+ # The real first argument should be the name of the installation program.
+ # Aesthetically quote it.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog$arg"
+
+ # We need to accept at least all the BSD install flags.
+ dest=
+ files=
+ opts=
+ prev=
+ install_type=
+ isdir=no
+ stripme=
+ for arg
+ do
+ if test -n "$dest"; then
+ files="$files $dest"
+ dest="$arg"
+ continue
+ fi
+
+ case $arg in
+ -d) isdir=yes ;;
+ -f) prev="-f" ;;
+ -g) prev="-g" ;;
+ -m) prev="-m" ;;
+ -o) prev="-o" ;;
+ -s)
+ stripme=" -s"
+ continue
+ ;;
+ -*) ;;
+
+ *)
+ # If the previous option needed an argument, then skip it.
+ if test -n "$prev"; then
+ prev=
+ else
+ dest="$arg"
+ continue
+ fi
+ ;;
+ esac
+
+ # Aesthetically quote the argument.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog $arg"
+ done
+
+ if test -z "$install_prog"; then
+ $echo "$modename: you must specify an install program" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prev' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test -z "$files"; then
+ if test -z "$dest"; then
+ $echo "$modename: no file or destination specified" 1>&2
+ else
+ $echo "$modename: you must specify a destination" 1>&2
+ fi
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Strip any trailing slash from the destination.
+ dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
+
+ # Check to see that the destination is a directory.
+ test -d "$dest" && isdir=yes
+ if test "$isdir" = yes; then
+ destdir="$dest"
+ destname=
+ else
+ destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$destdir" = "X$dest" && destdir=.
+ destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
+
+ # Not a directory, so check to see that there is only one file specified.
+ set dummy $files
+ if test $# -gt 2; then
+ $echo "$modename: \`$dest' is not a directory" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+ fi
+ case $destdir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ for file in $files; do
+ case $file in
+ *.lo) ;;
+ *)
+ $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ staticlibs=
+ future_libdirs=
+ current_libdirs=
+ for file in $files; do
+
+ # Do each installation.
+ case $file in
+ *.$libext)
+ # Do the static libraries later.
+ staticlibs="$staticlibs $file"
+ ;;
+
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ library_names=
+ old_library=
+ relink_command=
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Add the libdir to current_libdirs if it is the destination.
+ if test "X$destdir" = "X$libdir"; then
+ case "$current_libdirs " in
+ *" $libdir "*) ;;
+ *) current_libdirs="$current_libdirs $libdir" ;;
+ esac
+ else
+ # Note the libdir as a future libdir.
+ case "$future_libdirs " in
+ *" $libdir "*) ;;
+ *) future_libdirs="$future_libdirs $libdir" ;;
+ esac
+ fi
+
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/
+ test "X$dir" = "X$file/" && dir=
+ dir="$dir$objdir"
+
+ if test -n "$relink_command"; then
+ # Determine the prefix the user has applied to our future dir.
+ inst_prefix_dir=`$echo "$destdir" | sed "s%$libdir\$%%"`
+
+ # Don't allow the user to place us outside of our expected
+ # location b/c this prevents finding dependent libraries that
+ # are installed to the same prefix.
+ if test "$inst_prefix_dir" = "$destdir"; then
+ $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
+ exit 1
+ fi
+
+ if test -n "$inst_prefix_dir"; then
+ # Stick the inst_prefix_dir data into the link command.
+ relink_command=`$echo "$relink_command" | sed "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+ else
+ relink_command=`$echo "$relink_command" | sed "s%@inst_prefix_dir@%%"`
+ fi
+
+ $echo "$modename: warning: relinking \`$file'" 1>&2
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ exit 1
+ fi
+ fi
+
+ # See the names of the shared library.
+ set dummy $library_names
+ if test -n "$2"; then
+ realname="$2"
+ shift
+ shift
+
+ srcname="$realname"
+ test -n "$relink_command" && srcname="$realname"T
+
+ # Install the shared library and build the symlinks.
+ $show "$install_prog $dir/$srcname $destdir/$realname"
+ $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $?
+ if test -n "$stripme" && test -n "$striplib"; then
+ $show "$striplib $destdir/$realname"
+ $run eval "$striplib $destdir/$realname" || exit $?
+ fi
+
+ if test $# -gt 0; then
+ # Delete the old symlinks, and create new ones.
+ for linkname
+ do
+ if test "$linkname" != "$realname"; then
+ $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+ $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+ fi
+ done
+ fi
+
+ # Do each command in the postinstall commands.
+ lib="$destdir/$realname"
+ eval cmds=\"$postinstall_cmds\"
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Install the pseudo-library for information purposes.
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ instname="$dir/$name"i
+ $show "$install_prog $instname $destdir/$name"
+ $run eval "$install_prog $instname $destdir/$name" || exit $?
+
+ # Maybe install the static library, too.
+ test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+ ;;
+
+ *.lo)
+ # Install (i.e. copy) a libtool object.
+
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # Deduce the name of the destination old-style object file.
+ case $destfile in
+ *.lo)
+ staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
+ ;;
+ *.$objext)
+ staticdest="$destfile"
+ destfile=
+ ;;
+ *)
+ $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Install the libtool object if requested.
+ if test -n "$destfile"; then
+ $show "$install_prog $file $destfile"
+ $run eval "$install_prog $file $destfile" || exit $?
+ fi
+
+ # Install the old object if enabled.
+ if test "$build_old_libs" = yes; then
+ # Deduce the name of the old-style object file.
+ staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
+
+ $show "$install_prog $staticobj $staticdest"
+ $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+ fi
+ exit 0
+ ;;
+
+ *)
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # Do a test to see if this is really a libtool program.
+ case $host in
+ *cygwin*|*mingw*)
+ wrapper=`echo $file | ${SED} -e 's,.exe$,,'`
+ ;;
+ *)
+ wrapper=$file
+ ;;
+ esac
+ if (${SED} -e '4q' $wrapper | egrep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
+ notinst_deplibs=
+ relink_command=
+
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $wrapper ;;
+ *) . ./$wrapper ;;
+ esac
+
+ # Check the variables that should have been set.
+ if test -z "$notinst_deplibs"; then
+ $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
+ exit 1
+ fi
+
+ finalize=yes
+ for lib in $notinst_deplibs; do
+ # Check to see that each library is installed.
+ libdir=
+ if test -f "$lib"; then
+ # If there is no directory component, then add one.
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ fi
+ libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
+ if test -n "$libdir" && test ! -f "$libfile"; then
+ $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+ finalize=no
+ fi
+ done
+
+ relink_command=
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $wrapper ;;
+ *) . ./$wrapper ;;
+ esac
+
+ outputname=
+ if test "$fast_install" = no && test -n "$relink_command"; then
+ if test "$finalize" = yes && test -z "$run"; then
+ tmpdir="/tmp"
+ test -n "$TMPDIR" && tmpdir="$TMPDIR"
+ tmpdir="$tmpdir/libtool-$$"
+ if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then :
+ else
+ $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
+ continue
+ fi
+ file=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ outputname="$tmpdir/$file"
+ # Replace the output file specification.
+ relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ ${rm}r "$tmpdir"
+ continue
+ fi
+ file="$outputname"
+ else
+ $echo "$modename: warning: cannot relink \`$file'" 1>&2
+ fi
+ else
+ # Install the binary that we compiled earlier.
+ file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+ fi
+ fi
+
+ # remove .exe since cygwin /usr/bin/install will append another
+ # one anyways
+ case $install_prog,$host in
+ /usr/bin/install*,*cygwin*)
+ case $file:$destfile in
+ *.exe:*.exe)
+ # this is ok
+ ;;
+ *.exe:*)
+ destfile=$destfile.exe
+ ;;
+ *:*.exe)
+ destfile=`echo $destfile | ${SED} -e 's,.exe$,,'`
+ ;;
+ esac
+ ;;
+ esac
+ $show "$install_prog$stripme $file $destfile"
+ $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
+ test -n "$outputname" && ${rm}r "$tmpdir"
+ ;;
+ esac
+ done
+
+ for file in $staticlibs; do
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+ # Set up the ranlib parameters.
+ oldlib="$destdir/$name"
+
+ $show "$install_prog $file $oldlib"
+ $run eval "$install_prog \$file \$oldlib" || exit $?
+
+ if test -n "$stripme" && test -n "$striplib"; then
+ $show "$old_striplib $oldlib"
+ $run eval "$old_striplib $oldlib" || exit $?
+ fi
+
+ # Do each command in the postinstall commands.
+ eval cmds=\"$old_postinstall_cmds\"
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$future_libdirs"; then
+ $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+ fi
+
+ if test -n "$current_libdirs"; then
+ # Maybe just do a dry run.
+ test -n "$run" && current_libdirs=" -n$current_libdirs"
+ exec_cmd='$SHELL $0 --finish$current_libdirs'
+ else
+ exit 0
+ fi
+ ;;
+
+ # libtool finish mode
+ finish)
+ modename="$modename: finish"
+ libdirs="$nonopt"
+ admincmds=
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ for dir
+ do
+ libdirs="$libdirs $dir"
+ done
+
+ for libdir in $libdirs; do
+ if test -n "$finish_cmds"; then
+ # Do each command in the finish commands.
+ eval cmds=\"$finish_cmds\"
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || admincmds="$admincmds
+ $cmd"
+ done
+ IFS="$save_ifs"
+ fi
+ if test -n "$finish_eval"; then
+ # Do the single finish_eval.
+ eval cmds=\"$finish_eval\"
+ $run eval "$cmds" || admincmds="$admincmds
+ $cmds"
+ fi
+ done
+ fi
+
+ # Exit here if they wanted silent mode.
+ test "$show" = ":" && exit 0
+
+ echo "----------------------------------------------------------------------"
+ echo "Libraries have been installed in:"
+ for libdir in $libdirs; do
+ echo " $libdir"
+ done
+ echo
+ echo "If you ever happen to want to link against installed libraries"
+ echo "in a given directory, LIBDIR, you must either use libtool, and"
+ echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+ echo "flag during linking and do at least one of the following:"
+ if test -n "$shlibpath_var"; then
+ echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
+ echo " during execution"
+ fi
+ if test -n "$runpath_var"; then
+ echo " - add LIBDIR to the \`$runpath_var' environment variable"
+ echo " during linking"
+ fi
+ if test -n "$hardcode_libdir_flag_spec"; then
+ libdir=LIBDIR
+ eval flag=\"$hardcode_libdir_flag_spec\"
+
+ echo " - use the \`$flag' linker flag"
+ fi
+ if test -n "$admincmds"; then
+ echo " - have your system administrator run these commands:$admincmds"
+ fi
+ if test -f /etc/ld.so.conf; then
+ echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+ fi
+ echo
+ echo "See any operating system documentation about shared libraries for"
+ echo "more information, such as the ld(1) and ld.so(8) manual pages."
+ echo "----------------------------------------------------------------------"
+ exit 0
+ ;;
+
+ # libtool execute mode
+ execute)
+ modename="$modename: execute"
+
+ # The first argument is the command name.
+ cmd="$nonopt"
+ if test -z "$cmd"; then
+ $echo "$modename: you must specify a COMMAND" 1>&2
+ $echo "$help"
+ exit 1
+ fi
+
+ # Handle -dlopen flags immediately.
+ for file in $execute_dlfiles; do
+ if test ! -f "$file"; then
+ $echo "$modename: \`$file' is not a file" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ dir=
+ case $file in
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Read the libtool library.
+ dlname=
+ library_names=
+
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Skip this library if it cannot be dlopened.
+ if test -z "$dlname"; then
+ # Warn if it was a shared library.
+ test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
+ continue
+ fi
+
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+
+ if test -f "$dir/$objdir/$dlname"; then
+ dir="$dir/$objdir"
+ else
+ $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+ exit 1
+ fi
+ ;;
+
+ *.lo)
+ # Just add the directory containing the .lo file.
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ ;;
+
+ *)
+ $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+ continue
+ ;;
+ esac
+
+ # Get the absolute pathname.
+ absdir=`cd "$dir" && pwd`
+ test -n "$absdir" && dir="$absdir"
+
+ # Now add the directory to shlibpath_var.
+ if eval "test -z \"\$$shlibpath_var\""; then
+ eval "$shlibpath_var=\"\$dir\""
+ else
+ eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+ fi
+ done
+
+ # This variable tells wrapper scripts just to set shlibpath_var
+ # rather than running their programs.
+ libtool_execute_magic="$magic"
+
+ # Check if any of the arguments is a wrapper script.
+ args=
+ for file
+ do
+ case $file in
+ -*) ;;
+ *)
+ # Do a test to see if this is really a libtool program.
+ if (${SED} -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Transform arg to wrapped name.
+ file="$progdir/$program"
+ fi
+ ;;
+ esac
+ # Quote arguments (to preserve shell metacharacters).
+ file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
+ args="$args \"$file\""
+ done
+
+ if test -z "$run"; then
+ if test -n "$shlibpath_var"; then
+ # Export the shlibpath_var.
+ eval "export $shlibpath_var"
+ fi
+
+ # Restore saved enviroment variables
+ if test "${save_LC_ALL+set}" = set; then
+ LC_ALL="$save_LC_ALL"; export LC_ALL
+ fi
+ if test "${save_LANG+set}" = set; then
+ LANG="$save_LANG"; export LANG
+ fi
+
+ # Now prepare to actually exec the command.
+ exec_cmd="\$cmd$args"
+ else
+ # Display what would be done.
+ if test -n "$shlibpath_var"; then
+ eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+ $echo "export $shlibpath_var"
+ fi
+ $echo "$cmd$args"
+ exit 0
+ fi
+ ;;
+
+ # libtool clean and uninstall mode
+ clean | uninstall)
+ modename="$modename: $mode"
+ rm="$nonopt"
+ files=
+ rmforce=
+ exit_status=0
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ for arg
+ do
+ case $arg in
+ -f) rm="$rm $arg"; rmforce=yes ;;
+ -*) rm="$rm $arg" ;;
+ *) files="$files $arg" ;;
+ esac
+ done
+
+ if test -z "$rm"; then
+ $echo "$modename: you must specify an RM program" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ rmdirs=
+
+ for file in $files; do
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$dir" = "X$file"; then
+ dir=.
+ objdir="$objdir"
+ else
+ objdir="$dir/$objdir"
+ fi
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ test $mode = uninstall && objdir="$dir"
+
+ # Remember objdir for removal later, being careful to avoid duplicates
+ if test $mode = clean; then
+ case " $rmdirs " in
+ *" $objdir "*) ;;
+ *) rmdirs="$rmdirs $objdir" ;;
+ esac
+ fi
+
+ # Don't error if the file doesn't exist and rm -f was used.
+ if (test -L "$file") >/dev/null 2>&1 \
+ || (test -h "$file") >/dev/null 2>&1 \
+ || test -f "$file"; then
+ :
+ elif test -d "$file"; then
+ exit_status=1
+ continue
+ elif test "$rmforce" = yes; then
+ continue
+ fi
+
+ rmfiles="$file"
+
+ case $name in
+ *.la)
+ # Possibly a libtool archive, so verify it.
+ if (${SED} -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ . $dir/$name
+
+ # Delete the libtool libraries and symlinks.
+ for n in $library_names; do
+ rmfiles="$rmfiles $objdir/$n"
+ done
+ test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+ test $mode = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+
+ if test $mode = uninstall; then
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ eval cmds=\"$postuninstall_cmds\"
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd"
+ if test $? != 0 && test "$rmforce" != yes; then
+ exit_status=1
+ fi
+ done
+ IFS="$save_ifs"
+ fi
+
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ eval cmds=\"$old_postuninstall_cmds\"
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd"
+ if test $? != 0 && test "$rmforce" != yes; then
+ exit_status=1
+ fi
+ done
+ IFS="$save_ifs"
+ fi
+ # FIXME: should reinstall the best remaining shared library.
+ fi
+ fi
+ ;;
+
+ *.lo)
+ if test "$build_old_libs" = yes; then
+ oldobj=`$echo "X$name" | $Xsed -e "$lo2o"`
+ rmfiles="$rmfiles $dir/$oldobj"
+ fi
+ ;;
+
+ *)
+ # Do a test to see if this is a libtool program.
+ if test $mode = clean &&
+ (${SED} -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ relink_command=
+ . $dir/$file
+
+ rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+ if test "$fast_install" = yes && test -n "$relink_command"; then
+ rmfiles="$rmfiles $objdir/lt-$name"
+ fi
+ fi
+ ;;
+ esac
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles || exit_status=1
+ done
+
+ # Try to remove the ${objdir}s in the directories where we deleted files
+ for dir in $rmdirs; do
+ if test -d "$dir"; then
+ $show "rmdir $dir"
+ $run rmdir $dir >/dev/null 2>&1
+ fi
+ done
+
+ exit $exit_status
+ ;;
+
+ "")
+ $echo "$modename: you must specify a MODE" 1>&2
+ $echo "$generic_help" 1>&2
+ exit 1
+ ;;
+ esac
+
+ if test -z "$exec_cmd"; then
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$generic_help" 1>&2
+ exit 1
+ fi
+fi # test -z "$show_help"
+
+if test -n "$exec_cmd"; then
+ eval exec $exec_cmd
+ exit 1
+fi
+
+# We need to display help for each of the modes.
+case $mode in
+"") $echo \
+"Usage: $modename [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+ --config show all configuration variables
+ --debug enable verbose shell tracing
+-n, --dry-run display commands without modifying any files
+ --features display basic configuration information and exit
+ --finish same as \`--mode=finish'
+ --help display this help message and exit
+ --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS]
+ --quiet same as \`--silent'
+ --silent don't print informational messages
+ --version print version information
+
+MODE must be one of the following:
+
+ clean remove files from the build directory
+ compile compile a source file into a libtool object
+ execute automatically set library path, then run a program
+ finish complete the installation of libtool libraries
+ install install libraries or executables
+ link create a library or an executable
+ uninstall remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for
+a more detailed description of MODE."
+ exit 0
+ ;;
+
+clean)
+ $echo \
+"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+compile)
+ $echo \
+"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+ -o OUTPUT-FILE set the output file name to OUTPUT-FILE
+ -prefer-pic try to building PIC objects only
+ -prefer-non-pic try to building non-PIC objects only
+ -static always build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+ ;;
+
+execute)
+ $echo \
+"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+ -dlopen FILE add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+ ;;
+
+finish)
+ $echo \
+"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges. Use
+the \`--dry-run' option if you just want to see what would be executed."
+ ;;
+
+install)
+ $echo \
+"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command. The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+ ;;
+
+link)
+ $echo \
+"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+ -all-static do not do any dynamic linking at all
+ -avoid-version do not add a version suffix if possible
+ -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
+ -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
+ -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+ -export-symbols SYMFILE
+ try to export only the symbols listed in SYMFILE
+ -export-symbols-regex REGEX
+ try to export only the symbols matching REGEX
+ -LLIBDIR search LIBDIR for required installed libraries
+ -lNAME OUTPUT-FILE requires the installed library libNAME
+ -module build a library that can dlopened
+ -no-fast-install disable the fast-install mode
+ -no-install link a not-installable executable
+ -no-undefined declare that a library does not refer to external symbols
+ -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
+ -release RELEASE specify package release information
+ -rpath LIBDIR the created library will eventually be installed in LIBDIR
+ -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
+ -static do not do any dynamic linking of libtool libraries
+ -version-info CURRENT[:REVISION[:AGE]]
+ specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename. Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+ ;;
+
+uninstall)
+ $echo \
+"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+*)
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+esac
+
+echo
+$echo "Try \`$modename --help' for more information about other modes."
+
+exit 0
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/src/pal/src/libunwind/configure.ac b/src/pal/src/libunwind/configure.ac
new file mode 100644
index 0000000000..0c5125971f
--- /dev/null
+++ b/src/pal/src/libunwind/configure.ac
@@ -0,0 +1,445 @@
+define(pkg_major, 1)
+define(pkg_minor, 3)
+define(pkg_extra, -rc1)
+define(pkg_maintainer, libunwind-devel@nongnu.org)
+define(mkvers, $1.$2$3)
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT([libunwind],[mkvers(pkg_major, pkg_minor, pkg_extra)],[pkg_maintainer])
+AC_CONFIG_SRCDIR(src/mi/backtrace.c)
+AC_CONFIG_AUX_DIR(config)
+AC_CANONICAL_TARGET
+AM_INIT_AUTOMAKE([1.6 subdir-objects])
+AM_MAINTAINER_MODE
+AC_CONFIG_HEADERS([include/config.h])
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
+LT_INIT
+AM_PROG_AS
+AM_PROG_CC_C_O
+
+dnl Checks for libraries.
+AC_CHECK_LIB(uca, __uc_get_grs)
+OLD_LIBS=${LIBS}
+AC_SEARCH_LIBS(dlopen, dl)
+LIBS=${OLD_LIBS}
+case "$ac_cv_search_dlopen" in
+ -l*) DLLIB=$ac_cv_search_dlopen;;
+ *) DLLIB="";;
+esac
+
+CHECK_ATOMIC_OPS
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(asm/ptrace_offsets.h endian.h sys/endian.h execinfo.h \
+ ia64intrin.h sys/uc_access.h unistd.h signal.h sys/types.h \
+ sys/procfs.h sys/ptrace.h byteswap.h elf.h sys/elf.h link.h sys/link.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_C_INLINE
+AC_TYPE_SIZE_T
+AC_CHECK_SIZEOF(off_t)
+
+CPPFLAGS="${CPPFLAGS} -D_GNU_SOURCE"
+
+AC_CHECK_MEMBERS([struct dl_phdr_info.dlpi_subs],,,[#include <link.h>])
+AC_CHECK_TYPES([struct elf_prstatus, struct prstatus], [], [],
+[$ac_includes_default
+#if HAVE_SYS_PROCFS_H
+# include <sys/procfs.h>
+#endif
+])
+
+AC_CHECK_DECLS([PTRACE_POKEUSER, PTRACE_POKEDATA, PTRACE_SETREGSET,
+PTRACE_TRACEME, PTRACE_CONT, PTRACE_SINGLESTEP,
+PTRACE_SYSCALL, PT_IO, PT_GETREGS,
+PT_GETFPREGS, PT_CONTINUE, PT_TRACE_ME,
+PT_STEP, PT_SYSCALL], [], [],
+[$ac_includes_default
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <sys/ptrace.h>
+])
+
+dnl Checks for library functions.
+AC_CHECK_FUNCS(dl_iterate_phdr dl_phdr_removals_counter dlmodinfo getunwind \
+ ttrace mincore)
+
+AC_MSG_CHECKING([if building with AltiVec])
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#ifndef __ALTIVEC__
+# error choke
+#endif
+]])], [use_altivec=yes],[use_altivec=no])
+AM_CONDITIONAL(USE_ALTIVEC, [test x$use_altivec = xyes])
+AC_MSG_RESULT([$use_altivec])
+
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#ifndef __powerpc64__
+# error choke
+#endif
+]])], [ppc_bits=64], [ppc_bits=32])
+
+AC_DEFUN([SET_ARCH],[
+ AS_CASE([$1],
+ [aarch64*],[$2=aarch64],
+ [arm*],[$2=arm],
+ [i?86],[$2=x86],
+ [hppa*],[$2=hppa],
+ [mips*],[$2=mips],
+ [powerpc*],[$2=ppc$ppc_bits],
+ [sh*],[$2=sh],
+ [amd64],[$2=x86_64],
+ [tile*],[$2=tilegx],
+ [$2=$1])
+]) dnl SET_ARCH
+
+SET_ARCH([$build_cpu],[build_arch])
+SET_ARCH([$host_cpu],[host_arch])
+SET_ARCH([$target_cpu],[target_arch])
+
+# Check for Android
+AC_MSG_CHECKING([for Android])
+android="no"
+case "$host_os" in
+ *android*)
+ android="yes"
+ AC_MSG_RESULT([yes])
+ ;;
+ *)
+ AC_MSG_RESULT([no])
+ ;;
+esac
+
+AC_ARG_ENABLE(coredump,
+ AS_HELP_STRING([--enable-coredump],[building libunwind-coredump library]),,
+ [AS_CASE([$host_arch], [aarch64*|arm*|mips*|sh*|x86*|tile*], [enable_coredump=yes], [enable_coredump=no])]
+)
+
+AC_MSG_CHECKING([if we should build libunwind-coredump])
+AC_MSG_RESULT([$enable_coredump])
+
+AC_ARG_ENABLE(ptrace,
+ AS_HELP_STRING([--enable-ptrace],[building libunwind-ptrace library]),,
+ [AC_CHECK_HEADER([sys/ptrace.h], [enable_ptrace=yes], [enable_ptrace=no])]
+)
+
+AC_MSG_CHECKING([if we should build libunwind-ptrace])
+AC_MSG_RESULT([$enable_ptrace])
+
+AC_ARG_ENABLE(setjmp,
+ AS_HELP_STRING([--enable-setjmp],[building libunwind-setjmp library]),,
+ [AS_IF([test x$target_arch == x$host_arch], [enable_setjmp=yes], [enable_setjmp=no])]
+)
+
+AC_ARG_ENABLE(documentation,
+ AS_HELP_STRING([--disable-documentation],[Disable generating the man pages]),,
+ [enable_documentation=yes])
+
+AC_ARG_ENABLE(tests,
+ AS_HELP_STRING([--disable-tests],[Disable tests build]),,
+ [enable_tests=yes])
+
+AC_MSG_CHECKING([if we should build libunwind-setjmp])
+AC_MSG_RESULT([$enable_setjmp])
+
+AC_MSG_CHECKING([for build architecture])
+AC_MSG_RESULT([$build_arch])
+AC_MSG_CHECKING([for host architecture])
+AC_MSG_RESULT([$host_arch])
+AC_MSG_CHECKING([for target architecture])
+AC_MSG_RESULT([$target_arch])
+AC_MSG_CHECKING([for target operating system])
+AC_MSG_RESULT([$target_os])
+
+AM_CONDITIONAL(BUILD_COREDUMP, test x$enable_coredump = xyes)
+AM_CONDITIONAL(BUILD_PTRACE, test x$enable_ptrace = xyes)
+AM_CONDITIONAL(BUILD_SETJMP, test x$enable_setjmp = xyes)
+AM_CONDITIONAL(NO_PTRACE_TEST, test x$build_arch != x$host_arch)
+AM_CONDITIONAL(REMOTE_ONLY, test x$target_arch != x$host_arch)
+AM_CONDITIONAL(ARCH_AARCH64, test x$target_arch = xaarch64)
+AM_CONDITIONAL(ARCH_ARM, test x$target_arch = xarm)
+AM_CONDITIONAL(ARCH_IA64, test x$target_arch = xia64)
+AM_CONDITIONAL(ARCH_HPPA, test x$target_arch = xhppa)
+AM_CONDITIONAL(ARCH_MIPS, test x$target_arch = xmips)
+AM_CONDITIONAL(ARCH_X86, test x$target_arch = xx86)
+AM_CONDITIONAL(ARCH_X86_64, test x$target_arch = xx86_64)
+AM_CONDITIONAL(ARCH_PPC32, test x$target_arch = xppc32)
+AM_CONDITIONAL(ARCH_PPC64, test x$target_arch = xppc64)
+AM_CONDITIONAL(ARCH_SH, test x$target_arch = xsh)
+AM_CONDITIONAL(ARCH_TILEGX, test x$target_arch = xtilegx)
+AM_CONDITIONAL(OS_LINUX, expr x$target_os : xlinux >/dev/null)
+AM_CONDITIONAL(OS_HPUX, expr x$target_os : xhpux >/dev/null)
+AM_CONDITIONAL(OS_FREEBSD, expr x$target_os : xfreebsd >/dev/null)
+AM_CONDITIONAL(OS_QNX, expr x$target_os : xnto-qnx >/dev/null)
+
+AC_MSG_CHECKING([for ELF helper width])
+case "${target_arch}" in
+(arm|hppa|ppc32|x86|sh) use_elf32=yes; AC_MSG_RESULT([32]);;
+(aarch64|ia64|ppc64|x86_64|tilegx) use_elf64=yes; AC_MSG_RESULT([64]);;
+(mips) use_elfxx=yes; AC_MSG_RESULT([xx]);;
+*) AC_MSG_ERROR([Unknown ELF target: ${target_arch}])
+esac
+AM_CONDITIONAL(USE_ELF32, [test x$use_elf32 = xyes])
+AM_CONDITIONAL(USE_ELF64, [test x$use_elf64 = xyes])
+AM_CONDITIONAL(USE_ELFXX, [test x$use_elfxx = xyes])
+
+AC_MSG_CHECKING([whether to include DWARF support])
+if test x$target_arch != xia64; then
+ use_dwarf=yes
+else
+ use_dwarf=no
+fi
+AM_CONDITIONAL(USE_DWARF, [test x$use_dwarf = xyes])
+AC_MSG_RESULT([$use_dwarf])
+
+if test x$target_arch = xppc64; then
+ libdir='${exec_prefix}/lib64'
+ AC_MSG_NOTICE([PowerPC64 detected, lib will be installed ${libdir}]);
+ AC_SUBST([libdir])
+fi
+
+AC_MSG_CHECKING([whether to restrict build to remote support])
+if test x$target_arch != x$host_arch; then
+ CPPFLAGS="${CPPFLAGS} -DUNW_REMOTE_ONLY"
+ remote_only=yes
+else
+ remote_only=no
+fi
+AC_MSG_RESULT([$remote_only])
+
+AC_MSG_CHECKING([whether to enable debug support])
+AC_ARG_ENABLE(debug,
+AS_HELP_STRING([--enable-debug],[turn on debug support (slows down execution)]))
+if test x$enable_debug = xyes; then
+ CPPFLAGS="${CPPFLAGS} -DDEBUG"
+else
+ CPPFLAGS="${CPPFLAGS} -DNDEBUG"
+fi
+AC_MSG_RESULT([$enable_debug])
+
+AC_MSG_CHECKING([whether to enable C++ exception support])
+AC_ARG_ENABLE(cxx_exceptions,
+AS_HELP_STRING([--enable-cxx-exceptions],[use libunwind to handle C++ exceptions]),,
+[
+# C++ exception handling doesn't work too well on x86
+case $target_arch in
+ x86*) enable_cxx_exceptions=no;;
+ aarch64*) enable_cxx_exceptions=no;;
+ arm*) enable_cxx_exceptions=no;;
+ mips*) enable_cxx_exceptions=no;;
+ tile*) enable_cxx_exceptions=no;;
+ *) enable_cxx_exceptions=yes;;
+esac
+])
+
+AM_CONDITIONAL([SUPPORT_CXX_EXCEPTIONS], [test x$enable_cxx_exceptions = xyes])
+AC_MSG_RESULT([$enable_cxx_exceptions])
+
+AC_MSG_CHECKING([whether to load .debug_frame sections])
+AC_ARG_ENABLE(debug_frame,
+AS_HELP_STRING([--enable-debug-frame],[Load the ".debug_frame" section if available]),, [
+case "${target_arch}" in
+ (arm) enable_debug_frame=yes;;
+ (aarch64) enable_debug_frame=yes;;
+ (*) enable_debug_frame=no;;
+esac])
+if test x$enable_debug_frame = xyes; then
+ AC_DEFINE([CONFIG_DEBUG_FRAME], [], [Enable Debug Frame])
+fi
+AC_MSG_RESULT([$enable_debug_frame])
+
+AC_MSG_CHECKING([whether to block signals during mutex ops])
+AC_ARG_ENABLE(block_signals,
+AS_HELP_STRING([--enable-block-signals],[Block signals before performing mutex operations]),,
+[enable_block_signals=yes])
+if test x$enable_block_signals = xyes; then
+ AC_DEFINE([CONFIG_BLOCK_SIGNALS], [], [Block signals before mutex operations])
+fi
+AC_MSG_RESULT([$enable_block_signals])
+
+AC_MSG_CHECKING([whether to validate memory addresses before use])
+AC_ARG_ENABLE(conservative_checks,
+AS_HELP_STRING([--enable-conservative-checks],[Validate all memory addresses before use]),,
+[enable_conservative_checks=yes])
+if test x$enable_conservative_checks = xyes; then
+ AC_DEFINE(CONSERVATIVE_CHECKS, 1,
+ [Define to 1 if you want every memory access validated])
+fi
+AC_MSG_RESULT([$enable_conservative_checks])
+
+AC_MSG_CHECKING([whether to enable msabi support])
+AC_ARG_ENABLE(msabi_support,
+AS_HELP_STRING([--enable-msabi-support],[Enables support for Microsoft ABI extensions]))
+if test x$enable_msabi_support = xyes; then
+ AC_DEFINE([CONFIG_MSABI_SUPPORT], [], [Support for Microsoft ABI extensions])
+fi
+AC_MSG_RESULT([$enable_msabi_support])
+
+LIBLZMA=
+AC_MSG_CHECKING([whether to support LZMA-compressed symbol tables])
+AC_ARG_ENABLE(minidebuginfo,
+AS_HELP_STRING([--enable-minidebuginfo], [Enables support for LZMA-compressed symbol tables]),, [enable_minidebuginfo=auto])
+AC_MSG_RESULT([$enable_minidebuginfo])
+if test x$enable_minidebuginfo != xno; then
+ AC_CHECK_LIB([lzma], [lzma_mf_is_supported],
+ [LIBLZMA=-llzma
+ AC_DEFINE([HAVE_LZMA], [1], [Define if you have liblzma])
+ enable_minidebuginfo=yes],
+ [if test x$enable_minidebuginfo = xyes; then
+ AC_MSG_FAILURE([liblzma not found])
+ fi])
+fi
+AC_SUBST([LIBLZMA])
+AM_CONDITIONAL(HAVE_LZMA, test x$enable_minidebuginfo = xyes)
+
+AC_MSG_CHECKING([whether to support UNW_CACHE_PER_THREAD])
+AC_ARG_ENABLE([per-thread-cache],
+AS_HELP_STRING([--enable-per-thread-cache], [build with support for UNW_CACHE_PER_THREAD (which imposes a hight TLS memory usage) (default: disabled)]))
+AC_MSG_RESULT([$enable_per_thread_cache])
+AS_IF([test x$enable_per_thread_cache = xyes], [
+ LIBUNWIND___THREAD
+ AS_IF([test x$libc_cv_gcc___thread = xno], [
+ AC_MSG_FAILURE([UNW_CACHE_PER_THREAD requires __thread])
+ ])
+])
+
+AC_MSG_CHECKING([for Intel compiler])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[#ifndef __INTEL_COMPILER
+#error choke me
+#endif]])],[intel_compiler=yes],[intel_compiler=no])
+
+if test x$GCC = xyes -a x$intel_compiler != xyes; then
+ CFLAGS="${CFLAGS} -fexceptions -Wall -Wsign-compare"
+fi
+AC_MSG_RESULT([$intel_compiler])
+
+AC_MSG_CHECKING([for QCC compiler])
+AS_CASE([$CC], [qcc*|QCC*], [qcc_compiler=yes], [qcc_compiler=no])
+AC_MSG_RESULT([$qcc_compiler])
+
+if test x$intel_compiler = xyes; then
+ AC_MSG_CHECKING([if linker supports -static-libcxa])
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS -static-libcxa"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[have_static_libcxa=yes],[have_static_libcxa=no])
+ LDFLAGS="$save_LDFLAGS"
+ if test "x$have_static_libcxa" = xyes; then
+ LDFLAGS_STATIC_LIBCXA="-XCClinker -static-libcxa"
+ fi
+ AC_MSG_RESULT([$have_static_libcxa])
+fi
+
+if test x$qcc_compiler = xyes; then
+ LDFLAGS_NOSTARTFILES="-XCClinker -Wc,-nostartfiles"
+else
+ LDFLAGS_NOSTARTFILES="-XCClinker -nostartfiles"
+fi
+
+if test x$GCC = xyes -a x$intel_compiler != xyes -a x$qcc_compiler != xyes -a x$android != xyes; then
+ LIBCRTS="-lgcc_s"
+fi
+
+AC_MSG_CHECKING([for __builtin___clear_cache])
+AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[]], [[__builtin___clear_cache(0, 0)]])],
+ [have__builtin___clear_cache=yes],
+ [have__builtin___clear_cache=no])
+if test x$have__builtin___clear_cache = xyes; then
+ AC_DEFINE([HAVE__BUILTIN___CLEAR_CACHE], [1],
+ [Defined if __builtin___clear_cache() is available])
+fi
+AC_MSG_RESULT([$have__builtin___clear_cache])
+
+AC_MSG_CHECKING([for __builtin_unreachable])
+AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[]], [[__builtin_unreachable()]])],
+ [have__builtin_unreachable=yes],
+ [have__builtin_unreachable=no])
+if test x$have__builtin_unreachable = xyes; then
+ AC_DEFINE([HAVE__BUILTIN_UNREACHABLE], [1],
+ [Defined if __builtin_unreachable() is available])
+fi
+AC_MSG_RESULT([$have__builtin_unreachable])
+
+AC_MSG_CHECKING([for __sync atomics])
+AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[]], [[
+ __sync_bool_compare_and_swap((int *)0, 0, 1);
+ __sync_fetch_and_add((int *)0, 1);
+ ]])],
+ [have_sync_atomics=yes],
+ [have_sync_atomics=no])
+if test x$have_sync_atomics = xyes; then
+ AC_DEFINE([HAVE_SYNC_ATOMICS], [1],
+ [Defined if __sync atomics are available])
+fi
+AC_MSG_RESULT([$have_sync_atomics])
+
+CCASFLAGS="${CCASFLAGS} ${CPPFLAGS}"
+
+arch="$target_arch"
+ARCH=`echo $target_arch | tr [a-z] [A-Z]`
+
+dnl create shell variables from the M4 macros:
+PKG_MAJOR=pkg_major
+PKG_MINOR=pkg_minor
+PKG_EXTRA=pkg_extra
+PKG_MAINTAINER=pkg_maintainer
+
+old_LIBS="$LIBS"
+LIBS=""
+AC_SEARCH_LIBS(backtrace, execinfo)
+LIBS="$old_LIBS"
+case "$ac_cv_search_backtrace" in
+ -l*) BACKTRACELIB=$ac_cv_search_backtrace;;
+ *) BACKTRACELIB="";;
+esac
+
+
+AC_SUBST(build_arch)
+AC_SUBST(target_os)
+AC_SUBST(arch)
+AC_SUBST(ARCH)
+AC_SUBST(LDFLAGS_STATIC_LIBCXA)
+AC_SUBST(LDFLAGS_NOSTARTFILES)
+AC_SUBST(LIBCRTS)
+AC_SUBST(PKG_MAJOR)
+AC_SUBST(PKG_MINOR)
+AC_SUBST(PKG_EXTRA)
+AC_SUBST(PKG_MAINTAINER)
+AC_SUBST(enable_cxx_exceptions)
+AC_SUBST(enable_debug_frame)
+AC_SUBST(DLLIB)
+AC_SUBST(BACKTRACELIB)
+
+AC_PATH_PROG([LATEX2MAN],[latex2man])
+if test "x$LATEX2MAN" = "x"; then
+ AC_MSG_WARN([latex2man not found. Install latex2man. Disabling docs.])
+ enable_documentation="no";
+fi
+
+AM_CONDITIONAL([CONFIG_DOCS], [test x$enable_documentation = xyes])
+if test "x$enable_documentation" = "xyes"; then
+ AC_CONFIG_FILES(doc/Makefile doc/common.tex)
+fi
+
+AM_CONDITIONAL([CONFIG_TESTS], [test x$enable_tests = xyes])
+if test "x$enable_tests" = "xyes"; then
+ AC_CONFIG_FILES(tests/Makefile tests/check-namespace.sh)
+fi
+
+AC_CONFIG_FILES(Makefile src/Makefile
+ include/libunwind-common.h
+ include/libunwind.h include/tdep/libunwind_i.h)
+AC_CONFIG_FILES(src/unwind/libunwind.pc src/coredump/libunwind-coredump.pc
+ src/ptrace/libunwind-ptrace.pc src/setjmp/libunwind-setjmp.pc
+ src/libunwind-generic.pc)
+AC_OUTPUT
diff --git a/src/pal/src/libunwind/doc/Makefile.am b/src/pal/src/libunwind/doc/Makefile.am
new file mode 100644
index 0000000000..bfe4669124
--- /dev/null
+++ b/src/pal/src/libunwind/doc/Makefile.am
@@ -0,0 +1,80 @@
+# man pages that go into section 3:
+man3_MANS = libunwind.man libunwind-dynamic.man libunwind-ia64.man \
+ libunwind-ptrace.man libunwind-setjmp.man \
+ unw_apply_reg_state.man \
+ unw_backtrace.man \
+ unw_flush_cache.man \
+ unw_get_accessors.man \
+ unw_get_proc_info.man \
+ unw_get_proc_info_by_ip.man \
+ unw_get_proc_name.man \
+ unw_get_fpreg.man \
+ unw_get_reg.man \
+ unw_getcontext.man \
+ unw_init_local.man unw_init_remote.man \
+ unw_init_local2.man \
+ unw_is_fpreg.man \
+ unw_is_signal_frame.man \
+ unw_create_addr_space.man \
+ unw_destroy_addr_space.man \
+ unw_regname.man unw_resume.man \
+ unw_reg_states_iterate.man \
+ unw_set_caching_policy.man \
+ unw_set_cache_size.man \
+ unw_set_fpreg.man \
+ unw_set_reg.man \
+ unw_step.man \
+ unw_strerror.man \
+ _U_dyn_register.man \
+ _U_dyn_cancel.man
+
+EXTRA_DIST = NOTES libunwind.trans \
+ libunwind.tex libunwind-dynamic.tex libunwind-ia64.tex \
+ libunwind-ptrace.tex libunwind-setjmp.tex \
+ unw_apply_reg_state.tex \
+ unw_backtrace.tex \
+ unw_flush_cache.tex \
+ unw_get_accessors.tex \
+ unw_get_proc_info.tex \
+ unw_get_proc_info_by_ip.tex \
+ unw_get_proc_name.tex \
+ unw_get_fpreg.tex \
+ unw_get_reg.tex \
+ unw_getcontext.tex \
+ unw_init_local.tex unw_init_remote.tex \
+ unw_is_fpreg.tex \
+ unw_is_signal_frame.tex \
+ unw_create_addr_space.tex unw_destroy_addr_space.tex \
+ unw_regname.tex unw_resume.tex unw_set_caching_policy.tex \
+ unw_reg_states_iterate.tex \
+ unw_set_cache_size.tex \
+ unw_set_fpreg.tex \
+ unw_set_reg.tex \
+ unw_step.tex \
+ unw_strerror.tex \
+ _U_dyn_register.tex \
+ _U_dyn_cancel.tex \
+ $(man3_MANS)
+
+L2M = latex2man
+L2P = pdflatex
+L2M_CMD = $(L2M) -t $(srcdir)/libunwind.trans
+L2H_CMD = $(L2M) -H -t $(srcdir)/libunwind.trans
+
+.tex.man:
+ $(L2M_CMD) $< $@
+ -cp $@ $(srcdir)/$@
+
+html:
+ for n in $(man3_MANS); do \
+ page=`basename $$n .man`; \
+ $(L2H_CMD) $(srcdir)/$$page.tex "$$page(3).raw"; \
+ done
+
+pdf:
+ for n in $(man3_MANS); do \
+ page=`basename $$n .man`; \
+ $(L2P) $(srcdir)/$$page.tex "$$page(3).pdf"; \
+ done
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/src/pal/src/libunwind/doc/NOTES b/src/pal/src/libunwind/doc/NOTES
new file mode 100644
index 0000000000..3f3caa95bb
--- /dev/null
+++ b/src/pal/src/libunwind/doc/NOTES
@@ -0,0 +1,127 @@
+The central data structure of the unwind API is the unwind cursor.
+This structure tracks the register contents. The unwind API defines a
+handful of well-known frame "registers":
+
+ - ip: the instruction pointer (pc)
+ - rp: the return pointer (rp, aka "return address" or "return link")
+ - sp: the stack pointer (memory stack pointer, in the case of ia64)
+ - fp: the frame pointer
+ - first_ip: the starting address of the current "procedure"
+ - handler: a pointer to an architecture & language-specific
+ "personality" routine
+ - lsda: a pointer to an architecture & language-specific
+ data-area
+
+The API defines no well-known preserved registers. Each architecture
+can define additional registers as needed. Of course, a portable
+application may only rely on well-known registers. The names for
+preserved registers are defined in the architecture-specific header
+file <unwind-ARCH.h>. For example, to get the IA-64-specific register
+names, an application would do:
+
+ #include <unwind-ia64.h>
+
+The API is designed to handle two primary cases: unwinding within the
+current (local) process and unwinding of another ("remote") process
+(e.g., through ptrace()). In the local case, the initial machine
+state is captured by an unwind context (currently the same as
+ucontext_t). In the remote case, the initial machine state is
+captured by an unwind accessor structure, which provides callback
+routines for reading/writing memory and registers and for obtaining
+unwind information.
+
+Once a cursor has been initialized, you can step through the call
+chain with the unw_step() routine. The frame registers and the
+preserved state can then be accessed with unw_get_reg() or modified
+with unw_set_reg(). For floating-point registers, there are separate
+unw_get_fpreg() and unw_set_fpreg() routines (on some arches, e.g.,
+Alpha, these could be just aliases for unw_{g,s}et_reg()). The
+unw_resume() routine can be used to resume execution at an arbitrary
+point in the call-chain (as identified by an unwind cursor). This is
+intended for exception handling and, at least for now, the intention
+is to support this routine only for the local case. Kevin, if you
+feel gdb could benefit from such a routine, I'd be interested to hear
+about it.
+
+Note that it is perfectly legal to make copies of the unwind cursor.
+This makes it possible, e.g., to obtain an unwind context, modify the
+state in an earlier call frame, and then resume execution at the point
+at which the unwind context was captured.
+
+Here is a quick example of how to use the unwind API to do a simple
+stack trace:
+
+ unw_cursor_t cursor;
+ unw_word_t ip, sp;
+ unw_context_t uc;
+
+ unw_getcontext(&uc);
+ unw_init_local(&cursor, &uc);
+ do
+ {
+ unw_get_reg(&cursor, UNW_REG_IP, &ip);
+ unw_get_reg(&cursor, UNW_REG_SP, &sp);
+ printf ("ip=%016lx sp=%016lx\n", ip, sp);
+ }
+ while (unw_step (&cursor) > 0);
+
+Note that this particular example should work on pretty much any
+architecture, as it doesn't rely on any arch-specific registers.
+
+* Multiarchitecture support
+
+If libunwind is configured for a target other than the local (native)
+host, the library is installed as libunwind-$ARCH, where $ARCH is
+the target architecture name (e.g., ia32, ia64, or alpha). Similarly,
+the header file is installed as libunwind-$ARCH.
+
+With this setup, an application should:
+
+ - include <libunwind.h>, and
+ - link against -lunwind
+
+if the application needs to use the unwinder of the host. An
+application wanting to use the unwinder for a different target (e.g.,
+a cross-debugger) should:
+
+ - include <libunwind-$ARCH.h>, and
+ - link against -lunwind-$ARCH
+
+The global symbols exported by -lunwind-$ARCH are unique such that the
+same application can be linked against the separate unwind libraries
+of multiple targets. However, a single compilation unit can include
+the header file for only one target. For example, foo.c might include
+<libunwind-ia64.h> and bar.c might include <libunwind.h> and the
+entire application would have to be linked against both -lunwind and
+-lunwind-ia64.
+
+Note: the unwind header files of all targets have a common dependency
+on libunwind-common.h. To avoid version conflicts, it is necessary to
+ensure that the unwind libraries for all targets were derived from the
+same release of libunwind. That is, if the unwind library for one
+target is upgraded to a newer version, the libraries for all other
+targets also need to be upgraded.
+
+Note 2: The assumption is that a cross-unwinder can handle all
+interesting flavors of a target. For example, the unwinder for the
+ia64 target is expected to be able to handle both Linux and HP-UX.
+
+* IA-64 Specific Information
+
+Apart from the normal frame-registers, the IA-64 implementation of
+libunwind provides the means to access the current value of the
+register backing store pointer (bsp). One quirk with this
+frame-register is that it corresponds to the address that would be in
+register ar.bsp after flushing the current register stack to the
+backing store (i.e., as if a "flushrs" instruction had been executed).
+Of course, given this value and the contents of the current frame
+marker (CFM), it's easy to calculate the original value of ar.bsp:
+
+ unw_word_t cfm, bsp, bsp_after_flushrs, sof;
+
+ unw_get_reg (&cursor, UNW_IA64_BSP, &bsp_after_flushrs);
+ unw_get_reg (&cursor, UNW_IA64_CFM, &cfm);
+ bsp = ia64_rse_skip_regs (bsp_after_flushrs, -(cfm & 0x7f));
+
+** Dynamic Unwind Info
+
diff --git a/src/pal/src/libunwind/doc/_U_dyn_cancel.man b/src/pal/src/libunwind/doc/_U_dyn_cancel.man
new file mode 100644
index 0000000000..a420a6deaf
--- /dev/null
+++ b/src/pal/src/libunwind/doc/_U_dyn_cancel.man
@@ -0,0 +1,66 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "\\_U\\_DYN\\_CANCEL" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+_U_dyn_cancel
+\-\- cancel unwind\-info for dynamically generated code
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+void
+_U_dyn_cancel(unw_dyn_info_t *di);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The _U_dyn_cancel()
+routine cancels the registration of the
+unwind\-info for a dynamically generated procedure. Argument di
+is the pointer to the unw_dyn_info_t
+structure that
+describes the procedure\&'s unwind\-info.
+.PP
+The _U_dyn_cancel()
+routine is guaranteed to execute in
+constant time (in the absence of contention from concurrent calls to
+_U_dyn_register()
+or _U_dyn_cancel()).
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+_U_dyn_cancel()
+is thread\-safe but \fInot\fP
+safe to use
+from a signal handler.
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind\-dynamic(3),
+_U_dyn_register(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/_U_dyn_cancel.tex b/src/pal/src/libunwind/doc/_U_dyn_cancel.tex
new file mode 100644
index 0000000000..ca5a12a76e
--- /dev/null
+++ b/src/pal/src/libunwind/doc/_U_dyn_cancel.tex
@@ -0,0 +1,46 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{\_U\_dyn\_cancel}{David Mosberger-Tang}{Programming Library}{\_U\_dyn\_cancel}\_U\_dyn\_cancel -- cancel unwind-info for dynamically generated code
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{void} \Func{\_U\_dyn\_cancel}(\Type{unw\_dyn\_info\_t~*}\Var{di});\\
+
+\section{Description}
+
+The \Func{\_U\_dyn\_cancel}() routine cancels the registration of the
+unwind-info for a dynamically generated procedure. Argument \Var{di}
+is the pointer to the \Type{unw\_dyn\_info\_t} structure that
+describes the procedure's unwind-info.
+
+The \Func{\_U\_dyn\_cancel}() routine is guaranteed to execute in
+constant time (in the absence of contention from concurrent calls to
+\Func{\_U\_dyn\_register}() or \Func{\_U\_dyn\_cancel}()).
+
+
+\section{Thread and Signal Safety}
+
+\Func{\_U\_dyn\_cancel}() is thread-safe but \emph{not} safe to use
+from a signal handler.
+
+\section{See Also}
+
+\SeeAlso{libunwind-dynamic(3)}, \SeeAlso{\_U\_dyn\_register(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/_U_dyn_register.man b/src/pal/src/libunwind/doc/_U_dyn_register.man
new file mode 100644
index 0000000000..107e5fd0e1
--- /dev/null
+++ b/src/pal/src/libunwind/doc/_U_dyn_register.man
@@ -0,0 +1,68 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "\\_U\\_DYN\\_REGISTER" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+_U_dyn_register
+\-\- register unwind\-info for dynamically generated code
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+void
+_U_dyn_register(unw_dyn_info_t *di);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The _U_dyn_register()
+routine registers unwind\-info for a
+dynamically generated procedure. The procedure\&'s unwind\-info is
+described by a structure of type unw_dyn_info_t
+(see
+libunwind\-dynamic(3)).
+A pointer to this structure is
+passed in argument di\&.
+.PP
+The _U_dyn_register()
+routine is guaranteed to execute in
+constant time (in the absence of contention from concurrent calls to
+_U_dyn_register()
+or _U_dyn_cancel()).
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+_U_dyn_register()
+is thread\-safe but \fInot\fP
+safe to use
+from a signal handler.
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind\-dynamic(3),
+_U_dyn_cancel(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/_U_dyn_register.tex b/src/pal/src/libunwind/doc/_U_dyn_register.tex
new file mode 100644
index 0000000000..ab23b5c621
--- /dev/null
+++ b/src/pal/src/libunwind/doc/_U_dyn_register.tex
@@ -0,0 +1,47 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{\_U\_dyn\_register}{David Mosberger-Tang}{Programming Library}{\_U\_dyn\_register}\_U\_dyn\_register -- register unwind-info for dynamically generated code
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{void} \Func{\_U\_dyn\_register}(\Type{unw\_dyn\_info\_t~*}\Var{di});\\
+
+\section{Description}
+
+The \Func{\_U\_dyn\_register}() routine registers unwind-info for a
+dynamically generated procedure. The procedure's unwind-info is
+described by a structure of type \Type{unw\_dyn\_info\_t} (see
+\SeeAlso{libunwind-dynamic(3)}). A pointer to this structure is
+passed in argument \Var{di}.
+
+The \Func{\_U\_dyn\_register}() routine is guaranteed to execute in
+constant time (in the absence of contention from concurrent calls to
+\Func{\_U\_dyn\_register}() or \Func{\_U\_dyn\_cancel}()).
+
+
+\section{Thread and Signal Safety}
+
+\Func{\_U\_dyn\_register}() is thread-safe but \emph{not} safe to use
+from a signal handler.
+
+\section{See Also}
+
+\SeeAlso{libunwind-dynamic(3)}, \SeeAlso{\_U\_dyn\_cancel(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/common.tex.in b/src/pal/src/libunwind/doc/common.tex.in
new file mode 100644
index 0000000000..91c96a9df4
--- /dev/null
+++ b/src/pal/src/libunwind/doc/common.tex.in
@@ -0,0 +1,11 @@
+\setVersion{@VERSION@}
+
+\sloppy
+
+\newcommand{\Lt}{\symbol{"3C}}
+\newcommand{\Gt}{\symbol{"3E}}
+\newcommand{\Type}[1]{\File{#1}} % see libunwind.trans
+\newcommand{\Func}[1]{\Prog{#1}} % see libunwind.trans
+\newcommand{\Var}[1]{\Prog{#1}} % see libunwind.trans
+\newcommand{\Const}[1]{\File{#1}} % see libunwind.trans
+\newcommand{\SeeAlso}[2]{\File{#1}} % see libunwind.trans
diff --git a/src/pal/src/libunwind/doc/libunwind-dynamic.man b/src/pal/src/libunwind/doc/libunwind-dynamic.man
new file mode 100644
index 0000000000..7c7507cb10
--- /dev/null
+++ b/src/pal/src/libunwind/doc/libunwind-dynamic.man
@@ -0,0 +1,538 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:44 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "LIBUNWIND\-DYNAMIC" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+libunwind\-dynamic
+\-\- libunwind\-support for runtime\-generated code
+.PP
+.SH INTRODUCTION
+
+.PP
+For libunwind
+to do its job, it needs to be able to reconstruct
+the \fIframe state\fP
+of each frame in a call\-chain. The frame state
+describes the subset of the machine\-state that consists of the
+\fIframe registers\fP
+(typically the instruction\-pointer and the
+stack\-pointer) and all callee\-saved registers (preserved registers).
+The frame state describes each register either by providing its
+current value (for frame registers) or by providing the location at
+which the current value is stored (callee\-saved registers).
+.PP
+For statically generated code, the compiler normally takes care of
+emitting \fIunwind\-info\fP
+which provides the minimum amount of
+information needed to reconstruct the frame\-state for each instruction
+in a procedure. For dynamically generated code, the runtime code
+generator must use the dynamic unwind\-info interface provided by
+libunwind
+to supply the equivalent information. This manual
+page describes the format of this information in detail.
+.PP
+For the purpose of this discussion, a \fIprocedure\fP
+is defined to
+be an arbitrary piece of \fIcontiguous\fP
+code. Normally, each
+procedure directly corresponds to a function in the source\-language
+but this is not strictly required. For example, a runtime
+code\-generator could translate a given function into two separate
+(discontiguous) procedures: one for frequently\-executed (hot) code and
+one for rarely\-executed (cold) code. Similarly, simple
+source\-language functions (usually leaf functions) may get translated
+into code for which the default unwind\-conventions apply and for such
+code, it is not strictly necessary to register dynamic unwind\-info.
+.PP
+A procedure logically consists of a sequence of \fIregions\fP\&.
+Regions are nested in the sense that the frame state at the end of one
+region is, by default, assumed to be the frame state for the next
+region. Each region is thought of as being divided into a
+\fIprologue\fP,
+a \fIbody\fP,
+and an \fIepilogue\fP\&.
+Each of them
+can be empty. If non\-empty, the prologue sets up the frame state for
+the body. For example, the prologue may need to allocate some space
+on the stack and save certain callee\-saved registers. The body
+performs the actual work of the procedure but does not change the
+frame state in any way. If non\-empty, the epilogue restores the
+previous frame state and as such it undoes or cancels the effect of
+the prologue. In fact, a single epilogue may undo the effect of the
+prologues of several (nested) regions.
+.PP
+We should point out that even though the prologue, body, and epilogue
+are logically separate entities, optimizing code\-generators will
+generally interleave instructions from all three entities. For this
+reason, the dynamic unwind\-info interface of libunwind
+makes no
+distinction whatsoever between prologue and body. Similarly, the
+exact set of instructions that make up an epilogue is also irrelevant.
+The only point in the epilogue that needs to be described explicitly
+by the dynamic unwind\-info is the point at which the stack\-pointer
+gets restored. The reason this point needs to be described is that
+once the stack\-pointer is restored, all values saved in the
+deallocated portion of the stack frame become invalid and hence
+libunwind
+needs to know about it. The portion of the frame
+state not saved on the stack is assume to remain valid through the end
+of the region. For this reason, there is usually no need to describe
+instructions which restore the contents of callee\-saved registers.
+.PP
+Within a region, each instruction that affects the frame state in some
+fashion needs to be described with an operation descriptor. For this
+purpose, each instruction in the region is assigned a unique index.
+Exactly how this index is derived depends on the architecture. For
+example, on RISC and EPIC\-style architecture, instructions have a
+fixed size so it\&'s possible to simply number the instructions. In
+contrast, most CISC use variable\-length instruction encodings, so it
+is usually necessary to use a byte\-offset as the index. Given the
+instruction index, the operation descriptor specifies the effect of
+the instruction in an abstract manner. For example, it might express
+that the instruction stores calle\-saved register r1
+at offset 16
+in the stack frame.
+.PP
+.SH PROCEDURES
+
+.PP
+A runtime code\-generator registers the dynamic unwind\-info of a
+procedure by setting up a structure of type unw_dyn_info_t
+and calling _U_dyn_register(),
+passing the address of the
+structure as the sole argument. The members of the
+unw_dyn_info_t
+structure are described below:
+.TP
+void *next
+ Private to libunwind\&.
+Must not be used
+by the application.
+.TP
+void *prev
+ Private to libunwind\&.
+Must not be used
+by the application.
+.TP
+unw_word_t start_ip
+ The start\-address of the
+instructions of the procedure (remember: procedure are defined to be
+contiguous pieces of code, so a single code\-range is sufficient).
+.TP
+unw_word_t end_ip
+ The end\-address of the
+instructions of the procedure (non\-inclusive, that is,
+end_ip\-start_ip
+is the size of the procedure in
+bytes).
+.TP
+unw_word_t gp
+ The global\-pointer value in use
+for this procedure. The exact meaing of the global\-pointer is
+architecture\-specific and on some architecture, it is not used at
+all.
+.TP
+int32_t format
+ The format of the unwind\-info.
+This member can be one of UNW_INFO_FORMAT_DYNAMIC,
+UNW_INFO_FORMAT_TABLE,
+or
+UNW_INFO_FORMAT_REMOTE_TABLE\&.
+.TP
+union u
+ This union contains one sub\-member
+structure for every possible unwind\-info format:
+.RS
+.TP
+unw_dyn_proc_info_t pi
+ This member is used
+for format UNW_INFO_FORMAT_DYNAMIC\&.
+.TP
+unw_dyn_table_info_t ti
+ This member is used
+for format UNW_INFO_FORMAT_TABLE\&.
+.TP
+unw_dyn_remote_table_info_t rti
+ This member
+is used for format UNW_INFO_FORMAT_REMOTE_TABLE\&.
+.RE
+.RS
+.PP
+The format of these sub\-members is described in detail below.
+.RE
+.PP
+.SS PROC\-INFO FORMAT
+.PP
+This is the preferred dynamic unwind\-info format and it is generally
+the one used by full\-blown runtime code\-generators. In this format,
+the details of a procedure are described by a structure of type
+unw_dyn_proc_info_t\&.
+This structure contains the following
+members:
+.PP
+.RE
+.TP
+unw_word_t name_ptr
+ The address of a
+(human\-readable) name of the procedure or 0 if no such name is
+available. If non\-zero, The string stored at this address must be
+ASCII NUL terminated. For source languages that use name\-mangling
+(such as C++ or Java) the string stored at this address should be
+the \fIdemangled\fP
+version of the name.
+.PP
+.TP
+unw_word_t handler
+ The address of the
+personality\-routine for this procedure. Personality\-routines are
+used in conjunction with exception handling. See the C++ ABI draft
+(http://www.codesourcery.com/cxx\-abi/) for an overview and a
+description of the personality routine. If the procedure has no
+personality routine, handler
+must be set to 0.
+.PP
+.TP
+uint32_t flags
+ A bitmask of flags. At the
+moment, no flags have been defined and this member must be
+set to 0.
+.PP
+.TP
+unw_dyn_region_info_t *regions
+ A NULL\-terminated
+linked list of region\-descriptors. See section ``Region
+descriptors\&'' below for more details.
+.PP
+.SS TABLE\-INFO FORMAT
+.PP
+This format is generally used when the dynamically generated code was
+derived from static code and the unwind\-info for the dynamic and the
+static versions is identical. For example, this format can be useful
+when loading statically\-generated code into an address\-space in a
+non\-standard fashion (i.e., through some means other than
+dlopen()).
+In this format, the details of a group of procedures
+is described by a structure of type unw_dyn_table_info\&.
+This structure contains the following members:
+.PP
+.TP
+unw_word_t name_ptr
+ The address of a
+(human\-readable) name of the procedure or 0 if no such name is
+available. If non\-zero, The string stored at this address must be
+ASCII NUL terminated. For source languages that use name\-mangling
+(such as C++ or Java) the string stored at this address should be
+the \fIdemangled\fP
+version of the name.
+.PP
+.TP
+unw_word_t segbase
+ The segment\-base value
+that needs to be added to the segment\-relative values stored in the
+unwind\-info. The exact meaning of this value is
+architecture\-specific.
+.PP
+.TP
+unw_word_t table_len
+ The length of the
+unwind\-info (table_data)
+counted in units of words
+(unw_word_t).
+.PP
+.TP
+unw_word_t table_data
+ A pointer to the actual
+data encoding the unwind\-info. The exact format is
+architecture\-specific (see architecture\-specific sections below).
+.PP
+.SS REMOTE TABLE\-INFO FORMAT
+.PP
+The remote table\-info format has the same basic purpose as the regular
+table\-info format. The only difference is that when libunwind
+uses the unwind\-info, it will keep the table data in the target
+address\-space (which may be remote). Consequently, the type of the
+table_data
+member is unw_word_t
+rather than a pointer.
+This implies that libunwind
+will have to access the table\-data
+via the address\-space\&'s access_mem()
+call\-back, rather than
+through a direct memory reference.
+.PP
+From the point of view of a runtime\-code generator, the remote
+table\-info format offers no advantage and it is expected that such
+generators will describe their procedures either with the proc\-info
+format or the normal table\-info format. The main reason that the
+remote table\-info format exists is to enable the
+address\-space\-specific find_proc_info()
+callback (see
+unw_create_addr_space(3))
+to return unwind tables whose
+data remains in remote memory. This can speed up unwinding (e.g., for
+a debugger) because it reduces the amount of data that needs to be
+loaded from remote memory.
+.PP
+.SH REGIONS DESCRIPTORS
+
+.PP
+A region descriptor is a variable length structure that describes how
+each instruction in the region affects the frame state. Of course,
+most instructions in a region usualy do not change the frame state and
+for those, nothing needs to be recorded in the region descriptor. A
+region descriptor is a structure of type
+unw_dyn_region_info_t
+and has the following members:
+.TP
+unw_dyn_region_info_t *next
+ A pointer to the
+next region. If this is the last region, next
+is NULL\&.
+.TP
+int32_t insn_count
+ The length of the region in
+instructions. Each instruction is assumed to have a fixed size (see
+architecture\-specific sections for details). The value of
+insn_count
+may be negative in the last region of a procedure
+(i.e., it may be negative only if next
+is NULL).
+A
+negative value indicates that the region covers the last \fIN\fP
+instructions of the procedure, where \fIN\fP
+is the absolute value
+of insn_count\&.
+.TP
+uint32_t op_count
+ The (allocated) length of
+the op_count
+array.
+.TP
+unw_dyn_op_t op
+ An array of dynamic unwind
+directives. See Section ``Dynamic unwind directives\&'' for a
+description of the directives.
+.PP
+A region descriptor with an insn_count
+of zero is an
+\fIempty region\fP
+and such regions are perfectly legal. In fact,
+empty regions can be useful to establish a particular frame state
+before the start of another region.
+.PP
+A single region list can be shared across multiple procedures provided
+those procedures share a common prologue and epilogue (their bodies
+may differ, of course). Normally, such procedures consist of a canned
+prologue, the body, and a canned epilogue. This could be described by
+two regions: one covering the prologue and one covering the epilogue.
+Since the body length is variable, the latter region would need to
+specify a negative value in insn_count
+such that
+libunwind
+knows that the region covers the end of the procedure
+(up to the address specified by end_ip).
+.PP
+The region descriptor is a variable length structure to make it
+possible to allocate all the necessary memory with a single
+memory\-allocation request. To facilitate the allocation of a region
+descriptors libunwind
+provides a helper routine with the
+following synopsis:
+.PP
+size_t
+_U_dyn_region_size(int
+op_count);
+.PP
+This routine returns the number of bytes needed to hold a region
+descriptor with space for op_count
+unwind directives. Note
+that the length of the op
+array does not have to match exactly
+with the number of directives in a region. Instead, it is sufficient
+if the op
+array contains at least as many entries as there are
+directives, since the end of the directives can always be indicated
+with the UNW_DYN_STOP
+directive.
+.PP
+.SH DYNAMIC UNWIND DIRECTIVES
+
+.PP
+A dynamic unwind directive describes how the frame state changes
+at a particular point within a region. The description is in
+the form of a structure of type unw_dyn_op_t\&.
+This
+structure has the following members:
+.TP
+int8_t tag
+ The operation tag. Must be one
+of the unw_dyn_operation_t
+values described below.
+.TP
+int8_t qp
+ The qualifying predicate that controls
+whether or not this directive is active. This is useful for
+predicated architecturs such as IA\-64 or ARM, where the contents of
+another (callee\-saved) register determines whether or not an
+instruction is executed (takes effect). If the directive is always
+active, this member should be set to the manifest constant
+_U_QP_TRUE
+(this constant is defined for all
+architectures, predicated or not).
+.TP
+int16_t reg
+ The number of the register affected
+by the instruction.
+.TP
+int32_t when
+ The region\-relative number of
+the instruction to which this directive applies. For example,
+a value of 0 means that the effect described by this directive
+has taken place once the first instruction in the region has
+executed.
+.TP
+unw_word_t val
+ The value to be applied by the
+operation tag. The exact meaning of this value varies by tag. See
+Section ``Operation tags\&'' below.
+.PP
+It is perfectly legitimate to specify multiple dynamic unwind
+directives with the same when
+value, if a particular instruction
+has a complex effect on the frame state.
+.PP
+Empty regions by definition contain no actual instructions and as such
+the directives are not tied to a particular instruction. By
+convention, the when
+member should be set to 0, however.
+.PP
+There is no need for the dynamic unwind directives to appear
+in order of increasing when
+values. If the directives happen to
+be sorted in that order, it may result in slightly faster execution,
+but a runtime code\-generator should not go to extra lengths just to
+ensure that the directives are sorted.
+.PP
+IMPLEMENTATION NOTE: should libunwind
+implementations for
+certain architectures prefer the list of unwind directives to be
+sorted, it is recommended that such implementations first check
+whether the list happens to be sorted already and, if not, sort the
+directives explicitly before the first use. With this approach, the
+overhead of explicit sorting is only paid when there is a real benefit
+and if the runtime code\-generator happens to generated sorted lists
+naturally, the performance penalty is limited to a simple O(N) check.
+.PP
+.SS OPERATIONS TAGS
+.PP
+The possible operation tags are defined by enumeration type
+unw_dyn_operation_t
+which defines the following
+values:
+.PP
+.TP
+UNW_DYN_STOP
+ Marks the end of the dynamic unwind
+directive list. All remaining entries in the op
+array of the
+region\-descriptor are ignored. This tag is guaranteed to have a
+value of 0.
+.PP
+.TP
+UNW_DYN_SAVE_REG
+ Marks an instruction which saves
+register reg
+to register val\&.
+.PP
+.TP
+UNW_DYN_SPILL_FP_REL
+ Marks an instruction which
+spills register reg
+to a frame\-pointer\-relative location. The
+frame\-pointer\-relative offset is given by the value stored in member
+val\&.
+See the architecture\-specific sections for a description
+of the stack frame layout.
+.PP
+.TP
+UNW_DYN_SPILL_SP_REL
+ Marks an instruction which
+spills register reg
+to a stack\-pointer\-relative location. The
+stack\-pointer\-relative offset is given by the value stored in member
+val\&.
+See the architecture\-specific sections for a description
+of the stack frame layout.
+.PP
+.TP
+UNW_DYN_ADD
+ Marks an instruction which adds
+the constant value val
+to register reg\&.
+To add subtract
+a constant value, store the two\&'s\-complement of the value in
+val\&.
+The set of registers that can be specified for this tag
+is described in the architecture\-specific sections below.
+.PP
+.TP
+UNW_DYN_POP_FRAMES
+ .PP
+.TP
+UNW_DYN_LABEL_STATE
+ .PP
+.TP
+UNW_DYN_COPY_STATE
+ .PP
+.TP
+UNW_DYN_ALIAS
+ .PP
+unw_dyn_op_t
+.PP
+_U_dyn_op_save_reg();
+_U_dyn_op_spill_fp_rel();
+_U_dyn_op_spill_sp_rel();
+_U_dyn_op_add();
+_U_dyn_op_pop_frames();
+_U_dyn_op_label_state();
+_U_dyn_op_copy_state();
+_U_dyn_op_alias();
+_U_dyn_op_stop();
+.PP
+.SH IA\-64 SPECIFICS
+
+.PP
+\- meaning of segbase member in table\-info/table\-remote\-info format
+\- format of table_data in table\-info/table\-remote\-info format
+\- instruction size: each bundle is counted as 3 instructions, regardless
+of template (MLX)
+\- describe stack\-frame layout, especially with regards to sp\-relative
+and fp\-relative addressing
+\- UNW_DYN_ADD can only add to ``sp\&'' (always a negative value); use
+POP_FRAMES otherwise
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+_U_dyn_register(3),
+_U_dyn_cancel(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/libunwind-dynamic.tex b/src/pal/src/libunwind/doc/libunwind-dynamic.tex
new file mode 100644
index 0000000000..21e895a34f
--- /dev/null
+++ b/src/pal/src/libunwind/doc/libunwind-dynamic.tex
@@ -0,0 +1,401 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{libunwind-dynamic}{David Mosberger-Tang}{Programming Library}{Introduction to dynamic unwind-info}libunwind-dynamic -- libunwind-support for runtime-generated code
+\end{Name}
+
+\section{Introduction}
+
+For \Prog{libunwind} to do its job, it needs to be able to reconstruct
+the \emph{frame state} of each frame in a call-chain. The frame state
+describes the subset of the machine-state that consists of the
+\emph{frame registers} (typically the instruction-pointer and the
+stack-pointer) and all callee-saved registers (preserved registers).
+The frame state describes each register either by providing its
+current value (for frame registers) or by providing the location at
+which the current value is stored (callee-saved registers).
+
+For statically generated code, the compiler normally takes care of
+emitting \emph{unwind-info} which provides the minimum amount of
+information needed to reconstruct the frame-state for each instruction
+in a procedure. For dynamically generated code, the runtime code
+generator must use the dynamic unwind-info interface provided by
+\Prog{libunwind} to supply the equivalent information. This manual
+page describes the format of this information in detail.
+
+For the purpose of this discussion, a \emph{procedure} is defined to
+be an arbitrary piece of \emph{contiguous} code. Normally, each
+procedure directly corresponds to a function in the source-language
+but this is not strictly required. For example, a runtime
+code-generator could translate a given function into two separate
+(discontiguous) procedures: one for frequently-executed (hot) code and
+one for rarely-executed (cold) code. Similarly, simple
+source-language functions (usually leaf functions) may get translated
+into code for which the default unwind-conventions apply and for such
+code, it is not strictly necessary to register dynamic unwind-info.
+
+A procedure logically consists of a sequence of \emph{regions}.
+Regions are nested in the sense that the frame state at the end of one
+region is, by default, assumed to be the frame state for the next
+region. Each region is thought of as being divided into a
+\emph{prologue}, a \emph{body}, and an \emph{epilogue}. Each of them
+can be empty. If non-empty, the prologue sets up the frame state for
+the body. For example, the prologue may need to allocate some space
+on the stack and save certain callee-saved registers. The body
+performs the actual work of the procedure but does not change the
+frame state in any way. If non-empty, the epilogue restores the
+previous frame state and as such it undoes or cancels the effect of
+the prologue. In fact, a single epilogue may undo the effect of the
+prologues of several (nested) regions.
+
+We should point out that even though the prologue, body, and epilogue
+are logically separate entities, optimizing code-generators will
+generally interleave instructions from all three entities. For this
+reason, the dynamic unwind-info interface of \Prog{libunwind} makes no
+distinction whatsoever between prologue and body. Similarly, the
+exact set of instructions that make up an epilogue is also irrelevant.
+The only point in the epilogue that needs to be described explicitly
+by the dynamic unwind-info is the point at which the stack-pointer
+gets restored. The reason this point needs to be described is that
+once the stack-pointer is restored, all values saved in the
+deallocated portion of the stack frame become invalid and hence
+\Prog{libunwind} needs to know about it. The portion of the frame
+state not saved on the stack is assume to remain valid through the end
+of the region. For this reason, there is usually no need to describe
+instructions which restore the contents of callee-saved registers.
+
+Within a region, each instruction that affects the frame state in some
+fashion needs to be described with an operation descriptor. For this
+purpose, each instruction in the region is assigned a unique index.
+Exactly how this index is derived depends on the architecture. For
+example, on RISC and EPIC-style architecture, instructions have a
+fixed size so it's possible to simply number the instructions. In
+contrast, most CISC use variable-length instruction encodings, so it
+is usually necessary to use a byte-offset as the index. Given the
+instruction index, the operation descriptor specifies the effect of
+the instruction in an abstract manner. For example, it might express
+that the instruction stores calle-saved register \Var{r1} at offset 16
+in the stack frame.
+
+\section{Procedures}
+
+A runtime code-generator registers the dynamic unwind-info of a
+procedure by setting up a structure of type \Type{unw\_dyn\_info\_t}
+and calling \Func{\_U\_dyn\_register}(), passing the address of the
+structure as the sole argument. The members of the
+\Type{unw\_dyn\_info\_t} structure are described below:
+\begin{itemize}
+\item[\Type{void~*}next] Private to \Prog{libunwind}. Must not be used
+ by the application.
+\item[\Type{void~*}prev] Private to \Prog{libunwind}. Must not be used
+ by the application.
+\item[\Type{unw\_word\_t} \Var{start\_ip}] The start-address of the
+ instructions of the procedure (remember: procedure are defined to be
+ contiguous pieces of code, so a single code-range is sufficient).
+\item[\Type{unw\_word\_t} \Var{end\_ip}] The end-address of the
+ instructions of the procedure (non-inclusive, that is,
+ \Var{end\_ip}-\Var{start\_ip} is the size of the procedure in
+ bytes).
+\item[\Type{unw\_word\_t} \Var{gp}] The global-pointer value in use
+ for this procedure. The exact meaing of the global-pointer is
+ architecture-specific and on some architecture, it is not used at
+ all.
+\item[\Type{int32\_t} \Var{format}] The format of the unwind-info.
+ This member can be one of \Const{UNW\_INFO\_FORMAT\_DYNAMIC},
+ \Const{UNW\_INFO\_FORMAT\_TABLE}, or
+ \Const{UNW\_INFO\_FORMAT\_REMOTE\_TABLE}.
+\item[\Type{union} \Var{u}] This union contains one sub-member
+ structure for every possible unwind-info format:
+ \begin{description}
+ \item[\Type{unw\_dyn\_proc\_info\_t} \Var{pi}] This member is used
+ for format \Const{UNW\_INFO\_FORMAT\_DYNAMIC}.
+ \item[\Type{unw\_dyn\_table\_info\_t} \Var{ti}] This member is used
+ for format \Const{UNW\_INFO\_FORMAT\_TABLE}.
+ \item[\Type{unw\_dyn\_remote\_table\_info\_t} \Var{rti}] This member
+ is used for format \Const{UNW\_INFO\_FORMAT\_REMOTE\_TABLE}.
+ \end{description}\
+ The format of these sub-members is described in detail below.
+\end{itemize}
+
+\subsection{Proc-info format}
+
+This is the preferred dynamic unwind-info format and it is generally
+the one used by full-blown runtime code-generators. In this format,
+the details of a procedure are described by a structure of type
+\Type{unw\_dyn\_proc\_info\_t}. This structure contains the following
+members:
+\begin{description}
+
+\item[\Type{unw\_word\_t} \Var{name\_ptr}] The address of a
+ (human-readable) name of the procedure or 0 if no such name is
+ available. If non-zero, The string stored at this address must be
+ ASCII NUL terminated. For source languages that use name-mangling
+ (such as C++ or Java) the string stored at this address should be
+ the \emph{demangled} version of the name.
+
+\item[\Type{unw\_word\_t} \Var{handler}] The address of the
+ personality-routine for this procedure. Personality-routines are
+ used in conjunction with exception handling. See the C++ ABI draft
+ (http://www.codesourcery.com/cxx-abi/) for an overview and a
+ description of the personality routine. If the procedure has no
+ personality routine, \Var{handler} must be set to 0.
+
+\item[\Type{uint32\_t} \Var{flags}] A bitmask of flags. At the
+ moment, no flags have been defined and this member must be
+ set to 0.
+
+\item[\Type{unw\_dyn\_region\_info\_t~*}\Var{regions}] A NULL-terminated
+ linked list of region-descriptors. See section ``Region
+ descriptors'' below for more details.
+
+\end{description}
+
+\subsection{Table-info format}
+
+This format is generally used when the dynamically generated code was
+derived from static code and the unwind-info for the dynamic and the
+static versions is identical. For example, this format can be useful
+when loading statically-generated code into an address-space in a
+non-standard fashion (i.e., through some means other than
+\Func{dlopen}()). In this format, the details of a group of procedures
+is described by a structure of type \Type{unw\_dyn\_table\_info}.
+This structure contains the following members:
+\begin{description}
+
+\item[\Type{unw\_word\_t} \Var{name\_ptr}] The address of a
+ (human-readable) name of the procedure or 0 if no such name is
+ available. If non-zero, The string stored at this address must be
+ ASCII NUL terminated. For source languages that use name-mangling
+ (such as C++ or Java) the string stored at this address should be
+ the \emph{demangled} version of the name.
+
+\item[\Type{unw\_word\_t} \Var{segbase}] The segment-base value
+ that needs to be added to the segment-relative values stored in the
+ unwind-info. The exact meaning of this value is
+ architecture-specific.
+
+\item[\Type{unw\_word\_t} \Var{table\_len}] The length of the
+ unwind-info (\Var{table\_data}) counted in units of words
+ (\Type{unw\_word\_t}).
+
+\item[\Type{unw\_word\_t} \Var{table\_data}] A pointer to the actual
+ data encoding the unwind-info. The exact format is
+ architecture-specific (see architecture-specific sections below).
+
+\end{description}
+
+\subsection{Remote table-info format}
+
+The remote table-info format has the same basic purpose as the regular
+table-info format. The only difference is that when \Prog{libunwind}
+uses the unwind-info, it will keep the table data in the target
+address-space (which may be remote). Consequently, the type of the
+\Var{table\_data} member is \Type{unw\_word\_t} rather than a pointer.
+This implies that \Prog{libunwind} will have to access the table-data
+via the address-space's \Func{access\_mem}() call-back, rather than
+through a direct memory reference.
+
+From the point of view of a runtime-code generator, the remote
+table-info format offers no advantage and it is expected that such
+generators will describe their procedures either with the proc-info
+format or the normal table-info format. The main reason that the
+remote table-info format exists is to enable the
+address-space-specific \Func{find\_proc\_info}() callback (see
+\SeeAlso{unw\_create\_addr\_space}(3)) to return unwind tables whose
+data remains in remote memory. This can speed up unwinding (e.g., for
+a debugger) because it reduces the amount of data that needs to be
+loaded from remote memory.
+
+\section{Regions descriptors}
+
+A region descriptor is a variable length structure that describes how
+each instruction in the region affects the frame state. Of course,
+most instructions in a region usualy do not change the frame state and
+for those, nothing needs to be recorded in the region descriptor. A
+region descriptor is a structure of type
+\Type{unw\_dyn\_region\_info\_t} and has the following members:
+\begin{description}
+\item[\Type{unw\_dyn\_region\_info\_t~*}\Var{next}] A pointer to the
+ next region. If this is the last region, \Var{next} is \Const{NULL}.
+\item[\Type{int32\_t} \Var{insn\_count}] The length of the region in
+ instructions. Each instruction is assumed to have a fixed size (see
+ architecture-specific sections for details). The value of
+ \Var{insn\_count} may be negative in the last region of a procedure
+ (i.e., it may be negative only if \Var{next} is \Const{NULL}). A
+ negative value indicates that the region covers the last \emph{N}
+ instructions of the procedure, where \emph{N} is the absolute value
+ of \Var{insn\_count}.
+\item[\Type{uint32\_t} \Var{op\_count}] The (allocated) length of
+ the \Var{op\_count} array.
+\item[\Type{unw\_dyn\_op\_t} \Var{op}] An array of dynamic unwind
+ directives. See Section ``Dynamic unwind directives'' for a
+ description of the directives.
+\end{description}
+A region descriptor with an \Var{insn\_count} of zero is an
+\emph{empty region} and such regions are perfectly legal. In fact,
+empty regions can be useful to establish a particular frame state
+before the start of another region.
+
+A single region list can be shared across multiple procedures provided
+those procedures share a common prologue and epilogue (their bodies
+may differ, of course). Normally, such procedures consist of a canned
+prologue, the body, and a canned epilogue. This could be described by
+two regions: one covering the prologue and one covering the epilogue.
+Since the body length is variable, the latter region would need to
+specify a negative value in \Var{insn\_count} such that
+\Prog{libunwind} knows that the region covers the end of the procedure
+(up to the address specified by \Var{end\_ip}).
+
+The region descriptor is a variable length structure to make it
+possible to allocate all the necessary memory with a single
+memory-allocation request. To facilitate the allocation of a region
+descriptors \Prog{libunwind} provides a helper routine with the
+following synopsis:
+
+\noindent
+\Type{size\_t} \Func{\_U\_dyn\_region\_size}(\Type{int} \Var{op\_count});
+
+This routine returns the number of bytes needed to hold a region
+descriptor with space for \Var{op\_count} unwind directives. Note
+that the length of the \Var{op} array does not have to match exactly
+with the number of directives in a region. Instead, it is sufficient
+if the \Var{op} array contains at least as many entries as there are
+directives, since the end of the directives can always be indicated
+with the \Const{UNW\_DYN\_STOP} directive.
+
+\section{Dynamic unwind directives}
+
+A dynamic unwind directive describes how the frame state changes
+at a particular point within a region. The description is in
+the form of a structure of type \Type{unw\_dyn\_op\_t}. This
+structure has the following members:
+\begin{description}
+\item[\Type{int8\_t} \Var{tag}] The operation tag. Must be one
+ of the \Type{unw\_dyn\_operation\_t} values described below.
+\item[\Type{int8\_t} \Var{qp}] The qualifying predicate that controls
+ whether or not this directive is active. This is useful for
+ predicated architecturs such as IA-64 or ARM, where the contents of
+ another (callee-saved) register determines whether or not an
+ instruction is executed (takes effect). If the directive is always
+ active, this member should be set to the manifest constant
+ \Const{\_U\_QP\_TRUE} (this constant is defined for all
+ architectures, predicated or not).
+\item[\Type{int16\_t} \Var{reg}] The number of the register affected
+ by the instruction.
+\item[\Type{int32\_t} \Var{when}] The region-relative number of
+ the instruction to which this directive applies. For example,
+ a value of 0 means that the effect described by this directive
+ has taken place once the first instruction in the region has
+ executed.
+\item[\Type{unw\_word\_t} \Var{val}] The value to be applied by the
+ operation tag. The exact meaning of this value varies by tag. See
+ Section ``Operation tags'' below.
+\end{description}
+It is perfectly legitimate to specify multiple dynamic unwind
+directives with the same \Var{when} value, if a particular instruction
+has a complex effect on the frame state.
+
+Empty regions by definition contain no actual instructions and as such
+the directives are not tied to a particular instruction. By
+convention, the \Var{when} member should be set to 0, however.
+
+There is no need for the dynamic unwind directives to appear
+in order of increasing \Var{when} values. If the directives happen to
+be sorted in that order, it may result in slightly faster execution,
+but a runtime code-generator should not go to extra lengths just to
+ensure that the directives are sorted.
+
+IMPLEMENTATION NOTE: should \Prog{libunwind} implementations for
+certain architectures prefer the list of unwind directives to be
+sorted, it is recommended that such implementations first check
+whether the list happens to be sorted already and, if not, sort the
+directives explicitly before the first use. With this approach, the
+overhead of explicit sorting is only paid when there is a real benefit
+and if the runtime code-generator happens to generated sorted lists
+naturally, the performance penalty is limited to a simple O(N) check.
+
+\subsection{Operations tags}
+
+The possible operation tags are defined by enumeration type
+\Type{unw\_dyn\_operation\_t} which defines the following
+values:
+\begin{description}
+
+\item[\Const{UNW\_DYN\_STOP}] Marks the end of the dynamic unwind
+ directive list. All remaining entries in the \Var{op} array of the
+ region-descriptor are ignored. This tag is guaranteed to have a
+ value of 0.
+
+\item[\Const{UNW\_DYN\_SAVE\_REG}] Marks an instruction which saves
+ register \Var{reg} to register \Var{val}.
+
+\item[\Const{UNW\_DYN\_SPILL\_FP\_REL}] Marks an instruction which
+ spills register \Var{reg} to a frame-pointer-relative location. The
+ frame-pointer-relative offset is given by the value stored in member
+ \Var{val}. See the architecture-specific sections for a description
+ of the stack frame layout.
+
+\item[\Const{UNW\_DYN\_SPILL\_SP\_REL}] Marks an instruction which
+ spills register \Var{reg} to a stack-pointer-relative location. The
+ stack-pointer-relative offset is given by the value stored in member
+ \Var{val}. See the architecture-specific sections for a description
+ of the stack frame layout.
+
+\item[\Const{UNW\_DYN\_ADD}] Marks an instruction which adds
+ the constant value \Var{val} to register \Var{reg}. To add subtract
+ a constant value, store the two's-complement of the value in
+ \Var{val}. The set of registers that can be specified for this tag
+ is described in the architecture-specific sections below.
+
+\item[\Const{UNW\_DYN\_POP\_FRAMES}]
+
+\item[\Const{UNW\_DYN\_LABEL\_STATE}]
+
+\item[\Const{UNW\_DYN\_COPY\_STATE}]
+
+\item[\Const{UNW\_DYN\_ALIAS}]
+
+\end{description}
+
+unw\_dyn\_op\_t
+
+\_U\_dyn\_op\_save\_reg();
+\_U\_dyn\_op\_spill\_fp\_rel();
+\_U\_dyn\_op\_spill\_sp\_rel();
+\_U\_dyn\_op\_add();
+\_U\_dyn\_op\_pop\_frames();
+\_U\_dyn\_op\_label\_state();
+\_U\_dyn\_op\_copy\_state();
+\_U\_dyn\_op\_alias();
+\_U\_dyn\_op\_stop();
+
+\section{IA-64 specifics}
+
+- meaning of segbase member in table-info/table-remote-info format
+- format of table\_data in table-info/table-remote-info format
+- instruction size: each bundle is counted as 3 instructions, regardless
+ of template (MLX)
+- describe stack-frame layout, especially with regards to sp-relative
+ and fp-relative addressing
+- UNW\_DYN\_ADD can only add to ``sp'' (always a negative value); use
+ POP\_FRAMES otherwise
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{\_U\_dyn\_register(3)},
+\SeeAlso{\_U\_dyn\_cancel(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/libunwind-ia64.man b/src/pal/src/libunwind/doc/libunwind-ia64.man
new file mode 100644
index 0000000000..06b141eb3e
--- /dev/null
+++ b/src/pal/src/libunwind/doc/libunwind-ia64.man
@@ -0,0 +1,314 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:44 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "LIBUNWIND\-IA64" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+libunwind\-ia64
+\-\- IA\-64\-specific support in libunwind
+.PP
+.SH INTRODUCTION
+
+.PP
+The IA\-64 version of libunwind
+uses a platform\-string of
+ia64
+and, at least in theory, should be able to support all
+operating systems adhering to the processor\-specific ABI defined for
+the Itanium Processor Family. This includes both little\-endian Linux
+and big\-endian HP\-UX. Furthermore, to make it possible for a single
+library to unwind both 32\- and 64\-bit targets, the type
+unw_word_t
+is always defined to be 64 bits wide (independent
+of the natural word\-size of the host). Having said that, the current
+implementation has been tested only with IA\-64 Linux.
+.PP
+When targeting IA\-64, the libunwind
+header file defines the
+macro UNW_TARGET_IA64
+as 1 and the macro UNW_TARGET
+as ``ia64\&'' (without the quotation marks). The former makes it
+possible for platform\-dependent unwind code to use
+conditional\-compilation to select an appropriate implementation. The
+latter is useful for stringification purposes and to construct
+target\-platform\-specific symbols.
+.PP
+One special feature of IA\-64 is the use of NaT bits to support
+speculative execution. Often, NaT bits are thought of as the ``65\-th
+bit\&'' of a general register. However, to make everything fit into
+64\-bit wide unw_word_t
+values, libunwind
+treats the
+NaT\-bits like separate boolean registers, whose 64\-bit value is either
+TRUE (non\-zero) or FALSE (zero).
+.PP
+.SH MACHINE\-STATE
+
+.PP
+The machine\-state (set of registers) that is accessible through
+libunwind
+depends on the type of stack frame that a cursor
+points to. For normal frames, all ``preserved\&'' (callee\-saved)
+registers are accessible. For signal\-trampoline frames, all registers
+(including ``scratch\&'' (caller\-saved) registers) are accessible. Most
+applications do not have to worry a\-priori about which registers are
+accessible when. In case of doubt, it is always safe to \fItry\fP
+to
+access a register (via unw_get_reg()
+or
+unw_get_fpreg())
+and if the register isn\&'t accessible, the
+call will fail with a return\-value of \-UNW_EBADREG\&.
+.PP
+As a special exception to the above general rule, scratch registers
+r15\-r18
+are always accessible, even in normal
+frames. This makes it possible to pass arguments, e.g., to exception
+handlers.
+.PP
+For a detailed description of the IA\-64 register usage convention,
+please see the ``Itanium Software Conventions and Runtime Architecture
+Guide\&'', available at:
+.ce 100
+\fBhttp://www.intel.com/design/itanium/downloads/245358.htm\fP
+.ce 0
+
+.PP
+.SH REGISTER NAMES
+
+.PP
+The IA\-64\-version of libunwind
+defines three kinds of register
+name macros: frame\-register macros, normal register macros, and
+convenience macros. Below, we describe each kind in turn:
+.PP
+.SS FRAME\-REGISTER MACROS
+.PP
+Frame\-registers are special (pseudo) registers because they always
+have a valid value, even though sometimes they do not get saved
+explicitly (e.g., if a memory stack frame is 16 bytes in size, the
+previous stack\-pointer value can be calculated simply as
+sp+16,
+so there is no need to save the stack\-pointer
+explicitly). Moreover, the set of frame register values uniquely
+identifies a stack frame. The IA\-64 architecture defines two stacks
+(a memory and a register stack). Including the instruction\-pointer
+(IP), this means there are three frame registers:
+.TP
+UNW_IA64_IP:
+ Contains the instruction pointer (IP, or
+``program counter\&'') of the current stack frame. Given this value,
+the remaining machine\-state corresponds to the register\-values that
+were present in the CPU when it was just about to execute the
+instruction pointed to by UNW_IA64_IP\&.
+Bits 0 and 1 of
+this frame\-register encode the slot number of the instruction.
+\fBNote:\fP
+Due to the way the call instruction works on IA\-64,
+the slot number is usually zero, but can be non\-zero, e.g., in the
+stack\-frame of a signal\-handler trampoline.
+.TP
+UNW_IA64_SP:
+ Contains the (memory) stack\-pointer
+value (SP).
+.TP
+UNW_IA64_BSP:
+ Contains the register backing\-store
+pointer (BSP). \fBNote:\fP
+the value in this register is equal
+to the contents of register ar.bsp
+at the time the
+instruction at UNW_IA64_IP
+was about to begin execution.
+.PP
+.SS NORMAL REGISTER MACROS
+.PP
+The following normal register name macros are available:
+.TP
+UNW_IA64_GR:
+ The base\-index for general (integer)
+registers. Add an index in the range from 0..127 to get a
+particular general register. For example, to access r4,
+the index UNW_IA64_GR+4
+should be used.
+Registers r0
+and r1
+(gp)
+are read\-only,
+and any attempt to write them will result in an error
+(\-UNW_EREADONLYREG).
+Even though r1
+is
+read\-only, libunwind
+will automatically adjust its value if
+the instruction\-pointer (UNW_IA64_IP)
+is modified. For
+example, if UNW_IA64_IP
+is set to a value inside a
+function func(),
+then reading
+UNW_IA64_GR+1
+will return the global\-pointer
+value for this function.
+.TP
+UNW_IA64_NAT:
+ The base\-index for the NaT bits of the
+general (integer) registers. A non\-zero value in these registers
+corresponds to a set NaT\-bit. Add an index in the range from 0..127
+to get a particular NaT\-bit register. For example, to access the
+NaT bit of r4,
+the index UNW_IA64_NAT+4
+should be used.
+.TP
+UNW_IA64_FR:
+ The base\-index for floating\-point
+registers. Add an index in the range from 0..127 to get a
+particular floating\-point register. For example, to access
+f2,
+the index UNW_IA64_FR+2
+should be
+used. Registers f0
+and f1
+are read\-only, and any
+attempt to write to indices UNW_IA64_FR+0
+or
+UNW_IA64_FR+1
+will result in an error
+(\-UNW_EREADONLYREG).
+.TP
+UNW_IA64_AR:
+ The base\-index for application
+registers. Add an index in the range from 0..127 to get a
+particular application register. For example, to access
+ar40,
+the index UNW_IA64_AR+40
+should be
+used. The IA\-64 architecture defines several application registers
+as ``reserved for future use\&''\&. Attempting to access such registers
+results in an error (\-UNW_EBADREG).
+.TP
+UNW_IA64_BR:
+ The base\-index for branch registers.
+Add an index in the range from 0..7 to get a particular branch
+register. For example, to access b6,
+the index
+UNW_IA64_BR+6
+should be used.
+.TP
+UNW_IA64_PR:
+ Contains the set of predicate registers.
+This 64\-bit wide register contains registers p0
+through
+p63
+in the ``broad\-side\&'' format. Just like with the
+``move predicates\&'' instruction, the registers are mapped as if
+CFM.rrb.pr
+were set to 0. Thus, in general the value of
+predicate register pN
+with N>=16 can be found
+in bit 16 + ((N\-16)+CFM.rrb.pr) % 48\&.
+.TP
+UNW_IA64_CFM:
+ Contains the current\-frame\-mask
+register.
+.PP
+.SS CONVENIENCE MACROS
+.PP
+Convenience macros are simply aliases for certain frequently used
+registers:
+.TP
+UNW_IA64_GP:
+ Alias for UNW_IA64_GR+1,
+the global\-pointer register.
+.TP
+UNW_IA64_TP:
+ Alias for UNW_IA64_GR+13,
+the thread\-pointer register.
+.TP
+UNW_IA64_AR_RSC:
+ Alias for UNW_IA64_GR+16,
+the register\-stack configuration register.
+.TP
+UNW_IA64_AR_BSP:
+ Alias for
+UNW_IA64_GR+17\&.
+This register index accesses the
+value of register ar.bsp
+as of the time it was last saved
+explicitly. This is rarely what you want. Normally, you\&'ll want to
+use UNW_IA64_BSP
+instead.
+.TP
+UNW_IA64_AR_BSPSTORE:
+ Alias for UNW_IA64_GR+18,
+the register\-backing store write pointer.
+.TP
+UNW_IA64_AR_RNAT:
+ Alias for UNW_IA64_GR+19,
+the register\-backing store NaT\-collection register.
+.TP
+UNW_IA64_AR_CCV:
+ Alias for UNW_IA64_GR+32,
+the compare\-and\-swap value register.
+.TP
+UNW_IA64_AR_CSD:
+ Alias for UNW_IA64_GR+25,
+the compare\-and\-swap\-data register (used by 16\-byte atomic operations).
+.TP
+UNW_IA64_AR_UNAT:
+ Alias for UNW_IA64_GR+36,
+the user NaT\-collection register.
+.TP
+UNW_IA64_AR_FPSR:
+ Alias for UNW_IA64_GR+40,
+the floating\-point status (and control) register.
+.TP
+UNW_IA64_AR_PFS:
+ Alias for UNW_IA64_GR+64,
+the previous frame\-state register.
+.TP
+UNW_IA64_AR_LC:
+ Alias for UNW_IA64_GR+65
+the loop\-count register.
+.TP
+UNW_IA64_AR_EC:
+ Alias for UNW_IA64_GR+66,
+the epilogue\-count register.
+.PP
+.SH THE UNWIND\-CONTEXT TYPE
+
+.PP
+On IA\-64, unw_context_t
+is simply an alias for
+ucontext_t
+(as defined by the Single UNIX Spec). This implies
+that it is possible to initialize a value of this type not just with
+unw_getcontext(),
+but also with getcontext(),
+for
+example. However, since this is an IA\-64\-specific extension to
+libunwind,
+portable code should not rely on this equivalence.
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/libunwind-ia64.tex b/src/pal/src/libunwind/doc/libunwind-ia64.tex
new file mode 100644
index 0000000000..c08946dc4b
--- /dev/null
+++ b/src/pal/src/libunwind/doc/libunwind-ia64.tex
@@ -0,0 +1,216 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{libunwind-ia64}{David Mosberger-Tang}{Programming Library}{IA-64-specific support in libunwind}libunwind-ia64 -- IA-64-specific support in libunwind
+\end{Name}
+
+
+\section{Introduction}
+
+The IA-64 version of \Prog{libunwind} uses a platform-string of
+\texttt{ia64} and, at least in theory, should be able to support all
+operating systems adhering to the processor-specific ABI defined for
+the Itanium Processor Family. This includes both little-endian Linux
+and big-endian HP-UX. Furthermore, to make it possible for a single
+library to unwind both 32- and 64-bit targets, the type
+\Type{unw\_word\_t} is always defined to be 64 bits wide (independent
+of the natural word-size of the host). Having said that, the current
+implementation has been tested only with IA-64 Linux.
+
+When targeting IA-64, the \Prog{libunwind} header file defines the
+macro \Const{UNW\_TARGET\_IA64} as 1 and the macro \Const{UNW\_TARGET}
+as ``ia64'' (without the quotation marks). The former makes it
+possible for platform-dependent unwind code to use
+conditional-compilation to select an appropriate implementation. The
+latter is useful for stringification purposes and to construct
+target-platform-specific symbols.
+
+One special feature of IA-64 is the use of NaT bits to support
+speculative execution. Often, NaT bits are thought of as the ``65-th
+bit'' of a general register. However, to make everything fit into
+64-bit wide \Type{unw\_word\_t} values, \Prog{libunwind} treats the
+NaT-bits like separate boolean registers, whose 64-bit value is either
+TRUE (non-zero) or FALSE (zero).
+
+
+\section{Machine-State}
+
+The machine-state (set of registers) that is accessible through
+\Prog{libunwind} depends on the type of stack frame that a cursor
+points to. For normal frames, all ``preserved'' (callee-saved)
+registers are accessible. For signal-trampoline frames, all registers
+(including ``scratch'' (caller-saved) registers) are accessible. Most
+applications do not have to worry a-priori about which registers are
+accessible when. In case of doubt, it is always safe to \emph{try} to
+access a register (via \Func{unw\_get\_reg}() or
+\Func{unw\_get\_fpreg}()) and if the register isn't accessible, the
+call will fail with a return-value of \texttt{-}\Const{UNW\_EBADREG}.
+
+As a special exception to the above general rule, scratch registers
+\texttt{r15}-\texttt{r18} are always accessible, even in normal
+frames. This makes it possible to pass arguments, e.g., to exception
+handlers.
+
+For a detailed description of the IA-64 register usage convention,
+please see the ``Itanium Software Conventions and Runtime Architecture
+Guide'', available at:
+\begin{center}
+ \URL{http://www.intel.com/design/itanium/downloads/245358.htm}
+\end{center}
+
+
+\section{Register Names}
+
+The IA-64-version of \Prog{libunwind} defines three kinds of register
+name macros: frame-register macros, normal register macros, and
+convenience macros. Below, we describe each kind in turn:
+
+
+\subsection{Frame-register Macros}
+
+Frame-registers are special (pseudo) registers because they always
+have a valid value, even though sometimes they do not get saved
+explicitly (e.g., if a memory stack frame is 16 bytes in size, the
+previous stack-pointer value can be calculated simply as
+\texttt{sp+16}, so there is no need to save the stack-pointer
+explicitly). Moreover, the set of frame register values uniquely
+identifies a stack frame. The IA-64 architecture defines two stacks
+(a memory and a register stack). Including the instruction-pointer
+(IP), this means there are three frame registers:
+\begin{Description}
+\item[\Const{UNW\_IA64\_IP}:] Contains the instruction pointer (IP, or
+ ``program counter'') of the current stack frame. Given this value,
+ the remaining machine-state corresponds to the register-values that
+ were present in the CPU when it was just about to execute the
+ instruction pointed to by \Const{UNW\_IA64\_IP}. Bits 0 and 1 of
+ this frame-register encode the slot number of the instruction.
+ \textbf{Note:} Due to the way the call instruction works on IA-64,
+ the slot number is usually zero, but can be non-zero, e.g., in the
+ stack-frame of a signal-handler trampoline.
+\item[\Const{UNW\_IA64\_SP}:] Contains the (memory) stack-pointer
+ value (SP).
+\item[\Const{UNW\_IA64\_BSP}:] Contains the register backing-store
+ pointer (BSP). \textbf{Note:} the value in this register is equal
+ to the contents of register \texttt{ar.bsp} at the time the
+ instruction at \Const{UNW\_IA64\_IP} was about to begin execution.
+\end{Description}
+
+
+\subsection{Normal Register Macros}
+
+The following normal register name macros are available:
+\begin{Description}
+\item[\Const{UNW\_IA64\_GR}:] The base-index for general (integer)
+ registers. Add an index in the range from 0..127 to get a
+ particular general register. For example, to access \texttt{r4},
+ the index \Const{UNW\_IA64\_GR}\texttt{+4} should be used.
+ Registers \texttt{r0} and \texttt{r1} (\texttt{gp}) are read-only,
+ and any attempt to write them will result in an error
+ (\texttt{-}\Const{UNW\_EREADONLYREG}). Even though \texttt{r1} is
+ read-only, \Prog{libunwind} will automatically adjust its value if
+ the instruction-pointer (\Const{UNW\_IA64\_IP}) is modified. For
+ example, if \Const{UNW\_IA64\_IP} is set to a value inside a
+ function \Func{func}(), then reading
+ \Const{UNW\_IA64\_GR}\texttt{+1} will return the global-pointer
+ value for this function.
+\item[\Const{UNW\_IA64\_NAT}:] The base-index for the NaT bits of the
+ general (integer) registers. A non-zero value in these registers
+ corresponds to a set NaT-bit. Add an index in the range from 0..127
+ to get a particular NaT-bit register. For example, to access the
+ NaT bit of \texttt{r4}, the index \Const{UNW\_IA64\_NAT}\texttt{+4}
+ should be used.
+\item[\Const{UNW\_IA64\_FR}:] The base-index for floating-point
+ registers. Add an index in the range from 0..127 to get a
+ particular floating-point register. For example, to access
+ \texttt{f2}, the index \Const{UNW\_IA64\_FR}\texttt{+2} should be
+ used. Registers \texttt{f0} and \texttt{f1} are read-only, and any
+ attempt to write to indices \Const{UNW\_IA64\_FR}\texttt{+0} or
+ \Const{UNW\_IA64\_FR}\texttt{+1} will result in an error
+ (\texttt{-}\Const{UNW\_EREADONLYREG}).
+\item[\Const{UNW\_IA64\_AR}:] The base-index for application
+ registers. Add an index in the range from 0..127 to get a
+ particular application register. For example, to access
+ \texttt{ar40}, the index \Const{UNW\_IA64\_AR}\texttt{+40} should be
+ used. The IA-64 architecture defines several application registers
+ as ``reserved for future use''. Attempting to access such registers
+ results in an error (\texttt{-}\Const{UNW\_EBADREG}).
+\item[\Const{UNW\_IA64\_BR}:] The base-index for branch registers.
+ Add an index in the range from 0..7 to get a particular branch
+ register. For example, to access \texttt{b6}, the index
+ \Const{UNW\_IA64\_BR}\texttt{+6} should be used.
+\item[\Const{UNW\_IA64\_PR}:] Contains the set of predicate registers.
+ This 64-bit wide register contains registers \texttt{p0} through
+ \texttt{p63} in the ``broad-side'' format. Just like with the
+ ``move predicates'' instruction, the registers are mapped as if
+ \texttt{CFM.rrb.pr} were set to 0. Thus, in general the value of
+ predicate register \texttt{p}$N$ with $N$>=16 can be found
+ in bit \texttt{16 + (($N$-16)+CFM.rrb.pr) \% 48}.
+\item[\Const{UNW\_IA64\_CFM}:] Contains the current-frame-mask
+ register.
+\end{Description}
+
+
+\subsection{Convenience Macros}
+
+Convenience macros are simply aliases for certain frequently used
+registers:
+\begin{Description}
+\item[\Const{UNW\_IA64\_GP}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+1},
+ the global-pointer register.
+\item[\Const{UNW\_IA64\_TP}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+13},
+ the thread-pointer register.
+\item[\Const{UNW\_IA64\_AR\_RSC}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+16},
+ the register-stack configuration register.
+\item[\Const{UNW\_IA64\_AR\_BSP}:] Alias for
+ \Const{UNW\_IA64\_GR}\texttt{+17}. This register index accesses the
+ value of register \texttt{ar.bsp} as of the time it was last saved
+ explicitly. This is rarely what you want. Normally, you'll want to
+ use \Const{UNW\_IA64\_BSP} instead.
+\item[\Const{UNW\_IA64\_AR\_BSPSTORE}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+18},
+ the register-backing store write pointer.
+\item[\Const{UNW\_IA64\_AR\_RNAT}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+19},
+ the register-backing store NaT-collection register.
+\item[\Const{UNW\_IA64\_AR\_CCV}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+32},
+ the compare-and-swap value register.
+\item[\Const{UNW\_IA64\_AR\_CSD}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+25},
+ the compare-and-swap-data register (used by 16-byte atomic operations).
+\item[\Const{UNW\_IA64\_AR\_UNAT}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+36},
+ the user NaT-collection register.
+\item[\Const{UNW\_IA64\_AR\_FPSR}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+40},
+ the floating-point status (and control) register.
+\item[\Const{UNW\_IA64\_AR\_PFS}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+64},
+ the previous frame-state register.
+\item[\Const{UNW\_IA64\_AR\_LC}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+65}
+ the loop-count register.
+\item[\Const{UNW\_IA64\_AR\_EC}:] Alias for \Const{UNW\_IA64\_GR}\texttt{+66},
+ the epilogue-count register.
+\end{Description}
+
+
+\section{The Unwind-Context Type}
+
+On IA-64, \Type{unw\_context\_t} is simply an alias for
+\Type{ucontext\_t} (as defined by the Single UNIX Spec). This implies
+that it is possible to initialize a value of this type not just with
+\Func{unw\_getcontext}(), but also with \Func{getcontext}(), for
+example. However, since this is an IA-64-specific extension to
+\Prog{libunwind}, portable code should not rely on this equivalence.
+
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/libunwind-ptrace.man b/src/pal/src/libunwind/doc/libunwind-ptrace.man
new file mode 100644
index 0000000000..985fcae275
--- /dev/null
+++ b/src/pal/src/libunwind/doc/libunwind-ptrace.man
@@ -0,0 +1,220 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:44 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "LIBUNWIND\-PTRACE" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+libunwind\-ptrace
+\-\- ptrace() support in libunwind
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind\-ptrace.h>
+.br
+.PP
+unw_accessors_t
+_UPT_accessors;
+.br
+.PP
+void *_UPT_create(pid_t);
+.br
+void
+_UPT_destroy(void *);
+.br
+.PP
+int
+_UPT_find_proc_info(unw_addr_space_t,
+unw_word_t,
+unw_proc_info_t *,
+int,
+void *);
+.br
+void
+_UPT_put_unwind_info(unw_addr_space_t,
+unw_proc_info_t *,
+void *);
+.br
+int
+_UPT_get_dyn_info_list_addr(unw_addr_space_t,
+unw_word_t *,
+void *);
+.br
+int
+_UPT_access_mem(unw_addr_space_t,
+unw_word_t,
+unw_word_t *,
+int,
+void *);
+.br
+int
+_UPT_access_reg(unw_addr_space_t,
+unw_regnum_t,
+unw_word_t *,
+int,
+void *);
+.br
+int
+_UPT_access_fpreg(unw_addr_space_t,
+unw_regnum_t,
+unw_fpreg_t *,
+int,
+void *);
+.br
+int
+_UPT_get_proc_name(unw_addr_space_t,
+unw_word_t,
+char *,
+size_t,
+unw_word_t *,
+void *);
+.br
+int
+_UPT_resume(unw_addr_space_t,
+unw_cursor_t *,
+void *);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The ptrace(2)
+system\-call makes it possible for a process to
+gain access to the machine\-state and virtual memory of \fIanother\fP
+process. With the right set of call\-back routines, it is therefore
+possible to hook up libunwind
+to another process via
+ptrace(2).
+While it\&'s not very difficult to do so directly,
+libunwind
+further facilitates this task by providing
+ready\-to\-use callbacks for this purpose. The routines and variables
+implementing this facility use a name\-prefix of _UPT,
+which is
+stands for ``unwind\-via\-ptrace\&''\&.
+.PP
+An application that wants to use the _UPT\-facility
+first needs
+to create a new libunwind
+address\-space that represents the
+target process. This is done by calling
+unw_create_addr_space().
+In many cases, the application
+will simply want to pass the address of _UPT_accessors
+as the
+first argument to this routine. Doing so will ensure that
+libunwind
+will be able to properly unwind the target process.
+However, in special circumstances, an application may prefer to use
+only portions of the _UPT\-facility.
+For this reason, the
+individual callback routines (_UPT_find_proc_info(),
+_UPT_put_unwind_info(),
+etc.) are also available for direct
+use. Of course, the addresses of these routines could also be picked
+up from _UPT_accessors,
+but doing so would prevent static
+initialization. Also, when using _UPT_accessors,
+\fIall\fP
+the callback routines will be linked into the application, even if
+they are never actually called.
+.PP
+Next, the application can turn on ptrace\-mode on the target process,
+either by forking a new process, invoking PTRACE_TRACEME,
+and
+then starting the target program (via execve(2)),
+or by
+directly attaching to an already running process (via
+PTRACE_ATTACH).
+Either way, once the process\-ID (pid) of the
+target process is known, a _UPT\-info\-structure
+can be created
+by calling _UPT_create(),
+passing the pid of the target process
+as the only argument. The returned void\-pointer then needs to be
+passed as the ``argument\&'' pointer (third argument) to
+unw_init_remote().
+.PP
+The _UPT_resume()
+routine can be used to resume execution of
+the target process. It simply invokes ptrace(2)
+with a command
+value of PTRACE_CONT\&.
+.PP
+When the application is done using libunwind
+on the target
+process, _UPT_destroy()
+needs to be called, passing it the
+void\-pointer that was returned by the corresponding call to
+_UPT_create().
+This ensures that all memory and other
+resources are freed up.
+.PP
+.SH AVAILABILITY
+
+.PP
+Since ptrace(2)
+works within a single machine only, the
+_UPT\-facility
+by definition is not available in
+libunwind\-versions
+configured for cross\-unwinding.
+.PP
+.SH THREAD SAFETY
+
+.PP
+The _UPT\-facility
+assumes that a single _UPT\-info
+structure is never shared between threads. Because of this, no
+explicit locking is used. As long as only one thread uses
+a _UPT\-info
+structure at any given time, this facility
+is thread\-safe.
+.PP
+.SH RETURN VALUE
+
+.PP
+_UPT_create()
+may return a NULL
+pointer if it fails
+to create the _UPT\-info\-structure
+for any reason. For the
+current implementation, the only reason this call may fail is when the
+system is out of memory.
+.PP
+.SH FILES
+
+.PP
+.TP
+libunwind\-ptrace.h
+ Headerfile to include when using the
+interface defined by this library.
+.TP
+\fB\-l\fPunwind\-ptrace \fB\-l\fPunwind\-generic
+ Linker\-switches to add when building a program that uses the
+functions defined by this library.
+.PP
+.SH SEE ALSO
+
+.PP
+execve(2),
+libunwind(3),
+ptrace(2)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/libunwind-ptrace.tex b/src/pal/src/libunwind/doc/libunwind-ptrace.tex
new file mode 100644
index 0000000000..fe074d8619
--- /dev/null
+++ b/src/pal/src/libunwind/doc/libunwind-ptrace.tex
@@ -0,0 +1,134 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{libunwind-ptrace}{David Mosberger-Tang}{Programming Library}{ptrace() support in libunwind}libunwind-ptrace -- ptrace() support in libunwind
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind-ptrace.h$>$}\\
+
+\noindent
+\Type{unw\_accessors\_t} \Var{\_UPT\_accessors};\\
+
+\Type{void~*}\Func{\_UPT\_create}(\Type{pid\_t});\\
+\noindent
+\Type{void} \Func{\_UPT\_destroy}(\Type{void~*});\\
+
+\noindent
+\Type{int} \Func{\_UPT\_find\_proc\_info}(\Type{unw\_addr\_space\_t}, \Type{unw\_word\_t}, \Type{unw\_proc\_info\_t~*}, \Type{int}, \Type{void~*});\\
+\noindent
+\Type{void} \Func{\_UPT\_put\_unwind\_info}(\Type{unw\_addr\_space\_t}, \Type{unw\_proc\_info\_t~*}, \Type{void~*});\\
+\noindent
+\Type{int} \Func{\_UPT\_get\_dyn\_info\_list\_addr}(\Type{unw\_addr\_space\_t}, \Type{unw\_word\_t~*}, \Type{void~*});\\
+\noindent
+\Type{int} \Func{\_UPT\_access\_mem}(\Type{unw\_addr\_space\_t}, \Type{unw\_word\_t}, \Type{unw\_word\_t~*}, \Type{int}, \Type{void~*});\\
+\noindent
+\Type{int} \Func{\_UPT\_access\_reg}(\Type{unw\_addr\_space\_t}, \Type{unw\_regnum\_t}, \Type{unw\_word\_t~*}, \Type{int}, \Type{void~*});\\
+\noindent
+\Type{int} \Func{\_UPT\_access\_fpreg}(\Type{unw\_addr\_space\_t}, \Type{unw\_regnum\_t}, \Type{unw\_fpreg\_t~*}, \Type{int}, \Type{void~*});\\
+\noindent
+\Type{int} \Func{\_UPT\_get\_proc\_name}(\Type{unw\_addr\_space\_t}, \Type{unw\_word\_t}, \Type{char~*}, \Type{size\_t}, \Type{unw\_word\_t~*}, \Type{void~*});\\
+\noindent
+\Type{int} \Func{\_UPT\_resume}(\Type{unw\_addr\_space\_t}, \Type{unw\_cursor\_t~*}, \Type{void~*});\\
+
+\section{Description}
+
+The \Func{ptrace}(2) system-call makes it possible for a process to
+gain access to the machine-state and virtual memory of \emph{another}
+process. With the right set of call-back routines, it is therefore
+possible to hook up \Prog{libunwind} to another process via
+\Func{ptrace}(2). While it's not very difficult to do so directly,
+\Prog{libunwind} further facilitates this task by providing
+ready-to-use callbacks for this purpose. The routines and variables
+implementing this facility use a name-prefix of \Func{\_UPT}, which is
+stands for ``unwind-via-ptrace''.
+
+An application that wants to use the \Func{\_UPT}-facility first needs
+to create a new \Prog{libunwind} address-space that represents the
+target process. This is done by calling
+\Func{unw\_create\_addr\_space}(). In many cases, the application
+will simply want to pass the address of \Var{\_UPT\_accessors} as the
+first argument to this routine. Doing so will ensure that
+\Prog{libunwind} will be able to properly unwind the target process.
+However, in special circumstances, an application may prefer to use
+only portions of the \Prog{\_UPT}-facility. For this reason, the
+individual callback routines (\Func{\_UPT\_find\_proc\_info}(),
+\Func{\_UPT\_put\_unwind\_info}(), etc.) are also available for direct
+use. Of course, the addresses of these routines could also be picked
+up from \Var{\_UPT\_accessors}, but doing so would prevent static
+initialization. Also, when using \Var{\_UPT\_accessors}, \emph{all}
+the callback routines will be linked into the application, even if
+they are never actually called.
+
+Next, the application can turn on ptrace-mode on the target process,
+either by forking a new process, invoking \Const{PTRACE\_TRACEME}, and
+then starting the target program (via \Func{execve}(2)), or by
+directly attaching to an already running process (via
+\Const{PTRACE\_ATTACH}). Either way, once the process-ID (pid) of the
+target process is known, a \Prog{\_UPT}-info-structure can be created
+by calling \Func{\_UPT\_create}(), passing the pid of the target process
+as the only argument. The returned void-pointer then needs to be
+passed as the ``argument'' pointer (third argument) to
+\Func{unw\_init\_remote}().
+
+The \Func{\_UPT\_resume}() routine can be used to resume execution of
+the target process. It simply invokes \Func{ptrace}(2) with a command
+value of \Const{PTRACE\_CONT}.
+
+When the application is done using \Prog{libunwind} on the target
+process, \Func{\_UPT\_destroy}() needs to be called, passing it the
+void-pointer that was returned by the corresponding call to
+\Func{\_UPT\_create}(). This ensures that all memory and other
+resources are freed up.
+
+\section{Availability}
+
+Since \Func{ptrace}(2) works within a single machine only, the
+\Prog{\_UPT}-facility by definition is not available in
+\Prog{libunwind}-versions configured for cross-unwinding.
+
+\section{Thread Safety}
+
+The \Prog{\_UPT}-facility assumes that a single \Prog{\_UPT}-info
+structure is never shared between threads. Because of this, no
+explicit locking is used. As long as only one thread uses
+a \Prog{\_UPT}-info structure at any given time, this facility
+is thread-safe.
+
+\section{Return Value}
+
+\Func{\_UPT\_create}() may return a \Const{NULL} pointer if it fails
+to create the \Prog{\_UPT}-info-structure for any reason. For the
+current implementation, the only reason this call may fail is when the
+system is out of memory.
+
+\section{Files}
+
+\begin{Description}
+\item[\File{libunwind-ptrace.h}] Headerfile to include when using the
+ interface defined by this library.
+\item[\Opt{-l}\File{unwind-ptrace} \Opt{-l}\File{unwind-generic}]
+ Linker-switches to add when building a program that uses the
+ functions defined by this library.
+\end{Description}
+
+\section{See Also}
+
+execve(2),
+\SeeAlso{libunwind(3)},
+ptrace(2)
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/libunwind-setjmp.man b/src/pal/src/libunwind/doc/libunwind-setjmp.man
new file mode 100644
index 0000000000..1faa38e475
--- /dev/null
+++ b/src/pal/src/libunwind/doc/libunwind-setjmp.man
@@ -0,0 +1,132 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:44 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "LIBUNWIND\-SETJMP" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+libunwind\-setjmp
+\-\- libunwind\-based non\-local gotos
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <setjmp.h>
+.br
+.PP
+int
+setjmp(jmp_buf env);
+.br
+void
+longjmp(jmp_buf env,
+int val);
+.br
+int
+_setjmp(jmp_buf env);
+.br
+void
+_longjmp(jmp_buf env,
+int val);
+.br
+int
+sigsetjmp(sigjmp_buf env,
+int savemask);
+.br
+void
+siglongjmp(sigjmp_buf env,
+int val);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unwind\-setjmp
+library offers a libunwind\-based
+implementation of non\-local gotos. This implementation is intended to
+be a drop\-in replacement for the normal, system\-provided routines of
+the same name. The main advantage of using the unwind\-setjmp
+library is that setting up a non\-local goto via one of the
+setjmp()
+routines is very fast. Typically, just 2 or 3 words
+need to be saved in the jump\-buffer (plus one call to
+sigprocmask(2),
+in the case of sigsetjmp).
+On the
+other hand, executing a non\-local goto by calling one of the
+longjmp()
+routines tends to be much slower than with the
+system\-provided routines. In fact, the time spent on a
+longjmp()
+will be proportional to the number of call frames
+that exist between the points where setjmp()
+and
+longjmp()
+were called. For this reason, the
+unwind\-setjmp
+library is beneficial primarily in applications
+that frequently call setjmp()
+but only rarely call
+longjmp().
+.PP
+.SH CAVEATS
+
+.PP
+.TP
+.B *
+The correct operation of this library depends on the presence of
+correct unwind information. On newer platforms, this is rarely an
+issue. On older platforms, care needs to be taken to
+ensure that each of the functions whose stack frames may have to be
+unwound during a longjmp()
+have correct unwind information
+(on those platforms, there is usually a compiler\-switch, such as
+\fB\-funwind\-tables\fP,
+to request the generation of unwind
+information).
+.TP
+.B *
+The contents of jmp_buf and sigjmp_buf as setup
+and used by these routines is completely different from the ones
+used by the system\-provided routines. Thus, a jump\-buffer created
+by the libunwind\-based setjmp()/_setjmp
+may only be
+used in a call to the libunwind\-based
+longjmp()/_longjmp().
+The analogous applies for
+sigjmp_buf
+with sigsetjmp()
+and siglongjmp().
+.PP
+.SH FILES
+
+.PP
+.TP
+\fB\-l\fPunwind\-setjmp
+ The library an application should
+be linked against to ensure it uses the libunwind\-based non\-local
+goto routines.
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+setjmp(3), longjmp(3),
+_setjmp(3), _longjmp(3),
+sigsetjmp(3), siglongjmp(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/libunwind-setjmp.tex b/src/pal/src/libunwind/doc/libunwind-setjmp.tex
new file mode 100644
index 0000000000..17ce073186
--- /dev/null
+++ b/src/pal/src/libunwind/doc/libunwind-setjmp.tex
@@ -0,0 +1,87 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{libunwind-setjmp}{David Mosberger-Tang}{Programming Library}{libunwind-based non-local gotos}libunwind-setjmp -- libunwind-based non-local gotos
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$setjmp.h$>$}\\
+
+\noindent
+\Type{int} \Func{setjmp}(\Type{jmp\_buf}~\Var{env});\\
+\Type{void} \Func{longjmp}(\Type{jmp\_buf}~\Var{env}, \Type{int}~\Var{val});\\
+\Type{int} \Func{\_setjmp}(\Type{jmp\_buf}~\Var{env});\\
+\Type{void} \Func{\_longjmp}(\Type{jmp\_buf}~\Var{env}, \Type{int}~\Var{val});\\
+\Type{int} \Func{sigsetjmp}(\Type{sigjmp\_buf}~\Var{env}, \Type{int}~\Var{savemask});\\
+\Type{void} \Func{siglongjmp}(\Type{sigjmp\_buf}~\Var{env}, \Type{int}~\Var{val});\\
+
+\section{Description}
+
+The \Prog{unwind-setjmp} library offers a \Prog{libunwind}-based
+implementation of non-local gotos. This implementation is intended to
+be a drop-in replacement for the normal, system-provided routines of
+the same name. The main advantage of using the \Prog{unwind-setjmp}
+library is that setting up a non-local goto via one of the
+\Func{setjmp}() routines is very fast. Typically, just 2 or 3 words
+need to be saved in the jump-buffer (plus one call to
+\Func{sigprocmask}(2), in the case of \Func{sigsetjmp}). On the
+other hand, executing a non-local goto by calling one of the
+\Func{longjmp}() routines tends to be much slower than with the
+system-provided routines. In fact, the time spent on a
+\Func{longjmp}() will be proportional to the number of call frames
+that exist between the points where \Func{setjmp}() and
+\Func{longjmp}() were called. For this reason, the
+\Prog{unwind-setjmp} library is beneficial primarily in applications
+that frequently call \Func{setjmp}() but only rarely call
+\Func{longjmp}().
+
+\section{Caveats}
+
+\begin{itemize}
+\item The correct operation of this library depends on the presence of
+ correct unwind information. On newer platforms, this is rarely an
+ issue. On older platforms, care needs to be taken to
+ ensure that each of the functions whose stack frames may have to be
+ unwound during a \Func{longjmp}() have correct unwind information
+ (on those platforms, there is usually a compiler-switch, such as
+ \Opt{-funwind-tables}, to request the generation of unwind
+ information).
+\item The contents of \Type{jmp\_buf} and \Type{sigjmp\_buf} as setup
+ and used by these routines is completely different from the ones
+ used by the system-provided routines. Thus, a jump-buffer created
+ by the libunwind-based \Func{setjmp}()/\Func{\_setjmp} may only be
+ used in a call to the libunwind-based
+ \Func{longjmp}()/\Func{\_longjmp}(). The analogous applies for
+ \Type{sigjmp\_buf} with \Func{sigsetjmp}() and \Func{siglongjmp}().
+\end{itemize}
+
+\section{Files}
+
+\begin{Description}
+\item[\Opt{-l}\File{unwind-setjmp}] The library an application should
+ be linked against to ensure it uses the libunwind-based non-local
+ goto routines.
+\end{Description}
+
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+setjmp(3), longjmp(3),
+\_setjmp(3), \_longjmp(3),
+sigsetjmp(3), siglongjmp(3)
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/libunwind.man b/src/pal/src/libunwind/doc/libunwind.man
new file mode 100644
index 0000000000..02ab6b8937
--- /dev/null
+++ b/src/pal/src/libunwind/doc/libunwind.man
@@ -0,0 +1,508 @@
+'\" t
+.\" Manual page created with latex2man on Thu Jan 12 06:50:29 PST 2017
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "LIBUNWIND" "3" "12 January 2017" "Programming Library " "Programming Library "
+.SH NAME
+libunwind
+\-\- a (mostly) platform\-independent unwind API
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_getcontext(unw_context_t *);
+.br
+int
+unw_init_local(unw_cursor_t *,
+unw_context_t *);
+.br
+int
+unw_init_remote(unw_cursor_t *,
+unw_addr_space_t,
+void *);
+.br
+int
+unw_step(unw_cursor_t *);
+.br
+int
+unw_get_reg(unw_cursor_t *,
+unw_regnum_t,
+unw_word_t *);
+.br
+int
+unw_get_fpreg(unw_cursor_t *,
+unw_regnum_t,
+unw_fpreg_t *);
+.br
+int
+unw_set_reg(unw_cursor_t *,
+unw_regnum_t,
+unw_word_t);
+.br
+int
+unw_set_fpreg(unw_cursor_t *,
+unw_regnum_t,
+unw_fpreg_t);
+.br
+int
+unw_resume(unw_cursor_t *);
+.br
+.PP
+unw_addr_space_t
+unw_local_addr_space;
+.br
+unw_addr_space_t
+unw_create_addr_space(unw_accessors_t,
+int);
+.br
+void
+unw_destroy_addr_space(unw_addr_space_t);
+.br
+unw_accessors_t
+unw_get_accessors(unw_addr_space_t);
+.br
+void
+unw_flush_cache(unw_addr_space_t,
+unw_word_t,
+unw_word_t);
+.br
+int
+unw_set_caching_policy(unw_addr_space_t,
+unw_caching_policy_t);
+.br
+int
+unw_set_cache_size(unw_addr_space_t,
+size_t,
+int);
+.br
+.PP
+const char *unw_regname(unw_regnum_t);
+.br
+int
+unw_get_proc_info(unw_cursor_t *,
+unw_proc_info_t *);
+.br
+int
+unw_get_save_loc(unw_cursor_t *,
+int,
+unw_save_loc_t *);
+.br
+int
+unw_is_fpreg(unw_regnum_t);
+.br
+int
+unw_is_signal_frame(unw_cursor_t *);
+.br
+int
+unw_get_proc_name(unw_cursor_t *,
+char *,
+size_t,
+unw_word_t *);
+.br
+.PP
+void
+_U_dyn_register(unw_dyn_info_t *);
+.br
+void
+_U_dyn_cancel(unw_dyn_info_t *);
+.br
+.PP
+.SH LOCAL UNWINDING
+
+.PP
+Libunwind
+is very easy to use when unwinding a stack from
+within a running program. This is called \fIlocal\fP
+unwinding. Say
+you want to unwind the stack while executing in some function
+F().
+In this function, you would call unw_getcontext()
+to get a snapshot of the CPU registers (machine\-state). Then you
+initialize an \fIunwind cursor\fP
+based on this snapshot. This is
+done with a call to unw_init_local().
+The cursor now points
+to the current frame, that is, the stack frame that corresponds to the
+current activation of function F().
+The unwind cursor can then
+be moved ``up\&'' (towards earlier stack frames) by calling
+unw_step().
+By repeatedly calling this routine, you can
+uncover the entire call\-chain that led to the activation of function
+F().
+A positive return value from unw_step()
+indicates
+that there are more frames in the chain, zero indicates that the end
+of the chain has been reached, and any negative value indicates that
+some sort of error has occurred.
+.PP
+While it is not possible to directly move the unwind cursor in the
+``down\&'' direction (towards newer stack frames), this effect can be
+achieved by making copies of an unwind cursor. For example, a program
+that sometimes has to move ``down\&'' by one stack frame could maintain
+two cursor variables: ``curr\&''
+and ``prev\&''\&.
+The former
+would be used as the current cursor and prev
+would be maintained
+as the ``previous frame\&'' cursor by copying the contents of curr
+to prev
+right before calling unw_step().
+With this
+approach, the program could move one step ``down\&'' simply by copying
+back prev
+to curr
+whenever that is necessary. In the most
+extreme case, a program could maintain a separate cursor for each call
+frame and that way it could move up and down the callframe\-chain at
+will.
+.PP
+Given an unwind cursor, it is possible to read and write the CPU
+registers that were preserved for the current stack frame (as
+identified by the cursor). Libunwind
+provides several routines
+for this purpose: unw_get_reg()
+reads an integer (general)
+register, unw_get_fpreg()
+reads a floating\-point register,
+unw_set_reg()
+writes an integer register, and
+unw_set_fpreg()
+writes a floating\-point register. Note that,
+by definition, only the \fIpreserved\fP
+machine state can be accessed
+during an unwind operation. Normally, this state consists of the
+\fIcallee\-saved\fP
+(``preserved\&'') registers. However, in some
+special circumstances (e.g., in a signal handler trampoline), even the
+\fIcaller\-saved\fP
+(``scratch\&'') registers are preserved in the stack
+frame and, in those cases, libunwind
+will grant access to them
+as well. The exact set of registers that can be accessed via the
+cursor depends, of course, on the platform. However, there are two
+registers that can be read on all platforms: the instruction pointer
+(IP), sometimes also known as the ``program counter\&'', and the stack
+pointer (SP). In libunwind,
+these registers are identified by
+the macros UNW_REG_IP
+and UNW_REG_SP,
+respectively.
+.PP
+Besides just moving the unwind cursor and reading/writing saved
+registers, libunwind
+also provides the ability to resume
+execution at an arbitrary stack frame. As you might guess, this is
+useful for implementing non\-local gotos and the exception handling
+needed by some high\-level languages such as Java. Resuming execution
+with a particular stack frame simply requires calling
+unw_resume()
+and passing the cursor identifying the target
+frame as the only argument.
+.PP
+Normally, libunwind
+supports both local and remote unwinding
+(the latter will be explained in the next section). However, if you
+tell libunwind that your program only needs local unwinding, then a
+special implementation can be selected which may run much faster than
+the generic implementation which supports both kinds of unwinding. To
+select this optimized version, simply define the macro
+UNW_LOCAL_ONLY
+before including the headerfile
+<libunwind.h>\&.
+It is perfectly OK for a single program to
+employ both local\-only and generic unwinding. That is, whether or not
+UNW_LOCAL_ONLY
+is defined is a choice that each source\-file
+(compilation\-unit) can make on its own. Independent of the setting(s)
+of UNW_LOCAL_ONLY,
+you\&'ll always link the same library into
+the program (normally \fB\-l\fPunwind).
+Furthermore, the
+portion of libunwind
+that manages unwind\-info for dynamically
+generated code is not affected by the setting of
+UNW_LOCAL_ONLY\&.
+.PP
+If we put all of the above together, here is how we could use
+libunwind
+to write a function ``show_backtrace()\&''
+which prints a classic stack trace:
+.PP
+.Vb
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+
+void show_backtrace (void) {
+ unw_cursor_t cursor; unw_context_t uc;
+ unw_word_t ip, sp;
+
+ unw_getcontext(&uc);
+ unw_init_local(&cursor, &uc);
+ while (unw_step(&cursor) > 0) {
+ unw_get_reg(&cursor, UNW_REG_IP, &ip);
+ unw_get_reg(&cursor, UNW_REG_SP, &sp);
+ printf ("ip = %lx, sp = %lx\\n", (long) ip, (long) sp);
+ }
+}
+.Ve
+.PP
+.SH REMOTE UNWINDING
+
+.PP
+Libunwind
+can also be used to unwind a stack in a ``remote\&''
+process. Here, ``remote\&'' may mean another process on the same
+machine or even a process on a completely different machine from the
+one that is running libunwind\&.
+Remote unwinding is typically
+used by debuggers and instruction\-set simulators, for example.
+.PP
+Before you can unwind a remote process, you need to create a new
+address\-space object for that process. This is achieved with the
+unw_create_addr_space()
+routine. The routine takes two
+arguments: a pointer to a set of \fIaccessor\fP
+routines and an
+integer that specifies the byte\-order of the target process. The
+accessor routines provide libunwind
+with the means to
+communicate with the remote process. In particular, there are
+callbacks to read and write the process\&'s memory, its registers, and
+to access unwind information which may be needed by libunwind\&.
+.PP
+With the address space created, unwinding can be initiated by a call
+to unw_init_remote().
+This routine is very similar to
+unw_init_local(),
+except that it takes an address\-space
+object and an opaque pointer as arguments. The routine uses these
+arguments to fetch the initial machine state. Libunwind
+never
+uses the opaque pointer on its own, but instead just passes it on to
+the accessor (callback) routines. Typically, this pointer is used to
+select, e.g., the thread within a process that is to be unwound.
+.PP
+Once a cursor has been initialized with unw_init_remote(),
+unwinding works exactly like in the local case. That is, you can use
+unw_step()
+to move ``up\&'' in the call\-chain, read and write
+registers, or resume execution at a particular stack frame by calling
+unw_resume\&.
+.PP
+.SH CROSS\-PLATFORM AND MULTI\-PLATFORM UNWINDING
+
+.PP
+Libunwind
+has been designed to enable unwinding across
+platforms (architectures). Indeed, a single program can use
+libunwind
+to unwind an arbitrary number of target platforms,
+all at the same time!
+.PP
+We call the machine that is running libunwind
+the \fIhost\fP
+and the machine that is running the process being unwound the
+\fItarget\fP\&.
+If the host and the target platform are the same, we
+call it \fInative\fP
+unwinding. If they differ, we call it
+\fIcross\-platform\fP
+unwinding.
+.PP
+The principle behind supporting native, cross\-platform, and
+multi\-platform unwinding is very simple: for native unwinding, a
+program includes <libunwind.h>
+and uses the linker switch
+\fB\-l\fPunwind\&.
+For cross\-platform unwinding, a program
+includes <libunwind\-PLAT\&.h>
+and uses the linker
+switch \fB\-l\fPunwind\-PLAT,
+where PLAT
+is the name
+of the target platform (e.g., ia64
+for IA\-64, hppa\-elf
+for ELF\-based HP PA\-RISC, or x86
+for 80386). Multi\-platform
+unwinding works exactly like cross\-platform unwinding, the only
+limitation is that a single source file (compilation unit) can include
+at most one libunwind
+header file. In other words, the
+platform\-specific support for each supported target needs to be
+isolated in separate source files\-\-\-a limitation that shouldn\&'t be an
+issue in practice.
+.PP
+Note that, by definition, local unwinding is possible only for the
+native case. Attempting to call, e.g., unw_local_init()
+when
+targeting a cross\-platform will result in a link\-time error
+(unresolved references).
+.PP
+.SH THREAD\- AND SIGNAL\-SAFETY
+
+.PP
+All libunwind
+routines are thread\-safe. What this means is
+that multiple threads may use libunwind
+simulatenously.
+However, any given cursor may be accessed by only one thread at
+any given time.
+.PP
+To ensure thread\-safety, some libunwind
+routines may have to
+use locking. Such routines \fImust not\fP
+be called from signal
+handlers (directly or indirectly) and are therefore \fInot\fP
+signal\-safe. The manual page for each libunwind
+routine
+identifies whether or not it is signal\-safe, but as a general rule,
+any routine that may be needed for \fIlocal\fP
+unwinding is
+signal\-safe (e.g., unw_step()
+for local unwinding is
+signal\-safe). For remote\-unwinding, \fInone\fP
+of the
+libunwind
+routines are guaranteed to be signal\-safe.
+.PP
+.SH UNWINDING THROUGH DYNAMICALLY GENERATED CODE
+
+.PP
+Libunwind
+provides the routines _U_dyn_register()
+and
+_U_dyn_cancel()
+to register/cancel the information required to
+unwind through code that has been generated at runtime (e.g., by a
+just\-in\-time (JIT) compiler). It is important to register the
+information for \fIall\fP
+dynamically generated code because
+otherwise, a debugger may not be able to function properly or
+high\-level language exception handling may not work as expected.
+.PP
+The interface for registering and canceling dynamic unwind info has
+been designed for maximum efficiency, so as to minimize the
+performance impact on JIT\-compilers. In particular, both routines are
+guaranteed to execute in ``constant time\&'' (O(1)) and the
+data\-structure encapsulating the dynamic unwind info has been designed
+to facilitate sharing, such that similar procedures can share much of
+the underlying information.
+.PP
+For more information on the libunwind
+support for dynamically
+generated code, see libunwind\-dynamic(3)\&.
+.PP
+.SH CACHING OF UNWIND INFO
+
+.PP
+To speed up execution, libunwind
+may aggressively cache the
+information it needs to perform unwinding. If a process changes
+during its lifetime, this creates a risk of libunwind
+using
+stale data. For example, this would happen if libunwind
+were
+to cache information about a shared library which later on gets
+unloaded (e.g., via \fIdlclose\fP(3)).
+.PP
+To prevent the risk of using stale data, libunwind
+provides two
+facilities: first, it is possible to flush the cached information
+associated with a specific address range in the target process (or the
+entire address space, if desired). This functionality is provided by
+unw_flush_cache().
+The second facility is provided by
+unw_set_caching_policy(),
+which lets a program
+select the exact caching policy in use for a given address\-space
+object. In particular, by selecting the policy
+UNW_CACHE_NONE,
+it is possible to turn off caching
+completely, therefore eliminating the risk of stale data alltogether
+(at the cost of slower execution). By default, caching is enabled for
+local unwinding only. The cache size can be dynamically changed with
+unw_set_cache_size(),
+which also fluches the current cache.
+.PP
+.SH FILES
+
+.PP
+.TP
+libunwind.h
+ Headerfile to include for native (same
+platform) unwinding.
+.TP
+libunwind\-PLAT\&.h
+ Headerfile to include when
+the unwind target runs on platform PLAT\&.
+For example, to unwind
+an IA\-64 program, the header file libunwind\-ia64.h
+should be
+included.
+.TP
+\fB\-l\fPunwind
+ Linker\-switch to add when building a
+program that does native (same platform) unwinding.
+.TP
+\fB\-l\fPunwind\-PLAT
+ Linker\-switch to add when
+building a program that unwinds a program on platform PLAT\&.
+For example, to (cross\-)unwind an IA\-64 program, the linker switch
+\-lunwind\-ia64
+should be added. Note: multiple such switches
+may need to be specified for programs that can unwind programs on
+multiple platforms.
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind\-dynamic(3),
+libunwind\-ia64(3),
+libunwind\-ptrace(3),
+libunwind\-setjmp(3),
+unw_create_addr_space(3),
+unw_destroy_addr_space(3),
+unw_flush_cache(3),
+unw_get_accessors(3),
+unw_get_fpreg(3),
+unw_get_proc_info(3),
+unw_get_proc_name(3),
+unw_get_reg(3),
+unw_getcontext(3),
+unw_init_local(3),
+unw_init_remote(3),
+unw_is_fpreg(3),
+unw_is_signal_frame(3),
+unw_regname(3),
+unw_resume(3),
+unw_set_caching_policy(3),
+unw_set_cache_size(3),
+unw_set_fpreg(3),
+unw_set_reg(3),
+unw_step(3),
+unw_strerror(3),
+_U_dyn_register(3),
+_U_dyn_cancel(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/libunwind.tex b/src/pal/src/libunwind/doc/libunwind.tex
new file mode 100644
index 0000000000..6cbb476633
--- /dev/null
+++ b/src/pal/src/libunwind/doc/libunwind.tex
@@ -0,0 +1,359 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{libunwind}{David Mosberger-Tang}{Programming Library}{Introduction to libunwind}libunwind -- a (mostly) platform-independent unwind API
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\noindent
+\Type{int} \Func{unw\_getcontext}(\Type{unw\_context\_t~*});\\
+\noindent
+\Type{int} \Func{unw\_init\_local}(\Type{unw\_cursor\_t~*}, \Type{unw\_context\_t~*});\\
+\noindent
+\Type{int} \Func{unw\_init\_remote}(\Type{unw\_cursor\_t~*}, \Type{unw\_addr\_space\_t}, \Type{void~*});\\
+\noindent
+\Type{int} \Func{unw\_step}(\Type{unw\_cursor\_t~*});\\
+\noindent
+\Type{int} \Func{unw\_get\_reg}(\Type{unw\_cursor\_t~*}, \Type{unw\_regnum\_t}, \Type{unw\_word\_t~*});\\
+\noindent
+\Type{int} \Func{unw\_get\_fpreg}(\Type{unw\_cursor\_t~*}, \Type{unw\_regnum\_t}, \Type{unw\_fpreg\_t~*});\\
+\noindent
+\Type{int} \Func{unw\_set\_reg}(\Type{unw\_cursor\_t~*}, \Type{unw\_regnum\_t}, \Type{unw\_word\_t});\\
+\noindent
+\Type{int} \Func{unw\_set\_fpreg}(\Type{unw\_cursor\_t~*}, \Type{unw\_regnum\_t}, \Type{unw\_fpreg\_t});\\
+\noindent
+\Type{int} \Func{unw\_resume}(\Type{unw\_cursor\_t~*});\\
+
+\noindent
+\Type{unw\_addr\_space\_t} \Var{unw\_local\_addr\_space};\\
+\noindent
+\Type{unw\_addr\_space\_t} \Func{unw\_create\_addr\_space}(\Type{unw\_accessors\_t}, \Type{int});\\
+\noindent
+\Type{void} \Func{unw\_destroy\_addr\_space}(\Type{unw\_addr\_space\_t});\\
+\noindent
+\Type{unw\_accessors\_t} \Func{unw\_get\_accessors}(\Type{unw\_addr\_space\_t});\\
+\noindent
+\Type{void} \Func{unw\_flush\_cache}(\Type{unw\_addr\_space\_t}, \Type{unw\_word\_t}, \Type{unw\_word\_t});\\
+\noindent
+\Type{int} \Func{unw\_set\_caching\_policy}(\Type{unw\_addr\_space\_t}, \Type{unw\_caching\_policy\_t});\\
+\noindent
+\Type{int} \Func{unw\_set\_cache\_size}(\Type{unw\_addr\_space\_t}, \Type{size\_t}, \Type{int});\\
+
+\noindent
+\Type{const char *}\Func{unw\_regname}(\Type{unw\_regnum\_t});\\
+\noindent
+\Type{int} \Func{unw\_get\_proc\_info}(\Type{unw\_cursor\_t~*}, \Type{unw\_proc\_info\_t~*});\\
+\noindent
+\Type{int} \Func{unw\_get\_save\_loc}(\Type{unw\_cursor\_t~*}, \Type{int}, \Type{unw\_save\_loc\_t~*});\\
+\noindent
+\Type{int} \Func{unw\_is\_fpreg}(\Type{unw\_regnum\_t});\\
+\Type{int} \Func{unw\_is\_signal\_frame}(\Type{unw\_cursor\_t~*});\\
+\noindent
+\Type{int} \Func{unw\_get\_proc\_name}(\Type{unw\_cursor\_t~*}, \Type{char~*}, \Type{size\_t}, \Type{unw\_word\_t~*});\\
+
+\noindent
+\Type{void} \Func{\_U\_dyn\_register}(\Type{unw\_dyn\_info\_t~*});\\
+\noindent
+\Type{void} \Func{\_U\_dyn\_cancel}(\Type{unw\_dyn\_info\_t~*});\\
+
+\section{Local Unwinding}
+
+\Prog{Libunwind} is very easy to use when unwinding a stack from
+within a running program. This is called \emph{local} unwinding. Say
+you want to unwind the stack while executing in some function
+\Func{F}(). In this function, you would call \Func{unw\_getcontext}()
+to get a snapshot of the CPU registers (machine-state). Then you
+initialize an \emph{unwind~cursor} based on this snapshot. This is
+done with a call to \Func{unw\_init\_local}(). The cursor now points
+to the current frame, that is, the stack frame that corresponds to the
+current activation of function \Func{F}(). The unwind cursor can then
+be moved ``up'' (towards earlier stack frames) by calling
+\Func{unw\_step}(). By repeatedly calling this routine, you can
+uncover the entire call-chain that led to the activation of function
+\Func{F}(). A positive return value from \Func{unw\_step}() indicates
+that there are more frames in the chain, zero indicates that the end
+of the chain has been reached, and any negative value indicates that
+some sort of error has occurred.
+
+While it is not possible to directly move the unwind cursor in the
+``down'' direction (towards newer stack frames), this effect can be
+achieved by making copies of an unwind cursor. For example, a program
+that sometimes has to move ``down'' by one stack frame could maintain
+two cursor variables: ``\Var{curr}'' and ``\Var{prev}''. The former
+would be used as the current cursor and \Var{prev} would be maintained
+as the ``previous frame'' cursor by copying the contents of \Var{curr}
+to \Var{prev} right before calling \Func{unw\_step}(). With this
+approach, the program could move one step ``down'' simply by copying
+back \Var{prev} to \Var{curr} whenever that is necessary. In the most
+extreme case, a program could maintain a separate cursor for each call
+frame and that way it could move up and down the callframe-chain at
+will.
+
+Given an unwind cursor, it is possible to read and write the CPU
+registers that were preserved for the current stack frame (as
+identified by the cursor). \Prog{Libunwind} provides several routines
+for this purpose: \Func{unw\_get\_reg}() reads an integer (general)
+register, \Func{unw\_get\_fpreg}() reads a floating-point register,
+\Func{unw\_set\_reg}() writes an integer register, and
+\Func{unw\_set\_fpreg}() writes a floating-point register. Note that,
+by definition, only the \emph{preserved} machine state can be accessed
+during an unwind operation. Normally, this state consists of the
+\emph{callee-saved} (``preserved'') registers. However, in some
+special circumstances (e.g., in a signal handler trampoline), even the
+\emph{caller-saved} (``scratch'') registers are preserved in the stack
+frame and, in those cases, \Prog{libunwind} will grant access to them
+as well. The exact set of registers that can be accessed via the
+cursor depends, of course, on the platform. However, there are two
+registers that can be read on all platforms: the instruction pointer
+(IP), sometimes also known as the ``program counter'', and the stack
+pointer (SP). In \Prog{libunwind}, these registers are identified by
+the macros \Const{UNW\_REG\_IP} and \Const{UNW\_REG\_SP},
+respectively.
+
+Besides just moving the unwind cursor and reading/writing saved
+registers, \Prog{libunwind} also provides the ability to resume
+execution at an arbitrary stack frame. As you might guess, this is
+useful for implementing non-local gotos and the exception handling
+needed by some high-level languages such as Java. Resuming execution
+with a particular stack frame simply requires calling
+\Func{unw\_resume}() and passing the cursor identifying the target
+frame as the only argument.
+
+Normally, \Prog{libunwind} supports both local and remote unwinding
+(the latter will be explained in the next section). However, if you
+tell libunwind that your program only needs local unwinding, then a
+special implementation can be selected which may run much faster than
+the generic implementation which supports both kinds of unwinding. To
+select this optimized version, simply define the macro
+\Const{UNW\_LOCAL\_ONLY} before including the headerfile
+\File{$<$libunwind.h$>$}. It is perfectly OK for a single program to
+employ both local-only and generic unwinding. That is, whether or not
+\Const{UNW\_LOCAL\_ONLY} is defined is a choice that each source-file
+(compilation-unit) can make on its own. Independent of the setting(s)
+of \Const{UNW\_LOCAL\_ONLY}, you'll always link the same library into
+the program (normally \Opt{-l}\File{unwind}). Furthermore, the
+portion of \Prog{libunwind} that manages unwind-info for dynamically
+generated code is not affected by the setting of
+\Const{UNW\_LOCAL\_ONLY}.
+
+If we put all of the above together, here is how we could use
+\Prog{libunwind} to write a function ``\Func{show\_backtrace}()''
+which prints a classic stack trace:
+
+\begin{verbatim}
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+
+void show_backtrace (void) {
+ unw_cursor_t cursor; unw_context_t uc;
+ unw_word_t ip, sp;
+
+ unw_getcontext(&uc);
+ unw_init_local(&cursor, &uc);
+ while (unw_step(&cursor) > 0) {
+ unw_get_reg(&cursor, UNW_REG_IP, &ip);
+ unw_get_reg(&cursor, UNW_REG_SP, &sp);
+ printf ("ip = %lx, sp = %lx\n", (long) ip, (long) sp);
+ }
+}
+\end{verbatim}
+
+
+\section{Remote Unwinding}
+
+\Prog{Libunwind} can also be used to unwind a stack in a ``remote''
+process. Here, ``remote'' may mean another process on the same
+machine or even a process on a completely different machine from the
+one that is running \Prog{libunwind}. Remote unwinding is typically
+used by debuggers and instruction-set simulators, for example.
+
+Before you can unwind a remote process, you need to create a new
+address-space object for that process. This is achieved with the
+\Func{unw\_create\_addr\_space}() routine. The routine takes two
+arguments: a pointer to a set of \emph{accessor} routines and an
+integer that specifies the byte-order of the target process. The
+accessor routines provide \Func{libunwind} with the means to
+communicate with the remote process. In particular, there are
+callbacks to read and write the process's memory, its registers, and
+to access unwind information which may be needed by \Func{libunwind}.
+
+With the address space created, unwinding can be initiated by a call
+to \Func{unw\_init\_remote}(). This routine is very similar to
+\Func{unw\_init\_local}(), except that it takes an address-space
+object and an opaque pointer as arguments. The routine uses these
+arguments to fetch the initial machine state. \Prog{Libunwind} never
+uses the opaque pointer on its own, but instead just passes it on to
+the accessor (callback) routines. Typically, this pointer is used to
+select, e.g., the thread within a process that is to be unwound.
+
+Once a cursor has been initialized with \Func{unw\_init\_remote}(),
+unwinding works exactly like in the local case. That is, you can use
+\Func{unw\_step}() to move ``up'' in the call-chain, read and write
+registers, or resume execution at a particular stack frame by calling
+\Func{unw\_resume}.
+
+
+\section{Cross-platform and Multi-platform Unwinding}
+
+\Prog{Libunwind} has been designed to enable unwinding across
+platforms (architectures). Indeed, a single program can use
+\Prog{libunwind} to unwind an arbitrary number of target platforms,
+all at the same time!
+
+We call the machine that is running \Prog{libunwind} the \emph{host}
+and the machine that is running the process being unwound the
+\emph{target}. If the host and the target platform are the same, we
+call it \emph{native} unwinding. If they differ, we call it
+\emph{cross-platform} unwinding.
+
+The principle behind supporting native, cross-platform, and
+multi-platform unwinding is very simple: for native unwinding, a
+program includes \File{$<$libunwind.h$>$} and uses the linker switch
+\Opt{-l}\File{unwind}. For cross-platform unwinding, a program
+includes \File{$<$libunwind-}\Var{PLAT}\File{.h$>$} and uses the linker
+switch \Opt{-l}\File{unwind-}\Var{PLAT}, where \Var{PLAT} is the name
+of the target platform (e.g., \File{ia64} for IA-64, \File{hppa-elf}
+for ELF-based HP PA-RISC, or \File{x86} for 80386). Multi-platform
+unwinding works exactly like cross-platform unwinding, the only
+limitation is that a single source file (compilation unit) can include
+at most one \Prog{libunwind} header file. In other words, the
+platform-specific support for each supported target needs to be
+isolated in separate source files---a limitation that shouldn't be an
+issue in practice.
+
+Note that, by definition, local unwinding is possible only for the
+native case. Attempting to call, e.g., \Func{unw\_local\_init}() when
+targeting a cross-platform will result in a link-time error
+(unresolved references).
+
+
+\section{Thread- and Signal-Safety}
+
+
+All \Prog{libunwind} routines are thread-safe. What this means is
+that multiple threads may use \Prog{libunwind} simulatenously.
+However, any given cursor may be accessed by only one thread at
+any given time.
+
+To ensure thread-safety, some \Prog{libunwind} routines may have to
+use locking. Such routines \emph{must~not} be called from signal
+handlers (directly or indirectly) and are therefore \emph{not}
+signal-safe. The manual page for each \Prog{libunwind} routine
+identifies whether or not it is signal-safe, but as a general rule,
+any routine that may be needed for \emph{local} unwinding is
+signal-safe (e.g., \Func{unw\_step}() for local unwinding is
+signal-safe). For remote-unwinding, \emph{none} of the
+\Prog{libunwind} routines are guaranteed to be signal-safe.
+
+
+\section{Unwinding Through Dynamically Generated Code}
+
+\Func{Libunwind} provides the routines \Func{\_U\_dyn\_register}() and
+\Func{\_U\_dyn\_cancel}() to register/cancel the information required to
+unwind through code that has been generated at runtime (e.g., by a
+just-in-time (JIT) compiler). It is important to register the
+information for \emph{all} dynamically generated code because
+otherwise, a debugger may not be able to function properly or
+high-level language exception handling may not work as expected.
+
+The interface for registering and canceling dynamic unwind info has
+been designed for maximum efficiency, so as to minimize the
+performance impact on JIT-compilers. In particular, both routines are
+guaranteed to execute in ``constant time'' (O(1)) and the
+data-structure encapsulating the dynamic unwind info has been designed
+to facilitate sharing, such that similar procedures can share much of
+the underlying information.
+
+For more information on the \Prog{libunwind} support for dynamically
+generated code, see \SeeAlso{libunwind-dynamic(3)}.
+
+
+\section{Caching of Unwind Info}
+
+To speed up execution, \Prog{libunwind} may aggressively cache the
+information it needs to perform unwinding. If a process changes
+during its lifetime, this creates a risk of \Prog{libunwind} using
+stale data. For example, this would happen if \Prog{libunwind} were
+to cache information about a shared library which later on gets
+unloaded (e.g., via \Cmd{dlclose}{3}).
+
+To prevent the risk of using stale data, \Prog{libunwind} provides two
+facilities: first, it is possible to flush the cached information
+associated with a specific address range in the target process (or the
+entire address space, if desired). This functionality is provided by
+\Func{unw\_flush\_cache}(). The second facility is provided by
+\Func{unw\_set\_caching\_policy}(), which lets a program
+select the exact caching policy in use for a given address-space
+object. In particular, by selecting the policy
+\Const{UNW\_CACHE\_NONE}, it is possible to turn off caching
+completely, therefore eliminating the risk of stale data alltogether
+(at the cost of slower execution). By default, caching is enabled for
+local unwinding only. The cache size can be dynamically changed with
+\Func{unw\_set\_cache\_size}(), which also fluches the current cache.
+
+
+\section{Files}
+
+\begin{Description}
+\item[\File{libunwind.h}] Headerfile to include for native (same
+ platform) unwinding.
+\item[\File{libunwind-}\Var{PLAT}\File{.h}] Headerfile to include when
+ the unwind target runs on platform \Var{PLAT}. For example, to unwind
+ an IA-64 program, the header file \File{libunwind-ia64.h} should be
+ included.
+\item[\Opt{-l}\File{unwind}] Linker-switch to add when building a
+ program that does native (same platform) unwinding.
+\item[\Opt{-l}\File{unwind-}\Var{PLAT}] Linker-switch to add when
+ building a program that unwinds a program on platform \Var{PLAT}.
+ For example, to (cross-)unwind an IA-64 program, the linker switch
+ \File{-lunwind-ia64} should be added. Note: multiple such switches
+ may need to be specified for programs that can unwind programs on
+ multiple platforms.
+\end{Description}
+
+\section{See Also}
+
+\SeeAlso{libunwind-dynamic(3)},
+\SeeAlso{libunwind-ia64(3)},
+\SeeAlso{libunwind-ptrace(3)},
+\SeeAlso{libunwind-setjmp(3)},
+\SeeAlso{unw\_create\_addr\_space(3)},
+\SeeAlso{unw\_destroy\_addr\_space(3)},
+\SeeAlso{unw\_flush\_cache(3)},
+\SeeAlso{unw\_get\_accessors(3)},
+\SeeAlso{unw\_get\_fpreg(3)},
+\SeeAlso{unw\_get\_proc\_info(3)},
+\SeeAlso{unw\_get\_proc\_name(3)},
+\SeeAlso{unw\_get\_reg(3)},
+\SeeAlso{unw\_getcontext(3)},
+\SeeAlso{unw\_init\_local(3)},
+\SeeAlso{unw\_init\_remote(3)},
+\SeeAlso{unw\_is\_fpreg(3)},
+\SeeAlso{unw\_is\_signal\_frame(3)},
+\SeeAlso{unw\_regname(3)},
+\SeeAlso{unw\_resume(3)},
+\SeeAlso{unw\_set\_caching\_policy(3)},
+\SeeAlso{unw\_set\_cache\_size(3)},
+\SeeAlso{unw\_set\_fpreg(3)},
+\SeeAlso{unw\_set\_reg(3)},
+\SeeAlso{unw\_step(3)},
+\SeeAlso{unw\_strerror(3)},
+\SeeAlso{\_U\_dyn\_register(3)},
+\SeeAlso{\_U\_dyn\_cancel(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/libunwind.trans b/src/pal/src/libunwind/doc/libunwind.trans
new file mode 100644
index 0000000000..a514e5a081
--- /dev/null
+++ b/src/pal/src/libunwind/doc/libunwind.trans
@@ -0,0 +1,34 @@
+$manMacro1a{'Type'} = $manMacro1a{File};
+ $manMacro1b{'Type'} = $manMacro1b{File};
+$htmlMacro1a{'Type'} = $htmlMacro1a{File};
+ $htmlMacro1b{'Type'} = $htmlMacro1b{File};
+$texiMacro1a{'Type'} = $texiMacro1a{File};
+ $texiMacro1b{'Type'} = $texiMacro1b{File};
+$manMacro1a{'Func'} = $manMacro1a{Prog};
+ $manMacro1b{'Func'} = $manMacro1b{Prog};
+$htmlMacro1a{'Func'} = $htmlMacro1a{Arg};
+ $htmlMacro1b{'Func'} = $htmlMacro1b{Arg};
+$texiMacro1a{'Func'} = $texiMacro1a{Prog};
+ $texiMacro1b{'Func'} = $texiMacro1b{Prog};
+$manMacro1a{'Var'} = $manMacro1a{Prog};
+ $manMacro1b{'Var'} = $manMacro1b{Prog};
+$htmlMacro1a{'Var'} = $htmlMacro1a{Prog};
+ $htmlMacro1b{'Var'} = $htmlMacro1b{Prog};
+$texiMacro1a{'Var'} = $texiMacro1a{Prog};
+ $texiMacro1b{'Var'} = $texiMacro1b{Prog};
+$manMacro1a{'Const'} = $manMacro1a{File};
+ $manMacro1b{'Const'} = $manMacro1b{File};
+$htmlMacro1a{'Const'} = $htmlMacro1a{File};
+ $htmlMacro1b{'Const'} = $htmlMacro1b{File};
+$texiMacro1a{'Const'} = $texiMacro1a{File};
+ $texiMacro1b{'Const'} = $texiMacro1b{File};
+
+$manMacro1a{'SeeAlso'} = $manMacro1a{File};
+ $manMacro1b{'SeeAlso'} = $manMacro1b{File};
+# special handling of SeeAlso in latex2man, so that argument gets doubled:
+$htmlMacro2a{'SeeAlso'} = "<a href=\"";
+ $htmlMacro2b{'SeeAlso'} = ".html\">$htmlMacro1a{File}";
+ $htmlMacro2c{'SeeAlso'} = "$htmlMacro1b{File}</a>";
+$texiMacro1a{'SeeAlso'} = $texiMacro1a{File};
+ $texiMacro1b{'SeeAlso'} = $texiMacro1b{File};
+
diff --git a/src/pal/src/libunwind/doc/unw_apply_reg_state.man b/src/pal/src/libunwind/doc/unw_apply_reg_state.man
new file mode 100644
index 0000000000..457f0c4dd1
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_apply_reg_state.man
@@ -0,0 +1,90 @@
+'\" t
+.\" Manual page created with latex2man on Wed Aug 16 11:09:44 PDT 2017
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_APPLY\\_REG\\_STATE" "3" "16 August 2017" "Programming Library " "Programming Library "
+.SH NAME
+unw_apply_reg_state
+\-\- apply a register state update to a cursor
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_apply_reg_state(unw_cursor_t *cp,
+void *reg_states_data);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_apply_reg_state()
+routine updates the register values
+of a cursor according to the instructions in reg_states_data,
+which have been obtained by calling unw_reg_states_iterate\&.
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_apply_reg_state()
+returns 0.
+Otherwise the negative value of one of the error\-codes below is
+returned.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_apply_reg_state()
+is thread\-safe. If cursor cp
+is
+in the local address\-space, this routine is also safe to use from a
+signal handler.
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_EUNSPEC
+ An unspecified error occurred.
+.TP
+UNW_ENOINFO
+ Libunwind
+was unable to locate
+unwind\-info for the procedure.
+.TP
+UNW_EBADVERSION
+ The unwind\-info for the procedure has
+version or format that is not understood by libunwind\&.
+.PP
+In addition, unw_apply_reg_state()
+may return any error
+returned by the access_mem()
+call\-back (see
+unw_create_addr_space(3)).
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_reg_states_iterate(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_apply_reg_state.tex b/src/pal/src/libunwind/doc/unw_apply_reg_state.tex
new file mode 100644
index 0000000000..c67cc3ebfa
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_apply_reg_state.tex
@@ -0,0 +1,63 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_apply\_reg\_state}{David Mosberger-Tang}{Programming Library}{unw\_apply\_reg\_state}unw\_apply\_reg\_state -- apply a register state update to a cursor
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int}
+\Func{unw\_apply\_reg\_state}(\Type{unw\_cursor\_t~*}\Var{cp},
+\Type{void~*}\Var{reg\_states\_data});\\
+
+\section{Description}
+
+The \Func{unw\_apply\_reg\_state}() routine updates the register values
+of a cursor according to the instructions in \Var{reg\_states\_data},
+which have been obtained by calling \Var{unw\_reg\_states\_iterate}.
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_apply\_reg\_state}() returns 0.
+Otherwise the negative value of one of the error-codes below is
+returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_apply\_reg\_state}() is thread-safe. If cursor \Var{cp} is
+in the local address-space, this routine is also safe to use from a
+signal handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred.
+\item[\Const{UNW\_ENOINFO}] \Prog{Libunwind} was unable to locate
+ unwind-info for the procedure.
+\item[\Const{UNW\_EBADVERSION}] The unwind-info for the procedure has
+ version or format that is not understood by \Prog{libunwind}.
+\end{Description}
+In addition, \Func{unw\_apply\_reg\_state}() may return any error
+returned by the \Func{access\_mem}() call-back (see
+\Func{unw\_create\_addr\_space}(3)).
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_reg\_states\_iterate(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_backtrace.man b/src/pal/src/libunwind/doc/unw_backtrace.man
new file mode 100644
index 0000000000..5699bbfe28
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_backtrace.man
@@ -0,0 +1,86 @@
+'\" t
+.\" Manual page created with latex2man on Fri Aug 31 13:39:04 EEST 2012
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_BACKTRACE" "3" "31 August 2012" "Programming Library " "Programming Library "
+.SH NAME
+unw_backtrace
+\-\- return backtrace for the calling program
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_backtrace(void **buffer,
+int size);
+.br
+.PP
+#include <execinfo.h>
+.br
+.PP
+int
+backtrace(void **buffer,
+int size);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+unw_backtrace()
+is a convenient routine for obtaining the backtrace for
+the calling program. The routine fills up to size
+addresses in the array
+pointed by buffer\&.
+The routine is only available for local unwinding.
+.PP
+Note that many (but not all) systems provide practically identical function
+called backtrace().
+The prototype for this function is usually obtained
+by including the <execinfo.h>
+header file \-\- a prototype for
+backtrace()
+is not provided by libunwind\&.
+libunwind
+weakly
+aliases backtrace()
+to unw_backtrace(),
+so when a program
+calling backtrace()
+is linked against libunwind,
+it may end up
+calling unw_backtrace().
+.PP
+.SH RETURN VALUE
+
+.PP
+The routine returns the number of addresses stored in the array pointed by
+buffer\&.
+The return value may be zero to indicate that no addresses were
+stored.
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_step(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_backtrace.tex b/src/pal/src/libunwind/doc/unw_backtrace.tex
new file mode 100644
index 0000000000..c383eeb37a
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_backtrace.tex
@@ -0,0 +1,54 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_backtrace}{David Mosberger-Tang}{Programming Library}{unw\_backtrace}unw\_backtrace -- return backtrace for the calling program
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_backtrace}(\Type{void~**}\Var{buffer}, \Type{int}~\Var{size});\\
+
+\File{\#include $<$execinfo.h$>$}\\
+
+\Type{int} \Func{backtrace}(\Type{void~**}\Var{buffer}, \Type{int}~\Var{size});\\
+
+\section{Description}
+
+\Func{unw\_backtrace}() is a convenient routine for obtaining the backtrace for
+the calling program. The routine fills up to \Var{size} addresses in the array
+pointed by \Var{buffer}. The routine is only available for local unwinding.
+
+Note that many (but not all) systems provide practically identical function
+called \Func{backtrace}(). The prototype for this function is usually obtained
+by including the \File{$<$execinfo.h$>$} header file -- a prototype for
+\Func{backtrace}() is not provided by \Prog{libunwind}. \Prog{libunwind} weakly
+aliases \Func{backtrace}() to \Func{unw\_backtrace}(), so when a program
+calling \Func{backtrace}() is linked against \Prog{libunwind}, it may end up
+calling \Func{unw\_backtrace}().
+
+\section{Return Value}
+
+The routine returns the number of addresses stored in the array pointed by
+\Var{buffer}. The return value may be zero to indicate that no addresses were
+stored.
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_step(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_create_addr_space.man b/src/pal/src/libunwind/doc/unw_create_addr_space.man
new file mode 100644
index 0000000000..4aca13ecd8
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_create_addr_space.man
@@ -0,0 +1,457 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_CREATE\\_ADDR\\_SPACE" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+unw_create_addr_space
+\-\- create address space for remote unwinding
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+unw_addr_space_t
+unw_create_addr_space(unw_accessors_t *ap,
+int
+byteorder);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_create_addr_space()
+routine creates a new unwind
+address\-space and initializes it based on the call\-back routines
+passed via the ap
+pointer and the specified byteorder\&.
+The call\-back routines are described in detail below. The
+byteorder
+can be set to 0 to request the default byte\-order of
+the unwind target. To request a particular byte\-order,
+byteorder
+can be set to any constant defined by
+<endian.h>\&.
+In particular, __LITTLE_ENDIAN
+would
+request little\-endian byte\-order and __BIG_ENDIAN
+would
+request big\-endian byte\-order. Whether or not a particular byte\-order
+is supported depends on the target platform.
+.PP
+.SH CALL\-BACK ROUTINES
+
+.PP
+Libunwind
+uses a set of call\-back routines to access the
+information it needs to unwind a chain of stack\-frames. These
+routines are specified via the ap
+argument, which points to a
+variable of type unw_accessors_t\&.
+The contents of this
+variable is copied into the newly\-created address space, so the
+variable must remain valid only for the duration of the call to
+unw_create_addr_space().
+.PP
+The first argument to every call\-back routine is an address\-space
+identifier (as)
+and the last argument is an arbitrary,
+application\-specified void\-pointer (arg).
+When invoking a
+call\-back routine, libunwind
+sets the as
+argument to the
+address\-space on whose behalf the invocation is made and the arg
+argument to the value that was specified when
+unw_init_remote(3)
+was called.
+.PP
+The synopsis and a detailed description of every call\-back routine
+follows below.
+.PP
+.SS CALL\-BACK ROUTINE SYNOPSIS
+.PP
+int
+find_proc_info(unw_addr_space_t
+as,
+.br
+\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPunw_word_t
+ip,
+unw_proc_info_t *pip,
+.br
+\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPint
+need_unwind_info,
+void *arg);
+.br
+void
+put_unwind_info(unw_addr_space_t
+as,
+.br
+\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPunw_proc_info_t *pip,
+void *arg);
+.br
+int
+get_dyn_info_list_addr(unw_addr_space_t
+as,
+.br
+\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPunw_word_t *dilap,
+void *arg);
+.br
+int
+access_mem(unw_addr_space_t
+as,
+.br
+\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPunw_word_t
+addr,
+unw_word_t *valp,
+.br
+\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPint
+write,
+void *arg);
+.br
+int
+access_reg(unw_addr_space_t
+as,
+.br
+\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPunw_regnum_t
+regnum,
+unw_word_t *valp,
+.br
+\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPint
+write,
+void *arg);
+.br
+int
+access_fpreg(unw_addr_space_t
+as,
+.br
+\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPunw_regnum_t
+regnum,
+unw_fpreg_t *fpvalp,
+.br
+\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPint
+write,
+void *arg);
+.br
+int
+resume(unw_addr_space_t
+as,
+.br
+\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPunw_cursor_t *cp,
+void *arg);
+.br
+int
+get_proc_name(unw_addr_space_t
+as,
+.br
+\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPunw_word_t
+addr,
+char *bufp,
+.br
+\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPsize_t
+buf_len,
+unw_word_t *offp,
+.br
+\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fP\fB \fPvoid *arg);
+.br
+.PP
+.SS FIND_PROC_INFO
+.PP
+Libunwind
+invokes the find_proc_info()
+call\-back to
+locate the information need to unwind a particular procedure. The
+ip
+argument is an instruction\-address inside the procedure whose
+information is needed. The pip
+argument is a pointer to the
+variable used to return the desired information. The type of this
+variable is unw_proc_info_t\&.
+See
+unw_get_proc_info(3)
+for details. Argument
+need_unwind_info
+is zero if the call\-back does not need to
+provide values for the following members in the
+unw_proc_info_t
+structure: format,
+unwind_info_size,
+and unwind_info\&.
+If
+need_unwind_info
+is non\-zero, valid values need to be returned
+in these members. Furthermore, the contents of the memory addressed
+by the unwind_info
+member must remain valid until the info is
+released via the put_unwind_info
+call\-back (see below).
+.PP
+On successful completion, the find_proc_info()
+call\-back must
+return zero. Otherwise, the negative value of one of the
+unw_error_t
+error\-codes may be returned. In particular, this
+call\-back may return \-UNW_ESTOPUNWIND
+to signal the end of
+the frame\-chain.
+.PP
+.SS PUT_UNWIND_INFO
+.PP
+Libunwind
+invokes the put_unwind_info()
+call\-back to
+release the resources (such as memory) allocated by a previous call to
+find_proc_info()
+with the need_unwind_info
+argument
+set to a non\-zero value. The pip
+argument has the same value as
+the argument of the same name in the previous matching call to
+find_proc_info().
+Note that libunwind
+does \fInot\fP
+invoke put_unwind_info
+for calls to find_proc_info()
+with a zero need_unwind_info
+argument.
+.PP
+.SS GET_DYN_INFO_LIST_ADDR
+.PP
+Libunwind
+invokes the get_dyn_info_list_addr()
+call\-back to obtain the address of the head of the dynamic unwind\-info
+registration list. The variable stored at the returned address must
+have a type of unw_dyn_info_list_t
+(see
+_U_dyn_register(3)).
+The dliap
+argument is a pointer
+to a variable of type unw_word_t
+which is used to return the
+address of the dynamic unwind\-info registration list. If no dynamic
+unwind\-info registration list exist, the value pointed to by
+dliap
+must be cleared to zero. Libunwind
+will cache the
+value returned by get_dyn_info_list_addr()
+if caching is
+enabled for the given address\-space. The cache can be cleared with a
+call to unw_flush_cache().
+.PP
+On successful completion, the get_dyn_info_list_addr()
+call\-back must return zero. Otherwise, the negative value of one of
+the unw_error_t
+error\-codes may be returned.
+.PP
+.SS ACCESS_MEM
+.PP
+Libunwind
+invokes the access_mem()
+call\-back to read
+from or write to a word of memory in the target address\-space. The
+address of the word to be accessed is passed in argument addr\&.
+To read memory, libunwind
+sets argument write
+to zero and
+valp
+to point to the word that receives the read value. To
+write memory, libunwind
+sets argument write
+to a non\-zero
+value and valp
+to point to the word that contains the value to
+be written. The word that valp
+points to is always in the
+byte\-order of the host\-platform, regardless of the byte\-order of the
+target. In other words, it is the responsibility of the call\-back
+routine to convert between the target\&'s and the host\&'s byte\-order, if
+necessary.
+.PP
+On successful completion, the access_mem()
+call\-back must return zero. Otherwise, the negative value of one of
+the unw_error_t
+error\-codes may be returned.
+.PP
+.SS ACCESS_REG
+.PP
+Libunwind
+invokes the access_reg()
+call\-back to read
+from or write to a scalar (non\-floating\-point) CPU register. The
+index of the register to be accessed is passed in argument
+regnum\&.
+To read a register, libunwind
+sets argument
+write
+to zero and valp
+to point to the word that receives
+the read value. To write a register, libunwind
+sets argument
+write
+to a non\-zero value and valp
+to point to the word
+that contains the value to be written. The word that valp
+points to is always in the byte\-order of the host\-platform, regardless
+of the byte\-order of the target. In other words, it is the
+responsibility of the call\-back routine to convert between the
+target\&'s and the host\&'s byte\-order, if necessary.
+.PP
+On successful completion, the access_reg()
+call\-back must
+return zero. Otherwise, the negative value of one of the
+unw_error_t
+error\-codes may be returned.
+.PP
+.SS ACCESS_FPREG
+.PP
+Libunwind
+invokes the access_fpreg()
+call\-back to read
+from or write to a floating\-point CPU register. The index of the
+register to be accessed is passed in argument regnum\&.
+To read a
+register, libunwind
+sets argument write
+to zero and
+fpvalp
+to point to a variable of type unw_fpreg_t
+that
+receives the read value. To write a register, libunwind
+sets
+argument write
+to a non\-zero value and fpvalp
+to point to
+the variable of type unw_fpreg_t
+that contains the value to
+be written. The word that fpvalp
+points to is always in the
+byte\-order of the host\-platform, regardless of the byte\-order of the
+target. In other words, it is the responsibility of the call\-back
+routine to convert between the target\&'s and the host\&'s byte\-order, if
+necessary.
+.PP
+On successful completion, the access_fpreg()
+call\-back must
+return zero. Otherwise, the negative value of one of the
+unw_error_t
+error\-codes may be returned.
+.PP
+.SS RESUME
+.PP
+Libunwind
+invokes the resume()
+call\-back to resume
+execution in the target address space. Argument cp
+is the
+unwind\-cursor that identifies the stack\-frame in which execution
+should resume. By the time libunwind
+invokes the resume
+call\-back, it has already established the desired machine\- and
+memory\-state via calls to the access_reg(),
+access_fpreg,
+and access_mem()
+call\-backs. Thus, all
+the call\-back needs to do is perform whatever action is needed to
+actually resume execution.
+.PP
+The resume
+call\-back is invoked only in response to a call to
+unw_resume(3),
+so applications which never invoke
+unw_resume(3)
+need not define the resume
+callback.
+.PP
+On successful completion, the resume()
+call\-back must return
+zero. Otherwise, the negative value of one of the
+unw_error_t
+error\-codes may be returned. As a special case,
+when resuming execution in the local address space, the call\-back will
+not return on success.
+.PP
+.SS GET_PROC_NAME
+.PP
+Libunwind
+invokes the get_proc_name()
+call\-back to
+obtain the procedure\-name of a static (not dynamically generated)
+procedure. Argument addr
+is an instruction\-address within the
+procedure whose name is to be obtained. The bufp
+argument is a
+pointer to a character\-buffer used to return the procedure name. The
+size of this buffer is specified in argument buf_len\&.
+The
+returned name must be terminated by a NUL character. If the
+procedure\&'s name is longer than buf_len
+bytes, it must be
+truncated to buf_len\-1
+bytes, with the last byte in the
+buffer set to the NUL character and \-UNW_ENOMEM
+must be
+returned. Argument offp
+is a pointer to a word which is used to
+return the byte\-offset relative to the start of the procedure whose
+name is being returned. For example, if procedure foo()
+starts
+at address 0x40003000, then invoking get_proc_name()
+with
+addr
+set to 0x40003080 should return a value of 0x80 in the word
+pointed to by offp
+(assuming the procedure is at least 0x80
+bytes long).
+.PP
+On successful completion, the get_proc_name()
+call\-back must
+return zero. Otherwise, the negative value of one of the
+unw_error_t
+error\-codes may be returned.
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_create_addr_space()
+returns a
+non\-NULL
+value that represents the newly created
+address\-space. Otherwise, NULL
+is returned.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_create_addr_space()
+is thread\-safe but \fInot\fP
+safe to use from a signal handler.
+.PP
+.SH SEE ALSO
+
+.PP
+_U_dyn_register(3),
+libunwind(3),
+unw_destroy_addr_space(3),
+unw_get_proc_info(3),
+unw_init_remote(3),
+unw_resume(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_create_addr_space.tex b/src/pal/src/libunwind/doc/unw_create_addr_space.tex
new file mode 100644
index 0000000000..8de0691f3a
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_create_addr_space.tex
@@ -0,0 +1,265 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_create\_addr\_space}{David Mosberger-Tang}{Programming Library}{unw\_create\_addr\_space}unw\_create\_addr\_space -- create address space for remote unwinding
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{unw\_addr\_space\_t} \Func{unw\_create\_addr\_space}(\Type{unw\_accessors\_t~*}\Var{ap}, \Type{int} \Var{byteorder});\\
+
+\section{Description}
+
+The \Func{unw\_create\_addr\_space}() routine creates a new unwind
+address-space and initializes it based on the call-back routines
+passed via the \Var{ap} pointer and the specified \Var{byteorder}.
+The call-back routines are described in detail below. The
+\Var{byteorder} can be set to 0 to request the default byte-order of
+the unwind target. To request a particular byte-order,
+\Var{byteorder} can be set to any constant defined by
+\File{$<$endian.h$>$}. In particular, \Const{\_\_LITTLE\_ENDIAN} would
+request little-endian byte-order and \Const{\_\_BIG\_ENDIAN} would
+request big-endian byte-order. Whether or not a particular byte-order
+is supported depends on the target platform.
+
+\section{Call-back Routines}
+
+\Prog{Libunwind} uses a set of call-back routines to access the
+information it needs to unwind a chain of stack-frames. These
+routines are specified via the \Var{ap} argument, which points to a
+variable of type \Type{unw\_accessors\_t}. The contents of this
+variable is copied into the newly-created address space, so the
+variable must remain valid only for the duration of the call to
+\Func{unw\_create\_addr\_space}().
+
+The first argument to every call-back routine is an address-space
+identifier (\Var{as}) and the last argument is an arbitrary,
+application-specified void-pointer (\Var{arg}). When invoking a
+call-back routine, \Prog{libunwind} sets the \Var{as} argument to the
+address-space on whose behalf the invocation is made and the \Var{arg}
+argument to the value that was specified when
+\Func{unw\_init\_remote}(3) was called.
+
+The synopsis and a detailed description of every call-back routine
+follows below.
+
+\subsection{Call-back Routine Synopsis}
+
+\Type{int} \Func{find\_proc\_info}(\Type{unw\_addr\_space\_t} \Var{as},\\
+\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{unw\_word\_t} \Var{ip}, \Type{unw\_proc\_info\_t~*}\Var{pip},\\
+\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{int} \Var{need\_unwind\_info}, \Type{void~*}arg);\\
+\Type{void} \Func{put\_unwind\_info}(\Type{unw\_addr\_space\_t} \Var{as},\\
+\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{unw\_proc\_info\_t~*}pip, \Type{void~*}\Var{arg});\\
+\Type{int} \Func{get\_dyn\_info\_list\_addr}(\Type{unw\_addr\_space\_t} \Var{as},\\
+\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{unw\_word\_t~*}\Var{dilap}, \Type{void~*}\Var{arg});\\
+\Type{int} \Func{access\_mem}(\Var{unw\_addr\_space\_t} \Var{as},\\
+\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{unw\_word\_t} \Var{addr}, \Type{unw\_word\_t~*}\Var{valp},\\
+\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{int} \Var{write}, \Type{void~*}\Var{arg});\\
+\Type{int} \Func{access\_reg}(\Var{unw\_addr\_space\_t} \Var{as},\\
+\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{unw\_regnum\_t} \Var{regnum}, \Type{unw\_word\_t~*}\Var{valp},\\
+\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{int} \Var{write}, \Type{void~*}\Var{arg});\\
+\Type{int} \Func{access\_fpreg}(\Var{unw\_addr\_space\_t} \Var{as},\\
+\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{unw\_regnum\_t} \Var{regnum}, \Type{unw\_fpreg\_t~*}\Var{fpvalp},\\
+\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{int} \Var{write}, \Type{void~*}\Var{arg});\\
+\Type{int} \Func{resume}(\Var{unw\_addr\_space\_t} \Var{as},\\
+\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{unw\_cursor\_t~*}\Var{cp}, \Type{void~*}\Var{arg});\\
+\Type{int} \Func{get\_proc\_name}(\Type{unw\_addr\_space\_t} \Var{as},\\
+\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{unw\_word\_t} \Var{addr}, \Type{char~*}\Var{bufp},\\
+\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{size\_t} \Var{buf\_len}, \Type{unw\_word\_t~*}\Var{offp},\\
+\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\SP\Type{void~*}\Var{arg});\\
+
+\subsection{find\_proc\_info}
+
+\Prog{Libunwind} invokes the \Func{find\_proc\_info}() call-back to
+locate the information need to unwind a particular procedure. The
+\Var{ip} argument is an instruction-address inside the procedure whose
+information is needed. The \Var{pip} argument is a pointer to the
+variable used to return the desired information. The type of this
+variable is \Type{unw\_proc\_info\_t}. See
+\Func{unw\_get\_proc\_info(3)} for details. Argument
+\Var{need\_unwind\_info} is zero if the call-back does not need to
+provide values for the following members in the
+\Type{unw\_proc\_info\_t} structure: \Var{format},
+\Var{unwind\_info\_size}, and \Var{unwind\_info}. If
+\Var{need\_unwind\_info} is non-zero, valid values need to be returned
+in these members. Furthermore, the contents of the memory addressed
+by the \Var{unwind\_info} member must remain valid until the info is
+released via the \Func{put\_unwind\_info} call-back (see below).
+
+On successful completion, the \Func{find\_proc\_info}() call-back must
+return zero. Otherwise, the negative value of one of the
+\Type{unw\_error\_t} error-codes may be returned. In particular, this
+call-back may return -\Const{UNW\_ESTOPUNWIND} to signal the end of
+the frame-chain.
+
+\subsection{put\_unwind\_info}
+
+\Prog{Libunwind} invokes the \Func{put\_unwind\_info}() call-back to
+release the resources (such as memory) allocated by a previous call to
+\Func{find\_proc\_info}() with the \Var{need\_unwind\_info} argument
+set to a non-zero value. The \Var{pip} argument has the same value as
+the argument of the same name in the previous matching call to
+\Func{find\_proc\_info}(). Note that \Prog{libunwind} does \emph{not}
+invoke \Func{put\_unwind\_info} for calls to \Func{find\_proc\_info}()
+with a zero \Var{need\_unwind\_info} argument.
+
+
+\subsection{get\_dyn\_info\_list\_addr}
+
+\Prog{Libunwind} invokes the \Func{get\_dyn\_info\_list\_addr}()
+call-back to obtain the address of the head of the dynamic unwind-info
+registration list. The variable stored at the returned address must
+have a type of \Type{unw\_dyn\_info\_list\_t} (see
+\Func{\_U\_dyn\_register}(3)). The \Var{dliap} argument is a pointer
+to a variable of type \Type{unw\_word\_t} which is used to return the
+address of the dynamic unwind-info registration list. If no dynamic
+unwind-info registration list exist, the value pointed to by
+\Var{dliap} must be cleared to zero. \Prog{Libunwind} will cache the
+value returned by \Func{get\_dyn\_info\_list\_addr}() if caching is
+enabled for the given address-space. The cache can be cleared with a
+call to \Func{unw\_flush\_cache}().
+
+On successful completion, the \Func{get\_dyn\_info\_list\_addr}()
+call-back must return zero. Otherwise, the negative value of one of
+the \Type{unw\_error\_t} error-codes may be returned.
+
+\subsection{access\_mem}
+
+\Prog{Libunwind} invokes the \Func{access\_mem}() call-back to read
+from or write to a word of memory in the target address-space. The
+address of the word to be accessed is passed in argument \Var{addr}.
+To read memory, \Prog{libunwind} sets argument \Var{write} to zero and
+\Var{valp} to point to the word that receives the read value. To
+write memory, \Prog{libunwind} sets argument \Var{write} to a non-zero
+value and \Var{valp} to point to the word that contains the value to
+be written. The word that \Var{valp} points to is always in the
+byte-order of the host-platform, regardless of the byte-order of the
+target. In other words, it is the responsibility of the call-back
+routine to convert between the target's and the host's byte-order, if
+necessary.
+
+On successful completion, the \Func{access\_mem}()
+call-back must return zero. Otherwise, the negative value of one of
+the \Type{unw\_error\_t} error-codes may be returned.
+
+\subsection{access\_reg}
+
+\Prog{Libunwind} invokes the \Func{access\_reg}() call-back to read
+from or write to a scalar (non-floating-point) CPU register. The
+index of the register to be accessed is passed in argument
+\Var{regnum}. To read a register, \Prog{libunwind} sets argument
+\Var{write} to zero and \Var{valp} to point to the word that receives
+the read value. To write a register, \Prog{libunwind} sets argument
+\Var{write} to a non-zero value and \Var{valp} to point to the word
+that contains the value to be written. The word that \Var{valp}
+points to is always in the byte-order of the host-platform, regardless
+of the byte-order of the target. In other words, it is the
+responsibility of the call-back routine to convert between the
+target's and the host's byte-order, if necessary.
+
+On successful completion, the \Func{access\_reg}() call-back must
+return zero. Otherwise, the negative value of one of the
+\Type{unw\_error\_t} error-codes may be returned.
+
+\subsection{access\_fpreg}
+
+\Prog{Libunwind} invokes the \Func{access\_fpreg}() call-back to read
+from or write to a floating-point CPU register. The index of the
+register to be accessed is passed in argument \Var{regnum}. To read a
+register, \Prog{libunwind} sets argument \Var{write} to zero and
+\Var{fpvalp} to point to a variable of type \Type{unw\_fpreg\_t} that
+receives the read value. To write a register, \Prog{libunwind} sets
+argument \Var{write} to a non-zero value and \Var{fpvalp} to point to
+the variable of type \Type{unw\_fpreg\_t} that contains the value to
+be written. The word that \Var{fpvalp} points to is always in the
+byte-order of the host-platform, regardless of the byte-order of the
+target. In other words, it is the responsibility of the call-back
+routine to convert between the target's and the host's byte-order, if
+necessary.
+
+On successful completion, the \Func{access\_fpreg}() call-back must
+return zero. Otherwise, the negative value of one of the
+\Type{unw\_error\_t} error-codes may be returned.
+
+\subsection{resume}
+
+\Prog{Libunwind} invokes the \Func{resume}() call-back to resume
+execution in the target address space. Argument \Var{cp} is the
+unwind-cursor that identifies the stack-frame in which execution
+should resume. By the time \Prog{libunwind} invokes the \Func{resume}
+call-back, it has already established the desired machine- and
+memory-state via calls to the \Func{access\_reg}(),
+\Func{access\_fpreg}, and \Func{access\_mem}() call-backs. Thus, all
+the call-back needs to do is perform whatever action is needed to
+actually resume execution.
+
+The \Func{resume} call-back is invoked only in response to a call to
+\Func{unw\_resume}(3), so applications which never invoke
+\Func{unw\_resume}(3) need not define the \Func{resume} callback.
+
+On successful completion, the \Func{resume}() call-back must return
+zero. Otherwise, the negative value of one of the
+\Type{unw\_error\_t} error-codes may be returned. As a special case,
+when resuming execution in the local address space, the call-back will
+not return on success.
+
+\subsection{get\_proc\_name}
+
+\Prog{Libunwind} invokes the \Func{get\_proc\_name}() call-back to
+obtain the procedure-name of a static (not dynamically generated)
+procedure. Argument \Var{addr} is an instruction-address within the
+procedure whose name is to be obtained. The \Var{bufp} argument is a
+pointer to a character-buffer used to return the procedure name. The
+size of this buffer is specified in argument \Var{buf\_len}. The
+returned name must be terminated by a NUL character. If the
+procedure's name is longer than \Var{buf\_len} bytes, it must be
+truncated to \Var{buf\_len}\Prog{-1} bytes, with the last byte in the
+buffer set to the NUL character and -\Const{UNW\_ENOMEM} must be
+returned. Argument \Var{offp} is a pointer to a word which is used to
+return the byte-offset relative to the start of the procedure whose
+name is being returned. For example, if procedure \Func{foo}() starts
+at address 0x40003000, then invoking \Func{get\_proc\_name}() with
+\Var{addr} set to 0x40003080 should return a value of 0x80 in the word
+pointed to by \Var{offp} (assuming the procedure is at least 0x80
+bytes long).
+
+On successful completion, the \Func{get\_proc\_name}() call-back must
+return zero. Otherwise, the negative value of one of the
+\Type{unw\_error\_t} error-codes may be returned.
+
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_create\_addr\_space}() returns a
+non-\Const{NULL} value that represents the newly created
+address-space. Otherwise, \Const{NULL} is returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_create\_addr\_space}() is thread-safe but \emph{not}
+safe to use from a signal handler.
+
+\section{See Also}
+
+\SeeAlso{\_U\_dyn\_register(3)},
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_destroy\_addr\_space(3)},
+\SeeAlso{unw\_get\_proc\_info(3)},
+\SeeAlso{unw\_init\_remote(3)},
+\SeeAlso{unw\_resume(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_destroy_addr_space.man b/src/pal/src/libunwind/doc/unw_destroy_addr_space.man
new file mode 100644
index 0000000000..90c9777efb
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_destroy_addr_space.man
@@ -0,0 +1,57 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_DESTROY\\_ADDR\\_SPACE" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+unw_destroy_addr_space
+\-\- destroy unwind address space
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+void
+unw_destroy_addr_space(unw_addr_space_t
+as);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_destroy_addr_space()
+routine destroys the
+address space specified by argument as
+and thereby releases
+all associated resources (such as memory).
+.PP
+Applications must not destroy the local address space
+unw_local_addr_space\&.
+Attempting to do so results in
+undefined behavior (e.g., the application may crash).
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_create_addr_space(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_destroy_addr_space.tex b/src/pal/src/libunwind/doc/unw_destroy_addr_space.tex
new file mode 100644
index 0000000000..a66b10b4b0
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_destroy_addr_space.tex
@@ -0,0 +1,40 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_destroy\_addr\_space}{David Mosberger-Tang}{Programming Library}{unw\_destroy\_addr\_space}unw\_destroy\_addr\_space -- destroy unwind address space
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{void} \Func{unw\_destroy\_addr\_space}(\Type{unw\_addr\_space\_t} \Var{as});\\
+
+\section{Description}
+
+The \Func{unw\_destroy\_addr\_space}() routine destroys the
+address space specified by argument \Var{as} and thereby releases
+all associated resources (such as memory).
+
+Applications must not destroy the local address space
+\Var{unw\_local\_addr\_space}. Attempting to do so results in
+undefined behavior (e.g., the application may crash).
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_create\_addr\_space(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_flush_cache.man b/src/pal/src/libunwind/doc/unw_flush_cache.man
new file mode 100644
index 0000000000..627449effe
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_flush_cache.man
@@ -0,0 +1,93 @@
+'\" t
+.\" Manual page created with latex2man on Fri Dec 2 16:09:33 PST 2016
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_FLUSH\\_CACHE" "3" "02 December 2016" "Programming Library " "Programming Library "
+.SH NAME
+unw_flush_cache
+\-\- flush cached info
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+void
+unw_flush_cache(unw_addr_space_t
+as,
+unw_word_t
+lo,
+unw_word_t
+hi);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_flush_cache()
+routine flushes all cached info as it
+relates to address\-range lo
+to hi
+(non\-inclusive) in the
+target address\-space as\&.
+In addition, all info cached for
+address\-space as
+that is not tied to a particular code\-range is
+also flushed. For example, the address of the dynamic registration
+list is not tied to a code\-range and its cached value (if any) is
+flushed by a call to this routine. The address range specified by
+lo
+and hi
+should be understood as a hint:
+unw_flush_cache()
+may flush more information than requested,
+but \fInever\fP
+less. In other words, unw_flush_cache()
+may
+overflush, but not underflush.
+.PP
+As a special case, if arguments lo
+and hi
+are both 0, all
+information cached on behalf of address space as
+is flushed.
+.PP
+.SH RETURN VALUE
+
+.PP
+The unw_flush_cache()
+routine cannot fail and does not
+return a value.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+The unw_flush_cache()
+routine is thread\-safe as well as safe to
+use from a signal handler.
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_set_caching_policy(3)
+unw_set_cache_size(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_flush_cache.tex b/src/pal/src/libunwind/doc/unw_flush_cache.tex
new file mode 100644
index 0000000000..32319db5d1
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_flush_cache.tex
@@ -0,0 +1,58 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_flush\_cache}{David Mosberger-Tang}{Programming Library}{unw\_flush\_cache}unw\_flush\_cache -- flush cached info
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{void} \Func{unw\_flush\_cache}(\Type{unw\_addr\_space\_t} \Var{as}, \Type{unw\_word\_t} \Var{lo}, \Type{unw\_word\_t} \Var{hi});\\
+
+\section{Description}
+
+The \Func{unw\_flush\_cache}() routine flushes all cached info as it
+relates to address-range \Var{lo} to \Var{hi} (non-inclusive) in the
+target address-space \Var{as}. In addition, all info cached for
+address-space \Var{as} that is not tied to a particular code-range is
+also flushed. For example, the address of the dynamic registration
+list is not tied to a code-range and its cached value (if any) is
+flushed by a call to this routine. The address range specified by
+\Var{lo} and \Var{hi} should be understood as a hint:
+\Func{unw\_flush\_cache}() may flush more information than requested,
+but \emph{never} less. In other words, \Func{unw\_flush\_cache}() may
+overflush, but not underflush.
+
+As a special case, if arguments \Var{lo} and \Var{hi} are both 0, all
+information cached on behalf of address space \Var{as} is flushed.
+
+\section{Return Value}
+
+The \Func{unw\_flush\_cache}() routine cannot fail and does not
+return a value.
+
+\section{Thread and Signal Safety}
+
+The \Func{unw\_flush\_cache}() routine is thread-safe as well as safe to
+use from a signal handler.
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_set\_caching\_policy(3)}
+\SeeAlso{unw\_set\_cache\_size(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_get_accessors.man b/src/pal/src/libunwind/doc/unw_get_accessors.man
new file mode 100644
index 0000000000..83fe4fcea6
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_get_accessors.man
@@ -0,0 +1,79 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:44 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_GET\\_ACCESSORS" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+unw_get_accessors
+\-\- get pointer to accessor call\-backs
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+unw_accessors_t *unw_get_accessors(unw_addr_space_t as);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_get_accessors()
+routine returns a pointer to a
+unw_accessors_t
+structure, which contains the call\-back
+routines that were specified when address space as
+was created
+(see unw_create_addr_space(3)).
+The returned pointer is
+guaranteed to remain valid until address space as
+is destroyed
+by a call to unw_destroy_addr_space(3).
+.PP
+Note that unw_get_accessors()
+can be used to retrieve the
+call\-back routines for the local address space
+unw_local_addr_space\&.
+.PP
+.SH RETURN VALUE
+
+.PP
+The unw_get_accessors()
+routine cannot fail and always
+returns a valid (non\-NULL)
+pointer to an
+unw_accessors_t
+structure.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+The unw_get_accessors()
+routine is thread\-safe as well as
+safe to use from a signal handler.
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_create_addr_space(3),
+unw_destroy_addr_space(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_get_accessors.tex b/src/pal/src/libunwind/doc/unw_get_accessors.tex
new file mode 100644
index 0000000000..bf344a32de
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_get_accessors.tex
@@ -0,0 +1,55 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_get\_accessors}{David Mosberger-Tang}{Programming Library}{unw\_get\_accessors}unw\_get\_accessors -- get pointer to accessor call-backs
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{unw\_accessors\_t~*}\Func{unw\_get\_accessors}(\Type{unw\_addr\_space\_t~}\Var{as});\\
+
+\section{Description}
+
+The \Func{unw\_get\_accessors}() routine returns a pointer to a
+\Type{unw\_accessors\_t} structure, which contains the call-back
+routines that were specified when address space \Var{as} was created
+(see \Func{unw\_create\_addr\_space}(3)). The returned pointer is
+guaranteed to remain valid until address space \Var{as} is destroyed
+by a call to \Func{unw\_destroy\_addr\_space}(3).
+
+Note that \Func{unw\_get\_accessors}() can be used to retrieve the
+call-back routines for the local address space
+\Var{unw\_local\_addr\_space}.
+
+\section{Return Value}
+
+The \Func{unw\_get\_accessors}() routine cannot fail and always
+returns a valid (non-\Const{NULL}) pointer to an
+\Type{unw\_accessors\_t} structure.
+
+\section{Thread and Signal Safety}
+
+The \Func{unw\_get\_accessors}() routine is thread-safe as well as
+safe to use from a signal handler.
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_create\_addr\_space(3)},
+\SeeAlso{unw\_destroy\_addr\_space(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_get_fpreg.man b/src/pal/src/libunwind/doc/unw_get_fpreg.man
new file mode 100644
index 0000000000..5e54ca13d3
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_get_fpreg.man
@@ -0,0 +1,111 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_GET\\_FPREG" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+unw_get_fpreg
+\-\- get contents of floating\-point register
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_get_fpreg(unw_cursor_t *cp,
+unw_regnum_t
+reg,
+unw_fpreg_t *valp);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_get_fpreg()
+routine reads the value of floating\-point
+register reg
+in the stack frame identified by cursor cp
+and stores the value in the variable pointed to by valp\&.
+.PP
+The register numbering is target\-dependent and described in separate
+manual pages (e.g., libunwind\-ia64(3) for the IA\-64 target).
+Furthermore, the exact set of accessible registers may depend on the
+type of frame that cp
+is referring to. For ordinary stack
+frames, it is normally possible to access only the preserved
+(``callee\-saved\&'') registers and frame\-related registers (such as the
+stack\-pointer). However, for signal frames (see
+unw_is_signal_frame(3)),
+it is usually possible to access
+all registers.
+.PP
+Note that unw_get_fpreg()
+can only read the contents of
+floating\-point registers. See unw_get_fpreg(3)
+for a way to
+read registers which fit in a single word.
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_get_fpreg()
+returns 0.
+Otherwise the negative value of one of the error\-codes below is
+returned.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_get_fpreg()
+is thread\-safe as well as safe to use
+from a signal handler.
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_EUNSPEC
+ An unspecified error occurred.
+.TP
+UNW_EBADREG
+ An attempt was made to read a register
+that is either invalid or not accessible in the current frame.
+.PP
+In addition, unw_get_fpreg()
+may return any error returned by
+the access_mem(),
+access_reg(),
+and
+access_fpreg()
+call\-backs (see
+unw_create_addr_space(3)).
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+libunwind\-ia64(3),
+unw_get_reg(3),
+unw_is_fpreg(3),
+unw_is_signal_frame(3),
+unw_set_fpreg(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_get_fpreg.tex b/src/pal/src/libunwind/doc/unw_get_fpreg.tex
new file mode 100644
index 0000000000..dd679adc06
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_get_fpreg.tex
@@ -0,0 +1,77 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_get\_fpreg}{David Mosberger-Tang}{Programming Library}{unw\_get\_fpreg}unw\_get\_fpreg -- get contents of floating-point register
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_get\_fpreg}(\Type{unw\_cursor\_t~*}\Var{cp}, \Type{unw\_regnum\_t} \Var{reg}, \Type{unw\_fpreg\_t~*}\Var{valp});\\
+
+\section{Description}
+
+The \Func{unw\_get\_fpreg}() routine reads the value of floating-point
+register \Var{reg} in the stack frame identified by cursor \Var{cp}
+and stores the value in the variable pointed to by \Var{valp}.
+
+The register numbering is target-dependent and described in separate
+manual pages (e.g., libunwind-ia64(3) for the IA-64 target).
+Furthermore, the exact set of accessible registers may depend on the
+type of frame that \Var{cp} is referring to. For ordinary stack
+frames, it is normally possible to access only the preserved
+(``callee-saved'') registers and frame-related registers (such as the
+stack-pointer). However, for signal frames (see
+\Func{unw\_is\_signal\_frame}(3)), it is usually possible to access
+all registers.
+
+Note that \Func{unw\_get\_fpreg}() can only read the contents of
+floating-point registers. See \Func{unw\_get\_fpreg}(3) for a way to
+read registers which fit in a single word.
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_get\_fpreg}() returns 0.
+Otherwise the negative value of one of the error-codes below is
+returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_get\_fpreg}() is thread-safe as well as safe to use
+from a signal handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred.
+\item[\Const{UNW\_EBADREG}] An attempt was made to read a register
+ that is either invalid or not accessible in the current frame.
+\end{Description}
+In addition, \Func{unw\_get\_fpreg}() may return any error returned by
+the \Func{access\_mem}(), \Func{access\_reg}(), and
+\Func{access\_fpreg}() call-backs (see
+\Func{unw\_create\_addr\_space}(3)).
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{libunwind-ia64(3)},
+\SeeAlso{unw\_get\_reg(3)},
+\SeeAlso{unw\_is\_fpreg(3)},
+\SeeAlso{unw\_is\_signal\_frame(3)},
+\SeeAlso{unw\_set\_fpreg(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_get_proc_info.man b/src/pal/src/libunwind/doc/unw_get_proc_info.man
new file mode 100644
index 0000000000..09eadee27a
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_get_proc_info.man
@@ -0,0 +1,203 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:44 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_GET\\_PROC\\_INFO" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+unw_get_proc_info
+\-\- get info on current procedure
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_get_proc_info(unw_cursor_t *cp,
+unw_proc_info_t *pip);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_get_proc_info()
+routine returns auxiliary
+information about the procedure that created the stack frame
+identified by argument cp\&.
+The pip
+argument is a pointer
+to a structure of type unw_proc_info_t
+which is used to
+return the information. The unw_proc_info_t
+has the
+following members:
+.TP
+unw_word_t start_ip
+ The address of the first
+instruction of the procedure. If this address cannot be determined
+(e.g., due to lack of unwind information), the start_ip
+member is cleared to 0.
+.br
+.TP
+unw_word_t end_ip
+ The address of the first
+instruction \fIbeyond\fP
+the end of the procedure. If this address
+cannot be determined (e.g., due to lack of unwind information),
+the end_ip
+member is cleared to 0.
+.br
+.TP
+unw_word_t lsda
+ The address of the
+language\-specific data\-area (LSDA). This area normally contains
+language\-specific information needed during exception handling. If
+the procedure has no such area, this member is cleared to 0.
+.br
+.TP
+unw_word_t handler
+ The address of the exception
+handler routine. This is sometimes called the \fIpersonality\fP
+routine. If the procedure does not define
+a personality routine, the handler
+member is cleared to 0.
+.br
+.TP
+unw_word_t gp
+ The global\-pointer of the
+procedure. On platforms that do not use a global pointer, this
+member may contain an undefined value. On all other platforms, it
+must be set either to the correct global\-pointer value of the
+procedure or to 0 if the proper global\-pointer cannot be
+obtained for some reason.
+.br
+.TP
+unw_word_t flags
+ A set of flags. There are
+currently no target\-independent flags. For the IA\-64 target, the
+flag UNW_PI_FLAG_IA64_RBS_SWITCH
+is set if the
+procedure may switch the register\-backing store.
+.br
+.TP
+int format
+ The format of the unwind\-info for this
+procedure. If the unwind\-info consists of dynamic procedure info,
+format
+is equal to UNW_INFO_FORMAT_DYNAMIC\&.
+If the
+unwind\-info consists of a (target\-specific) unwind table, it is
+equal to to UNW_INFO_FORMAT_TABLE\&.
+All other values are
+reserved for future use by libunwind\&.
+This member exists
+for use by the find_proc_info()
+call\-back (see
+unw_create_addr_space(3)).
+The
+unw_get_proc_info()
+routine
+may return an undefined value in this member.
+.br
+.TP
+int unwind_info_size
+ The size of the unwind\-info
+in bytes. This member exists for use by the
+find_proc_info()
+call\-back (see
+unw_create_addr_space(3)).
+The
+unw_get_proc_info()
+routine
+may return an undefined value in this member.
+.br
+.TP
+void *unwind_info
+ The pointer to the unwind\-info.
+If no unwind info is available, this member must be set to
+NULL\&.
+This member exists for use by the
+find_proc_info()
+call\-back (see
+unw_create_addr_space(3)).
+The
+unw_get_proc_info()
+routine
+may return an undefined value in this member.
+.br
+.PP
+Note that for the purposes of libunwind,
+the code of a
+procedure is assumed to occupy a single, contiguous range of
+addresses. For this reason, it is alwas possible to describe the
+extent of a procedure with the start_ip
+and end_ip
+members. If a single function/routine is split into multiple,
+discontiguous pieces, libunwind
+will treat each piece as a
+separate procedure.
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_get_proc_info()
+returns 0.
+Otherwise the negative value of one of the error\-codes below is
+returned.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_get_proc_info()
+is thread\-safe. If cursor cp
+is
+in the local address\-space, this routine is also safe to use from a
+signal handler.
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_EUNSPEC
+ An unspecified error occurred.
+.TP
+UNW_ENOINFO
+ Libunwind
+was unable to locate
+unwind\-info for the procedure.
+.TP
+UNW_EBADVERSION
+ The unwind\-info for the procedure has
+version or format that is not understood by libunwind\&.
+.PP
+In addition, unw_get_proc_info()
+may return any error
+returned by the access_mem()
+call\-back (see
+unw_create_addr_space(3)).
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_create_addr_space(3),
+unw_get_proc_name(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_get_proc_info.tex b/src/pal/src/libunwind/doc/unw_get_proc_info.tex
new file mode 100644
index 0000000000..72621f1a65
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_get_proc_info.tex
@@ -0,0 +1,123 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_get\_proc\_info}{David Mosberger-Tang}{Programming Library}{unw\_get\_proc\_info}unw\_get\_proc\_info -- get info on current procedure
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_get\_proc\_info}(\Type{unw\_cursor\_t~*}\Var{cp}, \Type{unw\_proc\_info\_t~*}\Var{pip});\\
+
+\section{Description}
+
+The \Func{unw\_get\_proc\_info}() routine returns auxiliary
+information about the procedure that created the stack frame
+identified by argument \Var{cp}. The \Var{pip} argument is a pointer
+to a structure of type \Type{unw\_proc\_info\_t} which is used to
+return the information. The \Type{unw\_proc\_info\_t} has the
+following members:
+\begin{description}
+\item[\Type{unw\_word\_t} \Var{start\_ip}] The address of the first
+ instruction of the procedure. If this address cannot be determined
+ (e.g., due to lack of unwind information), the \Var{start\_ip}
+ member is cleared to 0. \\
+\item[\Type{unw\_word\_t} \Var{end\_ip}] The address of the first
+ instruction \emph{beyond} the end of the procedure. If this address
+ cannot be determined (e.g., due to lack of unwind information),
+ the \Var{end\_ip} member is cleared to 0. \\
+\item[\Type{unw\_word\_t} \Var{lsda}] The address of the
+ language-specific data-area (LSDA). This area normally contains
+ language-specific information needed during exception handling. If
+ the procedure has no such area, this member is cleared to 0. \\
+\item[\Type{unw\_word\_t} \Var{handler}] The address of the exception
+ handler routine. This is sometimes called the \emph{personality}
+ routine. If the procedure does not define
+ a personality routine, the \Var{handler} member is cleared to 0. \\
+\item[\Type{unw\_word\_t} \Var{gp}] The global-pointer of the
+ procedure. On platforms that do not use a global pointer, this
+ member may contain an undefined value. On all other platforms, it
+ must be set either to the correct global-pointer value of the
+ procedure or to 0 if the proper global-pointer cannot be
+ obtained for some reason. \\
+\item[\Type{unw\_word\_t} \Var{flags}] A set of flags. There are
+ currently no target-independent flags. For the IA-64 target, the
+ flag \Const{UNW\_PI\_FLAG\_IA64\_RBS\_SWITCH} is set if the
+ procedure may switch the register-backing store.\\
+\item[\Type{int} \Var{format}] The format of the unwind-info for this
+ procedure. If the unwind-info consists of dynamic procedure info,
+ \Var{format} is equal to \Const{UNW\_INFO\_FORMAT\_DYNAMIC}. If the
+ unwind-info consists of a (target-specific) unwind table, it is
+ equal to to \Const{UNW\_INFO\_FORMAT\_TABLE}. All other values are
+ reserved for future use by \Prog{libunwind}. This member exists
+ for use by the \Func{find\_proc\_info}() call-back (see
+ \Func{unw\_create\_addr\_space}(3)). The
+ \Func{unw\_get\_proc\_info}() routine
+ may return an undefined value in this member. \\
+\item[\Type{int} \Var{unwind\_info\_size}] The size of the unwind-info
+ in bytes. This member exists for use by the
+ \Func{find\_proc\_info}() call-back (see
+ \Func{unw\_create\_addr\_space}(3)). The
+ \Func{unw\_get\_proc\_info}() routine
+ may return an undefined value in this member.\\
+\item[\Type{void~*}\Var{unwind\_info}] The pointer to the unwind-info.
+ If no unwind info is available, this member must be set to
+ \Const{NULL}. This member exists for use by the
+ \Func{find\_proc\_info}() call-back (see
+ \Func{unw\_create\_addr\_space}(3)). The
+ \Func{unw\_get\_proc\_info}() routine
+ may return an undefined value in this member.\\
+\end{description}
+Note that for the purposes of \Prog{libunwind}, the code of a
+procedure is assumed to occupy a single, contiguous range of
+addresses. For this reason, it is alwas possible to describe the
+extent of a procedure with the \Var{start\_ip} and \Var{end\_ip}
+members. If a single function/routine is split into multiple,
+discontiguous pieces, \Prog{libunwind} will treat each piece as a
+separate procedure.
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_get\_proc\_info}() returns 0.
+Otherwise the negative value of one of the error-codes below is
+returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_get\_proc\_info}() is thread-safe. If cursor \Var{cp} is
+in the local address-space, this routine is also safe to use from a
+signal handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred.
+\item[\Const{UNW\_ENOINFO}] \Prog{Libunwind} was unable to locate
+ unwind-info for the procedure.
+\item[\Const{UNW\_EBADVERSION}] The unwind-info for the procedure has
+ version or format that is not understood by \Prog{libunwind}.
+\end{Description}
+In addition, \Func{unw\_get\_proc\_info}() may return any error
+returned by the \Func{access\_mem}() call-back (see
+\Func{unw\_create\_addr\_space}(3)).
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_create\_addr\_space(3)},
+\SeeAlso{unw\_get\_proc\_name(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_get_proc_info_by_ip.man b/src/pal/src/libunwind/doc/unw_get_proc_info_by_ip.man
new file mode 100644
index 0000000000..a347a1d008
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_get_proc_info_by_ip.man
@@ -0,0 +1,134 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_GET\\_PROC\\_INFO\\_BY\\_IP" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+unw_get_proc_info_by_ip
+\-\- get procedure info by IP
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_get_proc_info_by_ip(unw_addr_space_t as,
+unw_word_t ip,
+unw_proc_info_t *pip,
+void *arg);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_get_proc_info_by_ip()
+routine returns the same
+kind of auxiliary information about a procedure as
+unw_get_proc_info(),
+except that the info is looked up by
+instruction\-pointer (IP) instead of a cursor. This is more flexible
+because it is possible to look up the info for an arbitrary procedure,
+even if it is not part of the current call\-chain. However, since it
+is more flexible, it also tends to run slower (and often much slower)
+than unw_get_proc_info().
+.PP
+The routine expects the followins arguments: as
+is the
+address\-space in which the instruction\-pointer should be looked up.
+For a look\-up in the local address\-space,
+unw_local_addr_space
+can be passed for this argument.
+Argument ip
+is the instruction\-pointer for which the procedure
+info should be looked up and pip
+is a pointer to a structure of
+type unw_proc_info_t
+which is used to return the info.
+Lastly, arg
+is the address\-space argument that should be used
+when accessing the address\-space. It has the same purpose as the
+argument of the same name for unw_init_remote().
+When
+accessing the local address\-space (first argument is
+unw_local_addr_space),
+NULL
+must be passed for this
+argument.
+.PP
+Note that for the purposes of libunwind,
+the code of a
+procedure is assumed to occupy a single, contiguous range of
+addresses. For this reason, it is alwas possible to describe the
+extent of a procedure with the start_ip
+and end_ip
+members. If a single function/routine is split into multiple,
+discontiguous pieces, libunwind
+will treat each piece as a
+separate procedure.
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_get_proc_info_by_ip()
+returns 0. Otherwise the negative value of one of the error\-codes
+below is returned.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_get_proc_info()
+is thread\-safe. If the local
+address\-space is passed in argument as,
+this routine is also
+safe to use from a signal handler.
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_EUNSPEC
+ An unspecified error occurred.
+.TP
+UNW_ENOINFO
+ Libunwind
+was unable to locate
+unwind\-info for the procedure.
+.TP
+UNW_EBADVERSION
+ The unwind\-info for the procedure has
+version or format that is not understood by libunwind\&.
+.PP
+In addition, unw_get_proc_info()
+may return any error
+returned by the access_mem()
+call\-back (see
+unw_create_addr_space(3)).
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_create_addr_space(3),
+unw_get_proc_name(3),
+unw_get_proc_info(3),
+unw_init_remote(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_get_proc_info_by_ip.tex b/src/pal/src/libunwind/doc/unw_get_proc_info_by_ip.tex
new file mode 100644
index 0000000000..5e1d5d247e
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_get_proc_info_by_ip.tex
@@ -0,0 +1,91 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_get\_proc\_info\_by\_ip}{David Mosberger-Tang}{Programming Library}{unw\_get\_proc\_info\_by\_ip}unw\_get\_proc\_info\_by\_ip -- get procedure info by IP
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_get\_proc\_info\_by\_ip}(\Type{unw\_addr\_space\_t~}\Var{as}, \Type{unw\_word\_t~}\Var{ip}, \Type{unw\_proc\_info\_t~*}\Var{pip}, \Type{void~*}\Var{arg});\\
+
+\section{Description}
+
+The \Func{unw\_get\_proc\_info\_by\_ip}() routine returns the same
+kind of auxiliary information about a procedure as
+\Func{unw\_get\_proc\_info}(), except that the info is looked up by
+instruction-pointer (IP) instead of a cursor. This is more flexible
+because it is possible to look up the info for an arbitrary procedure,
+even if it is not part of the current call-chain. However, since it
+is more flexible, it also tends to run slower (and often much slower)
+than \Func{unw\_get\_proc\_info}().
+
+The routine expects the followins arguments: \Var{as} is the
+address-space in which the instruction-pointer should be looked up.
+For a look-up in the local address-space,
+\Var{unw\_local\_addr\_space} can be passed for this argument.
+Argument \Var{ip} is the instruction-pointer for which the procedure
+info should be looked up and \Var{pip} is a pointer to a structure of
+type \Type{unw\_proc\_info\_t} which is used to return the info.
+Lastly, \Var{arg} is the address-space argument that should be used
+when accessing the address-space. It has the same purpose as the
+argument of the same name for \Func{unw\_init\_remote}(). When
+accessing the local address-space (first argument is
+\Var{unw\_local\_addr\_space}), \Const{NULL} must be passed for this
+argument.
+
+Note that for the purposes of \Prog{libunwind}, the code of a
+procedure is assumed to occupy a single, contiguous range of
+addresses. For this reason, it is alwas possible to describe the
+extent of a procedure with the \Var{start\_ip} and \Var{end\_ip}
+members. If a single function/routine is split into multiple,
+discontiguous pieces, \Prog{libunwind} will treat each piece as a
+separate procedure.
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_get\_proc\_info\_by\_ip}()
+returns 0. Otherwise the negative value of one of the error-codes
+below is returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_get\_proc\_info}() is thread-safe. If the local
+address-space is passed in argument \Var{as}, this routine is also
+safe to use from a signal handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred.
+\item[\Const{UNW\_ENOINFO}] \Prog{Libunwind} was unable to locate
+ unwind-info for the procedure.
+\item[\Const{UNW\_EBADVERSION}] The unwind-info for the procedure has
+ version or format that is not understood by \Prog{libunwind}.
+\end{Description}
+In addition, \Func{unw\_get\_proc\_info}() may return any error
+returned by the \Func{access\_mem}() call-back (see
+\Func{unw\_create\_addr\_space}(3)).
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_create\_addr\_space(3)},
+\SeeAlso{unw\_get\_proc\_name(3)},
+\SeeAlso{unw\_get\_proc\_info(3)},
+\SeeAlso{unw\_init\_remote(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_get_proc_name.man b/src/pal/src/libunwind/doc/unw_get_proc_name.man
new file mode 100644
index 0000000000..8b2bd06eaf
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_get_proc_name.man
@@ -0,0 +1,123 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_GET\\_PROC\\_NAME" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+unw_get_proc_name
+\-\- get name of current procedure
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_get_proc_name(unw_cursor_t *cp,
+char *bufp,
+size_t
+len,
+unw_word_t *offp);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_get_proc_name()
+routine returns the name of the
+procedure that created the stack frame identified by argument
+cp\&.
+The bufp
+argument is a pointer to a character buffer
+that is at least len
+bytes long. This buffer is used to return
+the name of the procedure. The offp
+argument is a pointer to a
+word that is used to return the byte\-offset of the instruction\-pointer
+saved in the stack frame identified by cp,
+relative to the start
+of the procedure. For example, if procedure foo()
+starts at
+address 0x40003000, then invoking unw_get_proc_name()
+on a
+stack frame with an instruction\-pointer value of 0x40003080 would
+return a value of 0x80 in the word pointed to by offp
+(assuming
+the procedure is at least 0x80 bytes long).
+.PP
+Note that on some platforms there is no reliable way to distinguish
+between procedure names and ordinary labels. Furthermore, if symbol
+information has been stripped from a program, procedure names may be
+completely unavailable or may be limited to those exported via a
+dynamic symbol table. In such cases, unw_get_proc_name()
+may return the name of a label or a preceeding (nearby) procedure.
+However, the offset returned through offp
+is always relative to
+the returned name, which ensures that the value (address) of the
+returned name plus the returned offset will always be equal to the
+instruction\-pointer of the stack frame identified by cp\&.
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_get_proc_name()
+returns 0.
+Otherwise the negative value of one of the error\-codes below is
+returned.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_get_proc_name()
+is thread\-safe. If cursor cp
+is
+in the local address\-space, this routine is also safe to use from a
+signal handler.
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_EUNSPEC
+ An unspecified error occurred.
+.TP
+UNW_ENOINFO
+ Libunwind
+was unable to determine
+the name of the procedure.
+.TP
+UNW_ENOMEM
+ The procedure name is too long to fit
+in the buffer provided. A truncated version of the name has been
+returned.
+.PP
+In addition, unw_get_proc_name()
+may return any error
+returned by the access_mem()
+call\-back (see
+unw_create_addr_space(3)).
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_get_proc_info(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_get_proc_name.tex b/src/pal/src/libunwind/doc/unw_get_proc_name.tex
new file mode 100644
index 0000000000..c413990880
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_get_proc_name.tex
@@ -0,0 +1,82 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_get\_proc\_name}{David Mosberger-Tang}{Programming Library}{unw\_get\_proc\_name}unw\_get\_proc\_name -- get name of current procedure
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_get\_proc\_name}(\Type{unw\_cursor\_t~*}\Var{cp}, \Type{char~*}\Var{bufp}, \Type{size\_t} \Var{len}, \Type{unw\_word\_t~*}\Var{offp});\\
+
+\section{Description}
+
+The \Func{unw\_get\_proc\_name}() routine returns the name of the
+procedure that created the stack frame identified by argument
+\Var{cp}. The \Var{bufp} argument is a pointer to a character buffer
+that is at least \Var{len} bytes long. This buffer is used to return
+the name of the procedure. The \Var{offp} argument is a pointer to a
+word that is used to return the byte-offset of the instruction-pointer
+saved in the stack frame identified by \Var{cp}, relative to the start
+of the procedure. For example, if procedure \Func{foo}() starts at
+address 0x40003000, then invoking \Func{unw\_get\_proc\_name}() on a
+stack frame with an instruction-pointer value of 0x40003080 would
+return a value of 0x80 in the word pointed to by \Var{offp} (assuming
+the procedure is at least 0x80 bytes long).
+
+Note that on some platforms there is no reliable way to distinguish
+between procedure names and ordinary labels. Furthermore, if symbol
+information has been stripped from a program, procedure names may be
+completely unavailable or may be limited to those exported via a
+dynamic symbol table. In such cases, \Func{unw\_get\_proc\_name}()
+may return the name of a label or a preceeding (nearby) procedure.
+However, the offset returned through \Var{offp} is always relative to
+the returned name, which ensures that the value (address) of the
+returned name plus the returned offset will always be equal to the
+instruction-pointer of the stack frame identified by \Var{cp}.
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_get\_proc\_name}() returns 0.
+Otherwise the negative value of one of the error-codes below is
+returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_get\_proc\_name}() is thread-safe. If cursor \Var{cp} is
+in the local address-space, this routine is also safe to use from a
+signal handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred.
+\item[\Const{UNW\_ENOINFO}] \Prog{Libunwind} was unable to determine
+ the name of the procedure.
+\item[\Const{UNW\_ENOMEM}] The procedure name is too long to fit
+ in the buffer provided. A truncated version of the name has been
+ returned.
+\end{Description}
+In addition, \Func{unw\_get\_proc\_name}() may return any error
+returned by the \Func{access\_mem}() call-back (see
+\Func{unw\_create\_addr\_space}(3)).
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_get\_proc\_info(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_get_reg.man b/src/pal/src/libunwind/doc/unw_get_reg.man
new file mode 100644
index 0000000000..83e8bb43b6
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_get_reg.man
@@ -0,0 +1,112 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_GET\\_REG" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+unw_get_reg
+\-\- get register contents
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_get_reg(unw_cursor_t *cp,
+unw_regnum_t
+reg,
+unw_word_t *valp);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_get_reg()
+routine reads the value of register
+reg
+in the stack frame identified by cursor cp
+and stores
+the value in the word pointed to by valp\&.
+.PP
+The register numbering is target\-dependent and described in separate
+manual pages (e.g., libunwind\-ia64(3) for the IA\-64 target).
+Furthermore, the exact set of accessible registers may depend on the
+type of frame that cp
+is referring to. For ordinary stack
+frames, it is normally possible to access only the preserved
+(``callee\-saved\&'') registers and frame\-related registers (such as the
+stack\-pointer). However, for signal frames (see
+unw_is_signal_frame(3)),
+it is usually possible to access
+all registers.
+.PP
+Note that unw_get_reg()
+can only read the contents of
+registers whose values fit in a single word. See
+unw_get_fpreg(3)
+for a way to read registers which do not fit
+this constraint.
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_get_reg()
+returns 0.
+Otherwise the negative value of one of the error\-codes below is
+returned.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_get_reg()
+is thread\-safe as well as safe to use
+from a signal handler.
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_EUNSPEC
+ An unspecified error occurred.
+.TP
+UNW_EBADREG
+ An attempt was made to read a register
+that is either invalid or not accessible in the current frame.
+.PP
+In addition, unw_get_reg()
+may return any error returned by
+the access_mem(),
+access_reg(),
+and
+access_fpreg()
+call\-backs (see
+unw_create_addr_space(3)).
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+libunwind\-ia64(3),
+unw_get_fpreg(3),
+unw_is_signal_frame(3),
+unw_set_reg(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_get_reg.tex b/src/pal/src/libunwind/doc/unw_get_reg.tex
new file mode 100644
index 0000000000..b66e8c0dbb
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_get_reg.tex
@@ -0,0 +1,77 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_get\_reg}{David Mosberger-Tang}{Programming Library}{unw\_get\_reg}unw\_get\_reg -- get register contents
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_get\_reg}(\Type{unw\_cursor\_t~*}\Var{cp}, \Type{unw\_regnum\_t} \Var{reg}, \Type{unw\_word\_t~*}\Var{valp});\\
+
+\section{Description}
+
+The \Func{unw\_get\_reg}() routine reads the value of register
+\Var{reg} in the stack frame identified by cursor \Var{cp} and stores
+the value in the word pointed to by \Var{valp}.
+
+The register numbering is target-dependent and described in separate
+manual pages (e.g., libunwind-ia64(3) for the IA-64 target).
+Furthermore, the exact set of accessible registers may depend on the
+type of frame that \Var{cp} is referring to. For ordinary stack
+frames, it is normally possible to access only the preserved
+(``callee-saved'') registers and frame-related registers (such as the
+stack-pointer). However, for signal frames (see
+\Func{unw\_is\_signal\_frame}(3)), it is usually possible to access
+all registers.
+
+Note that \Func{unw\_get\_reg}() can only read the contents of
+registers whose values fit in a single word. See
+\Func{unw\_get\_fpreg}(3) for a way to read registers which do not fit
+this constraint.
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_get\_reg}() returns 0.
+Otherwise the negative value of one of the error-codes below is
+returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_get\_reg}() is thread-safe as well as safe to use
+from a signal handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred.
+\item[\Const{UNW\_EBADREG}] An attempt was made to read a register
+ that is either invalid or not accessible in the current frame.
+\end{Description}
+In addition, \Func{unw\_get\_reg}() may return any error returned by
+the \Func{access\_mem}(), \Func{access\_reg}(), and
+\Func{access\_fpreg}() call-backs (see
+\Func{unw\_create\_addr\_space}(3)).
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{libunwind-ia64(3)},
+\SeeAlso{unw\_get\_fpreg(3)},
+\SeeAlso{unw\_is\_signal\_frame(3)},
+\SeeAlso{unw\_set\_reg(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_getcontext.man b/src/pal/src/libunwind/doc/unw_getcontext.man
new file mode 100644
index 0000000000..13725df957
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_getcontext.man
@@ -0,0 +1,93 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_GETCONTEXT" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+unw_getcontext
+\-\- get initial machine\-state
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_getcontext(unw_context_t *ucp);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_getcontext()
+routine initializes the context structure
+pointed to by ucp
+with the machine\-state of the call\-site. The
+exact set of registers stored by unw_getcontext()
+is
+platform\-specific, but, in general, at least all preserved
+(``callee\-saved\&'') and all frame\-related registers, such as the
+stack\-pointer, will be stored.
+.PP
+This routine is normally implemented as a macro and applications
+should not attempt to take its address.
+.PP
+.SH PLATFORM\-SPECIFIC NOTES
+
+.PP
+On IA\-64, unw_context_t
+has a layout that is compatible with
+that of ucontext_t
+and such structures can be initialized with
+getcontext()
+instead of unw_getcontext().
+However, the
+reverse is \fInot\fP
+true and it is \fInot\fP
+safe to use structures
+initialized by unw_getcontext()
+in places where a structure
+initialized by getcontext()
+is expected. The reason for this
+asymmetry is that unw_getcontext()
+is optimized for maximum
+performance and does not, for example, save the signal mask.
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_getcontext()
+returns 0.
+Otherwise, a value of \-1 is returned.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_getcontext()
+is thread\-safe as well as safe to use
+from a signal handler.
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_init_local(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_getcontext.tex b/src/pal/src/libunwind/doc/unw_getcontext.tex
new file mode 100644
index 0000000000..fa3eb814b3
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_getcontext.tex
@@ -0,0 +1,63 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_getcontext}{David Mosberger-Tang}{Programming Library}{unw\_getcontext}unw\_getcontext -- get initial machine-state
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_getcontext}(\Type{unw\_context\_t~*}\Var{ucp});\\
+
+\section{Description}
+
+The \Func{unw\_getcontext}() routine initializes the context structure
+pointed to by \Var{ucp} with the machine-state of the call-site. The
+exact set of registers stored by \Func{unw\_getcontext}() is
+platform-specific, but, in general, at least all preserved
+(``callee-saved'') and all frame-related registers, such as the
+stack-pointer, will be stored.
+
+This routine is normally implemented as a macro and applications
+should not attempt to take its address.
+
+\section{Platform-specific Notes}
+
+On IA-64, \Type{unw\_context\_t} has a layout that is compatible with
+that of \Type{ucontext\_t} and such structures can be initialized with
+\Func{getcontext}() instead of \Func{unw\_getcontext}(). However, the
+reverse is \emph{not} true and it is \emph{not} safe to use structures
+initialized by \Func{unw\_getcontext()} in places where a structure
+initialized by \Func{getcontext()} is expected. The reason for this
+asymmetry is that \Func{unw\_getcontext()} is optimized for maximum
+performance and does not, for example, save the signal mask.
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_getcontext}() returns 0.
+Otherwise, a value of -1 is returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_getcontext}() is thread-safe as well as safe to use
+from a signal handler.
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_init\_local(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_init_local.man b/src/pal/src/libunwind/doc/unw_init_local.man
new file mode 100644
index 0000000000..301dd6f93b
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_init_local.man
@@ -0,0 +1,124 @@
+'\" t
+.\" Manual page created with latex2man on Wed Aug 16 12:11:05 PDT 2017
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_INIT\\_LOCAL" "3" "16 August 2017" "Programming Library " "Programming Library "
+.SH NAME
+unw_init_local
+\-\- initialize cursor for local unwinding
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_init_local(unw_cursor_t *c,
+unw_context_t *ctxt);
+.br
+int
+unw_init_local2(unw_cursor_t *c,
+unw_context_t *ctxt,
+int
+flag);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_init_local()
+routine initializes the unwind cursor
+pointed to by c
+with the machine\-state in the context structure
+pointed to by ctxt\&.
+As such, the machine\-state pointed to by
+ctxt
+identifies the initial stack frame at which unwinding
+starts. The machine\-state is expected to be one provided by a call to
+unw_getcontext; as such, the instruction pointer may point to the
+instruction after the last instruction of a function, and libunwind
+will back\-up the instruction pointer before beginning a walk up the
+call stack. The machine\-state must remain valid for the duration for
+which the cursor c
+is in use.
+.PP
+The unw_init_local()
+routine can be used only for unwinding in
+the address space of the current process (i.e., for local unwinding).
+For all other cases, unw_init_remote()
+must be used instead.
+However, unwind performance may be better when using
+unw_init_local().
+Also, unw_init_local()
+is
+available even when UNW_LOCAL_ONLY
+has been defined before
+including <libunwind.h>,
+whereas unw_init_remote()
+is not.
+.PP
+If the unw_context_t is known to be a signal frame (i.e., from the
+third argument in a sigaction handler on linux),
+unw_init_local2()
+should be used for correct initialization
+on some platforms, passing the UNW_INIT_SIGNAL_FRAME flag.
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_init_local()
+returns 0.
+Otherwise the negative value of one of the error\-codes below is
+returned.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_init_local()
+is thread\-safe as well as safe to use from a
+signal handler.
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_EINVAL
+ unw_init_local()
+was called in a
+version of libunwind
+which supports remote unwinding only
+(this normally happens when calling unw_init_local()
+for a
+cross\-platform version of libunwind).
+.TP
+UNW_EUNSPEC
+ An unspecified error occurred.
+.TP
+UNW_EBADREG
+ A register needed by unw_init_local()
+wasn\&'t accessible.
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_init_remote(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_init_local.tex b/src/pal/src/libunwind/doc/unw_init_local.tex
new file mode 100644
index 0000000000..ff0d03bc77
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_init_local.tex
@@ -0,0 +1,80 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_init\_local}{David Mosberger-Tang}{Programming Library}{unw\_init\_local}unw\_init\_local -- initialize cursor for local unwinding
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_init\_local}(\Type{unw\_cursor\_t~*}\Var{c}, \Type{unw\_context\_t~*}\Var{ctxt});\\
+\Type{int} \Func{unw\_init\_local2}(\Type{unw\_cursor\_t~*}\Var{c}, \Type{unw\_context\_t~*}\Var{ctxt}, \Type{int} \Var{flag});\\
+
+\section{Description}
+
+The \Func{unw\_init\_local}() routine initializes the unwind cursor
+pointed to by \Var{c} with the machine-state in the context structure
+pointed to by \Var{ctxt}. As such, the machine-state pointed to by
+\Var{ctxt} identifies the initial stack frame at which unwinding
+starts. The machine-state is expected to be one provided by a call to
+unw_getcontext; as such, the instruction pointer may point to the
+instruction after the last instruction of a function, and libunwind
+will back-up the instruction pointer before beginning a walk up the
+call stack. The machine-state must remain valid for the duration for
+which the cursor \Var{c} is in use.
+
+The \Func{unw\_init\_local}() routine can be used only for unwinding in
+the address space of the current process (i.e., for local unwinding).
+For all other cases, \Func{unw\_init\_remote}() must be used instead.
+However, unwind performance may be better when using
+\Func{unw\_init\_local}(). Also, \Func{unw\_init\_local}() is
+available even when \Const{UNW\_LOCAL\_ONLY} has been defined before
+including \File{$<$libunwind.h$>$}, whereas \Func{unw\_init\_remote}()
+is not.
+
+If the unw_context_t is known to be a signal frame (i.e., from the
+third argument in a sigaction handler on linux),
+\Func{unw\_init\_local2}() should be used for correct initialization
+on some platforms, passing the UNW_INIT_SIGNAL_FRAME flag.
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_init\_local}() returns 0.
+Otherwise the negative value of one of the error-codes below is
+returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_init\_local}() is thread-safe as well as safe to use from a
+signal handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_EINVAL}] \Func{unw\_init\_local}() was called in a
+ version of \Prog{libunwind} which supports remote unwinding only
+ (this normally happens when calling \Func{unw\_init\_local}() for a
+ cross-platform version of \Prog{libunwind}).
+\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred.
+\item[\Const{UNW\_EBADREG}] A register needed by \Func{unw\_init\_local}()
+ wasn't accessible.
+\end{Description}
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)}, \SeeAlso{unw\_init\_remote(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_init_local2.man b/src/pal/src/libunwind/doc/unw_init_local2.man
new file mode 100644
index 0000000000..6cbbf008ab
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_init_local2.man
@@ -0,0 +1 @@
+.so man3/unw_init_local.3
diff --git a/src/pal/src/libunwind/doc/unw_init_remote.man b/src/pal/src/libunwind/doc/unw_init_remote.man
new file mode 100644
index 0000000000..0acdac9617
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_init_remote.man
@@ -0,0 +1,123 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_INIT\\_REMOTE" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+unw_init_remote
+\-\- initialize cursor for remote unwinding
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_init_remote(unw_cursor_t *c,
+unw_addr_space_t as,
+void *arg);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_init_remote()
+routine initializes the unwind cursor
+pointed to by c
+for unwinding in the address space identified by
+as\&.
+The as
+argument can either be set to
+unw_local_addr_space
+(local address space) or to an arbitrary
+address space created with unw_create_addr_space().
+.PP
+The arg
+void\-pointer tells the address space exactly what entity
+should be unwound. For example, if unw_local_addr_space
+is
+passed in as,
+then arg
+needs to be a pointer to a context
+structure containing the machine\-state of the initial stack frame.
+However, other address\-spaces may instead expect a process\-id, a
+thread\-id, or a pointer to an arbitrary structure which identifies the
+stack\-frame chain to be unwound. In other words, the interpretation
+of arg
+is entirely dependent on the address\-space in use;
+libunwind
+never interprets the argument in any way on its own.
+.PP
+Note that unw_init_remote()
+can be used to initiate unwinding
+in \fIany\fP
+process, including the local process in which the
+unwinder itself is running. However, for local unwinding, it is
+generally preferable to use unw_init_local()
+instead, because
+it is easier to use and because it may perform better.
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_init_remote()
+returns 0.
+Otherwise the negative value of one of the error\-codes below is
+returned.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_init_remote()
+is thread\-safe. If the local address\-space
+is passed in argument as,
+this routine is also safe to use from
+a signal handler.
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_EINVAL
+ unw_init_remote()
+was called in a
+version of libunwind
+which supports local unwinding only
+(this normally happens when defining UNW_LOCAL_ONLY
+before
+including <libunwind.h>
+and then calling
+unw_init_remote()).
+.TP
+UNW_EUNSPEC
+ An unspecified error occurred.
+.TP
+UNW_EBADREG
+ A register needed by unw_init_remote()
+wasn\&'t accessible.
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_create_addr_space(3),
+unw_init_local(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_init_remote.tex b/src/pal/src/libunwind/doc/unw_init_remote.tex
new file mode 100644
index 0000000000..9b4dc7997a
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_init_remote.tex
@@ -0,0 +1,79 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_init\_remote}{David Mosberger-Tang}{Programming Library}{unw\_init\_remote}unw\_init\_remote -- initialize cursor for remote unwinding
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_init\_remote}(\Type{unw\_cursor\_t~*}\Var{c}, \Type{unw\_addr\_space\_t~}\Var{as}, \Type{void~*}\Var{arg});\\
+
+\section{Description}
+
+The \Func{unw\_init\_remote}() routine initializes the unwind cursor
+pointed to by \Var{c} for unwinding in the address space identified by
+\Var{as}. The \Var{as} argument can either be set to
+\Var{unw\_local\_addr\_space} (local address space) or to an arbitrary
+address space created with \Func{unw\_create\_addr\_space}().
+
+The \Var{arg} void-pointer tells the address space exactly what entity
+should be unwound. For example, if \Var{unw\_local\_addr\_space} is
+passed in \Var{as}, then \Var{arg} needs to be a pointer to a context
+structure containing the machine-state of the initial stack frame.
+However, other address-spaces may instead expect a process-id, a
+thread-id, or a pointer to an arbitrary structure which identifies the
+stack-frame chain to be unwound. In other words, the interpretation
+of \Var{arg} is entirely dependent on the address-space in use;
+\Prog{libunwind} never interprets the argument in any way on its own.
+
+Note that \Func{unw\_init\_remote}() can be used to initiate unwinding
+in \emph{any} process, including the local process in which the
+unwinder itself is running. However, for local unwinding, it is
+generally preferable to use \Func{unw\_init\_local}() instead, because
+it is easier to use and because it may perform better.
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_init\_remote}() returns 0.
+Otherwise the negative value of one of the error-codes below is
+returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_init\_remote}() is thread-safe. If the local address-space
+is passed in argument \Var{as}, this routine is also safe to use from
+a signal handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_EINVAL}] \Func{unw\_init\_remote}() was called in a
+ version of \Prog{libunwind} which supports local unwinding only
+ (this normally happens when defining \Const{UNW\_LOCAL\_ONLY} before
+ including \File{$<$libunwind.h$>$} and then calling
+ \Func{unw\_init\_remote}()).
+\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred.
+\item[\Const{UNW\_EBADREG}] A register needed by \Func{unw\_init\_remote}()
+ wasn't accessible.
+\end{Description}
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)}, \SeeAlso{unw\_create\_addr\_space(3)},
+\SeeAlso{unw\_init\_local(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_is_fpreg.man b/src/pal/src/libunwind/doc/unw_is_fpreg.man
new file mode 100644
index 0000000000..0c26ec1bc7
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_is_fpreg.man
@@ -0,0 +1,73 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_IS\\_FPREG" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+unw_is_fpreg
+\-\- check if a register is a floating\-point register
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_is_fpreg(unw_regnum_t
+reg);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_is_fpreg()
+routine checks whether register number
+reg
+is a floating\-point register.
+.PP
+This routine is normally implemented as a macro and applications
+should not attempt to take its address.
+.PP
+.SH RETURN VALUE
+
+.PP
+The unw_is_fpreg()
+routine returns a non\-zero value if
+reg
+is a floating\-point register. Otherwise, it returns a value
+of 0.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_is_fpreg()
+is thread\-safe as well as safe to use
+from a signal handler.
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_get_reg(3),
+unw_set_reg(3),
+unw_get_fpreg(3),
+unw_set_fpreg(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_is_fpreg.tex b/src/pal/src/libunwind/doc/unw_is_fpreg.tex
new file mode 100644
index 0000000000..c28cdc9be4
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_is_fpreg.tex
@@ -0,0 +1,52 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_is\_fpreg}{David Mosberger-Tang}{Programming Library}{unw\_is\_fpreg}unw\_is\_fpreg -- check if a register is a floating-point register
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_is\_fpreg}(\Type{unw\_regnum\_t} \Var{reg});\\
+
+\section{Description}
+
+The \Func{unw\_is\_fpreg}() routine checks whether register number
+\Var{reg} is a floating-point register.
+
+This routine is normally implemented as a macro and applications
+should not attempt to take its address.
+
+\section{Return Value}
+
+The \Func{unw\_is\_fpreg}() routine returns a non-zero value if
+\Var{reg} is a floating-point register. Otherwise, it returns a value
+of 0.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_is\_fpreg}() is thread-safe as well as safe to use
+from a signal handler.
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_get\_reg(3)},
+\SeeAlso{unw\_set\_reg(3)},
+\SeeAlso{unw\_get\_fpreg(3)},
+\SeeAlso{unw\_set\_fpreg(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_is_signal_frame.man b/src/pal/src/libunwind/doc/unw_is_signal_frame.man
new file mode 100644
index 0000000000..d9a7cda7b5
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_is_signal_frame.man
@@ -0,0 +1,88 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_IS\\_SIGNAL\\_FRAME" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+unw_is_signal_frame
+\-\- check if current frame is a signal frame
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_is_signal_frame(unw_cursor_t *cp);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_is_signal_frame()
+routine returns a positive value
+if the current frame identified by cp
+is a signal frame, and a
+value of 0 otherwise. For the purpose of this discussion, a signal
+frame is a frame that was created in response to a potentially
+asynchronous interruption. For UNIX and UNIX\-like platforms, such
+frames are normally created by the kernel when delivering a signal.
+In a kernel\-environment, a signal frame might, for example, correspond
+to a frame created in response to a device interrupt.
+.PP
+Signal frames are somewhat unusual because the asynchronous nature of
+the events that create them require storing the contents of registers
+that are normally treated as scratch (``caller\-saved\&'') registers.
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_is_signal_frame()
+returns a
+positive value if the current frame is a signal frame, or 0 if it is
+not. Otherwise, a negative value of one of the error\-codes below is
+returned.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_is_signal_frame()
+is thread\-safe as well as safe to use
+from a signal handler.
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_ENOINFO
+ Libunwind
+is unable to determine
+whether or not the current frame is a signal frame.
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_get_reg(3),
+unw_set_reg(3),
+unw_get_fpreg(3),
+unw_set_fpreg(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_is_signal_frame.tex b/src/pal/src/libunwind/doc/unw_is_signal_frame.tex
new file mode 100644
index 0000000000..f262e5600c
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_is_signal_frame.tex
@@ -0,0 +1,67 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_is\_signal\_frame}{David Mosberger-Tang}{Programming Library}{unw\_is\_signal\_frame}unw\_is\_signal\_frame -- check if current frame is a signal frame
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_is\_signal\_frame}(\Type{unw\_cursor\_t~*}\Var{cp});\\
+
+\section{Description}
+
+The \Func{unw\_is\_signal\_frame}() routine returns a positive value
+if the current frame identified by \Var{cp} is a signal frame, and a
+value of 0 otherwise. For the purpose of this discussion, a signal
+frame is a frame that was created in response to a potentially
+asynchronous interruption. For UNIX and UNIX-like platforms, such
+frames are normally created by the kernel when delivering a signal.
+In a kernel-environment, a signal frame might, for example, correspond
+to a frame created in response to a device interrupt.
+
+Signal frames are somewhat unusual because the asynchronous nature of
+the events that create them require storing the contents of registers
+that are normally treated as scratch (``caller-saved'') registers.
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_is\_signal\_frame}() returns a
+positive value if the current frame is a signal frame, or 0 if it is
+not. Otherwise, a negative value of one of the error-codes below is
+returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_is\_signal\_frame}() is thread-safe as well as safe to use
+from a signal handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_ENOINFO}] \Prog{Libunwind} is unable to determine
+ whether or not the current frame is a signal frame.
+\end{Description}
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_get\_reg(3)},
+\SeeAlso{unw\_set\_reg(3)},
+\SeeAlso{unw\_get\_fpreg(3)},
+\SeeAlso{unw\_set\_fpreg(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_reg_states_iterate.man b/src/pal/src/libunwind/doc/unw_reg_states_iterate.man
new file mode 100644
index 0000000000..e328ad2e38
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_reg_states_iterate.man
@@ -0,0 +1,137 @@
+'\" t
+.\" Manual page created with latex2man on Wed Aug 16 11:09:44 PDT 2017
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_REG\\_STATES\\_ITERATE" "3" "16 August 2017" "Programming Library " "Programming Library "
+.SH NAME
+unw_reg_states_iterate
+\-\- get register state info on current procedure
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_reg_states_iterate(unw_cursor_t *cp,
+unw_reg_states_callbackcb,
+void *token);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_reg_states_iterate()
+routine provides
+information about the procedure that created the stack frame
+identified by argument cp\&.
+The cb
+argument is a pointer
+to a function of type unw_reg_states_callback
+which is used to
+return the information. The function unw_reg_states_callback
+has the
+following definition:
+.PP
+int
+( *unw_reg_states_callback)(void *token,
+void *reg_states_data,
+size_t
+reg_states_data_size,
+unw_word_t
+start_ip,
+unw_word_t
+end_ip);
+.PP
+The callback function may be invoked several times for each call of unw_reg_states_iterate\&.
+Each call is associcated with a instruction address range and a set of instructions on how to update register values when returning from the procedure in that address range. For each invocation, the arguments to the callback function are:
+.TP
+void * token
+ The token value passed to unw_reg_states_callback\&.
+.br
+.TP
+void * reg_states_data
+ A pointer to data about
+updating register values. This data, or a copy of it, can be passed
+to unw_apply_reg_state\&.
+.br
+.TP
+int reg_states_data_size
+ The size of the register update data.
+.br
+.TP
+unw_word_t start_ip
+ The address of the first
+instruction of the address range.
+.br
+.TP
+unw_word_t end_ip
+ The address of the first
+instruction \fIbeyond\fP
+the end of the address range.
+.br
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_reg_states_iterate()
+returns
+0. If the callback function returns a nonzero value, that indicates
+failure and the function returns immediately. Otherwise the negative
+value of one of the error\-codes below is returned.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_reg_states_iterate()
+is thread\-safe. If cursor cp
+is
+in the local address\-space, this routine is also safe to use from a
+signal handler.
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_EUNSPEC
+ An unspecified error occurred.
+.TP
+UNW_ENOINFO
+ Libunwind
+was unable to locate
+unwind\-info for the procedure.
+.TP
+UNW_EBADVERSION
+ The unwind\-info for the procedure has
+version or format that is not understood by libunwind\&.
+.PP
+In addition, unw_reg_states_iterate()
+may return any error
+returned by the access_mem()
+call\-back (see
+unw_create_addr_space(3)).
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_apply_reg_state(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_reg_states_iterate.tex b/src/pal/src/libunwind/doc/unw_reg_states_iterate.tex
new file mode 100644
index 0000000000..36c9b548a2
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_reg_states_iterate.tex
@@ -0,0 +1,83 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_reg\_states\_iterate}{David Mosberger-Tang}{Programming Library}{unw\_reg\_states\_iterate}unw\_reg\_states\_iterate -- get register state info on current procedure
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_reg\_states\_iterate}(\Type{unw\_cursor\_t~*}\Var{cp}, \Type{unw\_reg\_states\_callback}\Var{cb}, \Type{void~*}\Var{token});\\
+
+\section{Description}
+
+The \Func{unw\_reg\_states\_iterate}() routine provides
+information about the procedure that created the stack frame
+identified by argument \Var{cp}. The \Var{cb} argument is a pointer
+to a function of type \Type{unw\_reg\_states\_callback} which is used to
+return the information. The function \Type{unw\_reg\_states\_callback} has the
+following definition:
+
+\Type{int} (~*\Var{unw\_reg\_states\_callback})(\Type{void~*}\Var{token},
+ \Type{void~*}\Var{reg\_states\_data},
+ \Type{size\_t} \Var{reg\_states\_data\_size},
+ \Type{unw\_word\_t} \Var{start\_ip}, \Type{unw\_word\_t} \Var{end\_ip});
+
+The callback function may be invoked several times for each call of \Func{unw\_reg\_states\_iterate}. Each call is associcated with a instruction address range and a set of instructions on how to update register values when returning from the procedure in that address range. For each invocation, the arguments to the callback function are:
+\begin{description}
+\item[\Type{void~*} \Var{token}] The token value passed to \Var{unw\_reg\_states\_callback}. \\
+\item[\Type{void~*} \Var{reg\_states\_data}] A pointer to data about
+ updating register values. This data, or a copy of it, can be passed
+ to \Var{unw\_apply\_reg\_state}.\\
+\item[\Type{int} \Var{reg\_states\_data\_size}] The size of the register update data. \\
+\item[\Type{unw\_word\_t} \Var{start\_ip}] The address of the first
+ instruction of the address range. \\
+\item[\Type{unw\_word\_t} \Var{end\_ip}] The address of the first
+ instruction \emph{beyond} the end of the address range. \\
+\end{description}
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_reg\_states\_iterate}() returns
+0. If the callback function returns a nonzero value, that indicates
+failure and the function returns immediately. Otherwise the negative
+value of one of the error-codes below is returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_reg\_states\_iterate}() is thread-safe. If cursor \Var{cp} is
+in the local address-space, this routine is also safe to use from a
+signal handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred.
+\item[\Const{UNW\_ENOINFO}] \Prog{Libunwind} was unable to locate
+ unwind-info for the procedure.
+\item[\Const{UNW\_EBADVERSION}] The unwind-info for the procedure has
+ version or format that is not understood by \Prog{libunwind}.
+\end{Description}
+In addition, \Func{unw\_reg\_states\_iterate}() may return any error
+returned by the \Func{access\_mem}() call-back (see
+\Func{unw\_create\_addr\_space}(3)).
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_apply\_reg\_state(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_regname.man b/src/pal/src/libunwind/doc/unw_regname.man
new file mode 100644
index 0000000000..1e3e2dbc6e
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_regname.man
@@ -0,0 +1,68 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_REGNAME" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+unw_regname
+\-\- get register name
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+const char *unw_regname(unw_regnum_t
+regnum);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_regname()
+routine returns a printable name for
+register regnum\&.
+If regnum
+is an invalid or otherwise
+unrecognized register number, a string consisting of three question
+marks is returned. The returned string is statically allocated and
+therefore guaranteed to remain valid until the application terminates.
+.PP
+.SH RETURN VALUE
+
+.PP
+The unw_regname()
+routine cannot fail and always returns a
+valid (non\-NULL)
+string.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+The unw_regname()
+routine is thread\-safe as well as safe to
+use from a signal handler.
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_regname.tex b/src/pal/src/libunwind/doc/unw_regname.tex
new file mode 100644
index 0000000000..94b6434194
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_regname.tex
@@ -0,0 +1,47 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_regname}{David Mosberger-Tang}{Programming Library}{unw\_regname}unw\_regname -- get register name
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{const char~*}\Func{unw\_regname}(\Type{unw\_regnum\_t} \Var{regnum});\\
+
+\section{Description}
+
+The \Func{unw\_regname}() routine returns a printable name for
+register \Var{regnum}. If \Var{regnum} is an invalid or otherwise
+unrecognized register number, a string consisting of three question
+marks is returned. The returned string is statically allocated and
+therefore guaranteed to remain valid until the application terminates.
+
+\section{Return Value}
+
+The \Func{unw\_regname}() routine cannot fail and always returns a
+valid (non-\Const{NULL}) string.
+
+\section{Thread and Signal Safety}
+
+The \Func{unw\_regname}() routine is thread-safe as well as safe to
+use from a signal handler.
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_resume.man b/src/pal/src/libunwind/doc/unw_resume.man
new file mode 100644
index 0000000000..1bf38327bf
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_resume.man
@@ -0,0 +1,146 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_RESUME" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+unw_resume
+\-\- resume execution in a particular stack frame
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_resume(unw_cursor_t *cp);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_resume()
+routine resumes execution at the stack frame
+identified by cp\&.
+The behavior of this routine differs
+slightly for local and remote unwinding.
+.PP
+For local unwinding, unw_resume()
+restores the machine state
+and then directly resumes execution in the target stack frame. Thus
+unw_resume()
+does not return in this case. Restoring the
+machine state normally involves restoring the ``preserved\&''
+(callee\-saved) registers. However, if execution in any of the stack
+frames younger (more deeply nested) than the one identified by
+cp
+was interrupted by a signal, then unw_resume()
+will
+restore all registers as well as the signal mask. Attempting to call
+unw_resume()
+on a cursor which identifies the stack frame of
+another thread results in undefined behavior (e.g., the program may
+crash).
+.PP
+For remote unwinding, unw_resume()
+installs the machine state
+identified by the cursor by calling the access_reg
+and
+access_fpreg
+accessor callbacks as needed. Once that is
+accomplished, the resume
+accessor callback is invoked. The
+unw_resume
+routine then returns normally (that is, unlikely
+for local unwinding, unw_resume
+will always return for remote
+unwinding).
+.PP
+Most platforms reserve some registers to pass arguments to exception
+handlers (e.g., IA\-64 uses r15\-r18
+for this
+purpose). These registers are normally treated like ``scratch\&''
+registers. However, if libunwind
+is used to set an exception
+argument register to a particular value (e.g., via
+unw_set_reg()),
+then unw_resume()
+will install this
+value as the contents of the register. In other words, the exception
+handling arguments are installed even in cases where normally only the
+``preserved\&'' registers are restored.
+.PP
+Note that unw_resume()
+does \fInot\fP
+invoke any unwind
+handlers (aka, ``personality routines\&''). If a program needs this, it
+will have to do so on its own by obtaining the unw_proc_info_t
+of each unwound frame and appropriately processing its unwind handler
+and language\-specific data area (lsda). These steps are generally
+dependent on the target\-platform and are regulated by the
+processor\-specific ABI (application\-binary interface).
+.PP
+.SH RETURN VALUE
+
+.PP
+For local unwinding, unw_resume()
+does not return on success.
+For remote unwinding, it returns 0 on success. On failure, the
+negative value of one of the errors below is returned.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_resume()
+is thread\-safe. If cursor cp
+is in the
+local address\-space, this routine is also safe to use from a signal
+handler.
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_EUNSPEC
+ An unspecified error occurred.
+.TP
+UNW_EBADREG
+ A register needed by unw_resume()
+wasn\&'t
+accessible.
+.TP
+UNW_EINVALIDIP
+ The instruction pointer identified by
+cp
+is not valid.
+.TP
+UNW_BADFRAME
+ The stack frame identified by
+cp
+is not valid.
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_set_reg(3),
+sigprocmask(2)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_resume.tex b/src/pal/src/libunwind/doc/unw_resume.tex
new file mode 100644
index 0000000000..38b18248ab
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_resume.tex
@@ -0,0 +1,99 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_resume}{David Mosberger-Tang}{Programming Library}{unw\_resume}unw\_resume -- resume execution in a particular stack frame
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_resume}(\Type{unw\_cursor\_t~*}\Var{cp});\\
+
+\section{Description}
+
+The \Func{unw\_resume}() routine resumes execution at the stack frame
+identified by \Var{cp}. The behavior of this routine differs
+slightly for local and remote unwinding.
+
+For local unwinding, \Func{unw\_resume}() restores the machine state
+and then directly resumes execution in the target stack frame. Thus
+\Func{unw\_resume}() does not return in this case. Restoring the
+machine state normally involves restoring the ``preserved''
+(callee-saved) registers. However, if execution in any of the stack
+frames younger (more deeply nested) than the one identified by
+\Var{cp} was interrupted by a signal, then \Func{unw\_resume}() will
+restore all registers as well as the signal mask. Attempting to call
+\Func{unw\_resume}() on a cursor which identifies the stack frame of
+another thread results in undefined behavior (e.g., the program may
+crash).
+
+For remote unwinding, \Func{unw\_resume}() installs the machine state
+identified by the cursor by calling the \Func{access\_reg} and
+\Func{access\_fpreg} accessor callbacks as needed. Once that is
+accomplished, the \Func{resume} accessor callback is invoked. The
+\Func{unw\_resume} routine then returns normally (that is, unlikely
+for local unwinding, \Func{unw\_resume} will always return for remote
+unwinding).
+
+Most platforms reserve some registers to pass arguments to exception
+handlers (e.g., IA-64 uses \texttt{r15}-\texttt{r18} for this
+purpose). These registers are normally treated like ``scratch''
+registers. However, if \Prog{libunwind} is used to set an exception
+argument register to a particular value (e.g., via
+\Func{unw\_set\_reg}()), then \Func{unw\_resume}() will install this
+value as the contents of the register. In other words, the exception
+handling arguments are installed even in cases where normally only the
+``preserved'' registers are restored.
+
+Note that \Func{unw\_resume}() does \emph{not} invoke any unwind
+handlers (aka, ``personality routines''). If a program needs this, it
+will have to do so on its own by obtaining the \Type{unw\_proc\_info\_t}
+of each unwound frame and appropriately processing its unwind handler
+and language-specific data area (lsda). These steps are generally
+dependent on the target-platform and are regulated by the
+processor-specific ABI (application-binary interface).
+
+\section{Return Value}
+
+For local unwinding, \Func{unw\_resume}() does not return on success.
+For remote unwinding, it returns 0 on success. On failure, the
+negative value of one of the errors below is returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_resume}() is thread-safe. If cursor \Var{cp} is in the
+local address-space, this routine is also safe to use from a signal
+handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred.
+\item[\Const{UNW\_EBADREG}] A register needed by \Func{unw\_resume}() wasn't
+ accessible.
+\item[\Const{UNW\_EINVALIDIP}] The instruction pointer identified by
+ \Var{cp} is not valid.
+\item[\Const{UNW\_BADFRAME}] The stack frame identified by
+ \Var{cp} is not valid.
+\end{Description}
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_set\_reg(3)},
+sigprocmask(2)
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_set_cache_size.man b/src/pal/src/libunwind/doc/unw_set_cache_size.man
new file mode 100644
index 0000000000..34bbc53961
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_set_cache_size.man
@@ -0,0 +1,88 @@
+'\" t
+.\" Manual page created with latex2man on Fri Jan 13 08:33:21 PST 2017
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_SET\\_CACHE\\_SIZE" "3" "13 January 2017" "Programming Library " "Programming Library "
+.SH NAME
+unw_set_cache_size
+\-\- set unwind cache size
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_set_cache_size(unw_addr_space_t
+as,
+size_t
+size,
+int
+flag);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_set_cache_size()
+routine sets the cache size of
+address space as
+to hold at least as many items as given by
+argument size\&.
+It may hold more items as determined by the
+implementation. To disable caching, call
+unw_set_caching_policy)
+with a policy of
+UNW_CACHE_NONE\&.
+Flag is currently unused and must be 0.
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_set_cache_size()
+returns 0.
+Otherwise the negative value of one of the error\-codes below is
+returned.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_set_cache_size()
+is thread\-safe but \fInot\fP
+safe
+to use from a signal handler.
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_ENOMEM
+ The desired cache size could not be
+established because the application is out of memory.
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_create_addr_space(3),
+unw_set_caching_policy(3),
+unw_flush_cache(3)
+.PP
+.SH AUTHOR
+
+.PP
+Dave Watson
+.br
+Email: \fBdade.watson@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_set_cache_size.tex b/src/pal/src/libunwind/doc/unw_set_cache_size.tex
new file mode 100644
index 0000000000..1bd7e00df7
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_set_cache_size.tex
@@ -0,0 +1,59 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_set\_cache\_size}{Dave Watson}{Programming Library}{unw\_set\_cache\_size}unw\_set\_cache\_size -- set unwind cache size
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_set\_cache\_size}(\Type{unw\_addr\_space\_t} \Var{as}, \Type{size\_t} \Var{size}, \Type{int} \Var{flag});\\
+
+\section{Description}
+
+The \Func{unw\_set\_cache\_size}() routine sets the cache size of
+address space \Var{as} to hold at least as many items as given by
+argument \Var{size}. It may hold more items as determined by the
+implementation. To disable caching, call
+\Func{unw\_set\_caching\_policy}) with a policy of
+\Const{UNW\_CACHE\_NONE}. Flag is currently unused and must be 0.
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_set\_cache\_size}() returns 0.
+Otherwise the negative value of one of the error-codes below is
+returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_set\_cache\_size}() is thread-safe but \emph{not} safe
+to use from a signal handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_ENOMEM}] The desired cache size could not be
+ established because the application is out of memory.
+\end{Description}
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_create\_addr\_space(3)},
+\SeeAlso{unw\_set\_caching\_policy(3)},
+\SeeAlso{unw\_flush\_cache(3)}
+
+\section{Author}
+
+\noindent
+Dave Watson\\
+Email: \Email{dade.watson@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_set_caching_policy.man b/src/pal/src/libunwind/doc/unw_set_caching_policy.man
new file mode 100644
index 0000000000..4862ea545e
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_set_caching_policy.man
@@ -0,0 +1,119 @@
+'\" t
+.\" Manual page created with latex2man on Fri Dec 2 16:09:33 PST 2016
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_SET\\_CACHING\\_POLICY" "3" "02 December 2016" "Programming Library " "Programming Library "
+.SH NAME
+unw_set_caching_policy
+\-\- set unwind caching policy
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_set_caching_policy(unw_addr_space_t
+as,
+unw_caching_policy_t
+policy);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_set_caching_policy()
+routine sets the caching policy
+of address space as
+to the policy specified by argument
+policy\&.
+The policy
+argument can take one of three
+possible values:
+.TP
+UNW_CACHE_NONE
+ Turns off caching completely. This
+also implicitly flushes the contents of all caches as if
+unw_flush_cache()
+had been called.
+.TP
+UNW_CACHE_GLOBAL
+ Enables caching using a global cache
+that is shared by all threads. If global caching is unavailable or
+unsupported, libunwind
+may fall back on using a per\-thread
+cache, as if UNW_CACHE_PER_THREAD
+had been specified.
+.TP
+UNW_CACHE_PER_THREAD
+ Enables caching using
+thread\-local caches. If a thread\-local caching are unavailable or
+unsupported, libunwind
+may fall back on using a global cache,
+as if UNW_CACHE_GLOBAL
+had been specified.
+.PP
+If caching is enabled, an application must be prepared to make
+appropriate calls to unw_flush_cache()
+whenever the target
+changes in a way that could affect the validity of cached information.
+For example, after unloading (removing) a shared library,
+unw_flush_cache()
+would have to be called (at least) for the
+address\-range that was covered by the shared library.
+.PP
+For address spaces created via unw_create_addr_space(3),
+caching is turned off by default. For the local address space
+unw_local_addr_space,
+caching is turned on by default.
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_set_caching_policy()
+returns 0.
+Otherwise the negative value of one of the error\-codes below is
+returned.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_set_caching_policy()
+is thread\-safe but \fInot\fP
+safe
+to use from a signal handler.
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_ENOMEM
+ The desired caching policy could not be
+established because the application is out of memory.
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_create_addr_space(3),
+unw_set_cache_size(3),
+unw_flush_cache(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_set_caching_policy.tex b/src/pal/src/libunwind/doc/unw_set_caching_policy.tex
new file mode 100644
index 0000000000..3a4b07e84a
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_set_caching_policy.tex
@@ -0,0 +1,81 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_set\_caching\_policy}{David Mosberger-Tang}{Programming Library}{unw\_set\_caching\_policy}unw\_set\_caching\_policy -- set unwind caching policy
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_set\_caching\_policy}(\Type{unw\_addr\_space\_t} \Var{as}, \Type{unw\_caching\_policy\_t} \Var{policy});\\
+
+\section{Description}
+
+The \Func{unw\_set\_caching\_policy}() routine sets the caching policy
+of address space \Var{as} to the policy specified by argument
+\Var{policy}. The \Var{policy} argument can take one of three
+possible values:
+\begin{description}
+\item[\Const{UNW\_CACHE\_NONE}] Turns off caching completely. This
+ also implicitly flushes the contents of all caches as if
+ \Func{unw\_flush\_cache}() had been called.
+\item[\Const{UNW\_CACHE\_GLOBAL}] Enables caching using a global cache
+ that is shared by all threads. If global caching is unavailable or
+ unsupported, \Prog{libunwind} may fall back on using a per-thread
+ cache, as if \Const{UNW\_CACHE\_PER\_THREAD} had been specified.
+\item[\Const{UNW\_CACHE\_PER\_THREAD}] Enables caching using
+ thread-local caches. If a thread-local caching are unavailable or
+ unsupported, \Prog{libunwind} may fall back on using a global cache,
+ as if \Const{UNW\_CACHE\_GLOBAL} had been specified.
+\end{description}
+
+If caching is enabled, an application must be prepared to make
+appropriate calls to \Func{unw\_flush\_cache}() whenever the target
+changes in a way that could affect the validity of cached information.
+For example, after unloading (removing) a shared library,
+\Func{unw\_flush\_cache}() would have to be called (at least) for the
+address-range that was covered by the shared library.
+
+For address spaces created via \Func{unw\_create\_addr\_space}(3),
+caching is turned off by default. For the local address space
+\Func{unw\_local\_addr\_space}, caching is turned on by default.
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_set\_caching\_policy}() returns 0.
+Otherwise the negative value of one of the error-codes below is
+returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_set\_caching\_policy}() is thread-safe but \emph{not} safe
+to use from a signal handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_ENOMEM}] The desired caching policy could not be
+ established because the application is out of memory.
+\end{Description}
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_create\_addr\_space(3)},
+\SeeAlso{unw\_set\_cache\_size(3)},
+\SeeAlso{unw\_flush\_cache(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_set_fpreg.man b/src/pal/src/libunwind/doc/unw_set_fpreg.man
new file mode 100644
index 0000000000..6cefa54623
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_set_fpreg.man
@@ -0,0 +1,117 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_SET\\_FPREG" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+unw_set_fpreg
+\-\- set contents of floating\-point register
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_set_fpreg(unw_cursor_t *cp,
+unw_regnum_t
+reg,
+unw_fpreg_t
+val);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_set_fpreg()
+routine sets the value of register
+reg
+in the stack frame identified by cursor cp
+to the
+value passed in val\&.
+.PP
+The register numbering is target\-dependent and described in separate
+manual pages (e.g., libunwind\-ia64(3) for the IA\-64 target).
+Furthermore, the exact set of accessible registers may depend on the
+type of frame that cp
+is referring to. For ordinary stack
+frames, it is normally possible to access only the preserved
+(``callee\-saved\&'') registers and frame\-related registers (such as the
+stack\-pointer). However, for signal frames (see
+unw_is_signal_frame(3)),
+it is usually possible to access
+all registers.
+.PP
+Note that unw_set_fpreg()
+can only write the contents of
+floating\-point registers. See unw_set_reg(3)
+for a way to
+write registers which fit in a single word.
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_set_fpreg()
+returns 0.
+Otherwise the negative value of one of the error\-codes below is
+returned.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_set_fpreg()
+is thread\-safe as well as safe to use
+from a signal handler.
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_EUNSPEC
+ An unspecified error occurred.
+.TP
+UNW_EBADREG
+ An attempt was made to write a register
+that is either invalid or not accessible in the current frame.
+.TP
+UNW_EREADONLY
+ An attempt was made to write to a
+read\-only register.
+.PP
+In addition, unw_set_fpreg()
+may return any error returned by
+the access_mem(),
+access_reg(),
+and
+access_fpreg()
+call\-backs (see
+unw_create_addr_space(3)).
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+libunwind\-ia64(3),
+unw_get_fpreg(3),
+unw_is_fpreg(3),
+unw_is_signal_frame(3),
+unw_set_reg(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_set_fpreg.tex b/src/pal/src/libunwind/doc/unw_set_fpreg.tex
new file mode 100644
index 0000000000..aaf7fb25a7
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_set_fpreg.tex
@@ -0,0 +1,79 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_set\_fpreg}{David Mosberger-Tang}{Programming Library}{unw\_set\_fpreg}unw\_set\_fpreg -- set contents of floating-point register
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_set\_fpreg}(\Type{unw\_cursor\_t~*}\Var{cp}, \Type{unw\_regnum\_t} \Var{reg}, \Type{unw\_fpreg\_t} \Var{val});\\
+
+\section{Description}
+
+The \Func{unw\_set\_fpreg}() routine sets the value of register
+\Var{reg} in the stack frame identified by cursor \Var{cp} to the
+value passed in \Var{val}.
+
+The register numbering is target-dependent and described in separate
+manual pages (e.g., libunwind-ia64(3) for the IA-64 target).
+Furthermore, the exact set of accessible registers may depend on the
+type of frame that \Var{cp} is referring to. For ordinary stack
+frames, it is normally possible to access only the preserved
+(``callee-saved'') registers and frame-related registers (such as the
+stack-pointer). However, for signal frames (see
+\Func{unw\_is\_signal\_frame}(3)), it is usually possible to access
+all registers.
+
+Note that \Func{unw\_set\_fpreg}() can only write the contents of
+floating-point registers. See \Func{unw\_set\_reg}(3) for a way to
+write registers which fit in a single word.
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_set\_fpreg}() returns 0.
+Otherwise the negative value of one of the error-codes below is
+returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_set\_fpreg}() is thread-safe as well as safe to use
+from a signal handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred.
+\item[\Const{UNW\_EBADREG}] An attempt was made to write a register
+ that is either invalid or not accessible in the current frame.
+\item[\Const{UNW\_EREADONLY}] An attempt was made to write to a
+ read-only register.
+\end{Description}
+In addition, \Func{unw\_set\_fpreg}() may return any error returned by
+the \Func{access\_mem}(), \Func{access\_reg}(), and
+\Func{access\_fpreg}() call-backs (see
+\Func{unw\_create\_addr\_space}(3)).
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{libunwind-ia64(3)},
+\SeeAlso{unw\_get\_fpreg(3)},
+\SeeAlso{unw\_is\_fpreg(3)},
+\SeeAlso{unw\_is\_signal\_frame(3)},
+\SeeAlso{unw\_set\_reg(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_set_reg.man b/src/pal/src/libunwind/doc/unw_set_reg.man
new file mode 100644
index 0000000000..5d57045f74
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_set_reg.man
@@ -0,0 +1,117 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_SET\\_REG" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+unw_set_reg
+\-\- set register contents
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_set_reg(unw_cursor_t *cp,
+unw_regnum_t
+reg,
+unw_word_t
+val);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_set_reg()
+routine sets the value of register
+reg
+in the stack frame identified by cursor cp
+to the
+value passed in val\&.
+.PP
+The register numbering is target\-dependent and described in separate
+manual pages (e.g., libunwind\-ia64(3) for the IA\-64 target).
+Furthermore, the exact set of accessible registers may depend on the
+type of frame that cp
+is referring to. For ordinary stack
+frames, it is normally possible to access only the preserved
+(``callee\-saved\&'') registers and frame\-related registers (such as the
+stack\-pointer). However, for signal frames (see
+unw_is_signal_frame(3)),
+it is usually possible to access
+all registers.
+.PP
+Note that unw_set_reg()
+can only write the contents of
+registers whose values fit in a single word. See
+unw_set_fpreg(3)
+for a way to write registers which do not
+fit this constraint.
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_set_reg()
+returns 0.
+Otherwise the negative value of one of the error\-codes below is
+returned.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_set_reg()
+is thread\-safe as well as safe to use
+from a signal handler.
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_EUNSPEC
+ An unspecified error occurred.
+.TP
+UNW_EBADREG
+ An attempt was made to write a register
+that is either invalid or not accessible in the current frame.
+.TP
+UNW_EREADONLY
+ An attempt was made to write to a
+read\-only register.
+.PP
+In addition, unw_set_reg()
+may return any error returned by
+the access_mem(),
+access_reg(),
+and
+access_fpreg()
+call\-backs (see
+unw_create_addr_space(3)).
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+libunwind\-ia64(3),
+unw_get_reg(3),
+unw_is_signal_frame(3),
+unw_set_fpreg(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_set_reg.tex b/src/pal/src/libunwind/doc/unw_set_reg.tex
new file mode 100644
index 0000000000..2421846be5
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_set_reg.tex
@@ -0,0 +1,79 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_set\_reg}{David Mosberger-Tang}{Programming Library}{unw\_set\_reg}unw\_set\_reg -- set register contents
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_set\_reg}(\Type{unw\_cursor\_t~*}\Var{cp}, \Type{unw\_regnum\_t} \Var{reg}, \Type{unw\_word\_t} \Var{val});\\
+
+\section{Description}
+
+The \Func{unw\_set\_reg}() routine sets the value of register
+\Var{reg} in the stack frame identified by cursor \Var{cp} to the
+value passed in \Var{val}.
+
+The register numbering is target-dependent and described in separate
+manual pages (e.g., libunwind-ia64(3) for the IA-64 target).
+Furthermore, the exact set of accessible registers may depend on the
+type of frame that \Var{cp} is referring to. For ordinary stack
+frames, it is normally possible to access only the preserved
+(``callee-saved'') registers and frame-related registers (such as the
+stack-pointer). However, for signal frames (see
+\Func{unw\_is\_signal\_frame}(3)), it is usually possible to access
+all registers.
+
+Note that \Func{unw\_set\_reg}() can only write the contents of
+registers whose values fit in a single word. See
+\Func{unw\_set\_fpreg}(3) for a way to write registers which do not
+fit this constraint.
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_set\_reg}() returns 0.
+Otherwise the negative value of one of the error-codes below is
+returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_set\_reg}() is thread-safe as well as safe to use
+from a signal handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred.
+\item[\Const{UNW\_EBADREG}] An attempt was made to write a register
+ that is either invalid or not accessible in the current frame.
+\item[\Const{UNW\_EREADONLY}] An attempt was made to write to a
+ read-only register.
+\end{Description}
+In addition, \Func{unw\_set\_reg}() may return any error returned by
+the \Func{access\_mem}(), \Func{access\_reg}(), and
+\Func{access\_fpreg}() call-backs (see
+\Func{unw\_create\_addr\_space}(3)).
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{libunwind-ia64(3)},
+\SeeAlso{unw\_get\_reg(3)},
+\SeeAlso{unw\_is\_signal\_frame(3)},
+\SeeAlso{unw\_set\_fpreg(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_step.man b/src/pal/src/libunwind/doc/unw_step.man
new file mode 100644
index 0000000000..54da1b2f3d
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_step.man
@@ -0,0 +1,106 @@
+'\" t
+.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_STEP" "3" "16 August 2007" "Programming Library " "Programming Library "
+.SH NAME
+unw_step
+\-\- advance to next stack frame
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_step(unw_cursor_t *cp);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_step()
+routine advances the unwind cursor cp
+to
+the next older, less deeply nested stack frame.
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_step()
+returns a positive value
+if the updated cursor refers to a valid stack frame, or 0 if the
+previous stack frame was the last frame in the chain. On error, the
+negative value of one of the error\-codes below is returned.
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_step()
+is thread\-safe. If cursor cp
+is in the local
+address\-space, this routine is also safe to use from a signal handler.
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_EUNSPEC
+ An unspecified error occurred.
+.TP
+UNW_ENOINFO
+ Libunwind
+was unable to locate the
+unwind\-info needed to complete the operation.
+.TP
+UNW_EBADVERSION
+ The unwind\-info needed to complete the
+operation has a version or a format that is not understood by
+libunwind\&.
+.TP
+UNW_EINVALIDIP
+ The instruction\-pointer
+(``program\-counter\&'') of the next stack frame is invalid (e.g., not
+properly aligned).
+.TP
+UNW_EBADFRAME
+ The next stack frame is invalid.
+.TP
+UNW_ESTOPUNWIND
+ Returned if a call to
+find_proc_info()
+returned \-UNW_ESTOPUNWIND\&.
+.PP
+In addition, unw_step()
+may return any error returned by the
+find_proc_info(),
+get_dyn_info_list_addr(),
+access_mem(),
+access_reg(),
+or access_fpreg()
+call\-backs (see unw_create_addr_space(3)).
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_create_addr_space(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_step.tex b/src/pal/src/libunwind/doc/unw_step.tex
new file mode 100644
index 0000000000..106bd9ba99
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_step.tex
@@ -0,0 +1,68 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_step}{David Mosberger-Tang}{Programming Library}{unw\_step}unw\_step -- advance to next stack frame
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_step}(\Type{unw\_cursor\_t~*}\Var{cp});\\
+
+\section{Description}
+
+The \Func{unw\_step}() routine advances the unwind cursor \Var{cp} to
+the next older, less deeply nested stack frame.
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_step}() returns a positive value
+if the updated cursor refers to a valid stack frame, or 0 if the
+previous stack frame was the last frame in the chain. On error, the
+negative value of one of the error-codes below is returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_step}() is thread-safe. If cursor \Var{cp} is in the local
+address-space, this routine is also safe to use from a signal handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred.
+\item[\Const{UNW\_ENOINFO}] \Prog{Libunwind} was unable to locate the
+ unwind-info needed to complete the operation.
+\item[\Const{UNW\_EBADVERSION}] The unwind-info needed to complete the
+ operation has a version or a format that is not understood by
+ \Prog{libunwind}.
+\item[\Const{UNW\_EINVALIDIP}] The instruction-pointer
+ (``program-counter'') of the next stack frame is invalid (e.g., not
+ properly aligned).
+\item[\Const{UNW\_EBADFRAME}] The next stack frame is invalid.
+\item[\Const{UNW\_ESTOPUNWIND}] Returned if a call to
+ \Func{find\_proc\_info}() returned -\Const{UNW\_ESTOPUNWIND}.
+\end{Description}
+In addition, \Func{unw\_step}() may return any error returned by the
+\Func{find\_proc\_info}(), \Func{get\_dyn\_info\_list\_addr}(),
+\Func{access\_mem}(), \Func{access\_reg}(), or \Func{access\_fpreg}()
+call-backs (see \Func{unw\_create\_addr\_space}(3)).
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_create\_addr\_space(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/doc/unw_strerror.man b/src/pal/src/libunwind/doc/unw_strerror.man
new file mode 100644
index 0000000000..467c44d262
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_strerror.man
@@ -0,0 +1,63 @@
+'\" t
+.\" Manual page created with latex2man on Wed Aug 18 16:51:29 CEST 2004
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_STRERROR" "3" "18 August 2004" "Programming Library " "Programming Library "
+.SH NAME
+unw_strerror
+\-\- get text corresponding to error code
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+const char *
+unw_strerror(int
+err_code);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_strerror()
+routine maps the (negative) err_code
+to a corresponding text message and returns it.
+.PP
+.SH RETURN VALUE
+
+.PP
+The message that corresponds to err_code
+or, if the
+err_code
+has no corresponding message, the text "invalid error
+code".
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_strerror()
+is thread\-safe as well as safe to use
+from a signal handler.
+.PP
+.SH AUTHOR
+
+.PP
+Thomas Hallgren
+.br
+BEA Systems
+.br
+Stockholm, Sweden
+.br
+Email: \fBthallgre@bea.com\fP
+.br
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/src/pal/src/libunwind/doc/unw_strerror.tex b/src/pal/src/libunwind/doc/unw_strerror.tex
new file mode 100644
index 0000000000..7cad011768
--- /dev/null
+++ b/src/pal/src/libunwind/doc/unw_strerror.tex
@@ -0,0 +1,42 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_strerror}{Thomas Hallgren}{Programming Library}{unw\_strerror}unw\_strerror -- get text corresponding to error code
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{const char *} \Func{unw\_strerror}(\Type{int} \Var{err\_code});\\
+
+\section{Description}
+
+The \Func{unw\_strerror}() routine maps the (negative) \Var{err\_code}
+to a corresponding text message and returns it.
+
+\section{Return Value}
+
+The message that corresponds to \Var{err\_code} or, if the
+\Var{err\_code} has no corresponding message, the text "invalid error
+code".
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_strerror}() is thread-safe as well as safe to use
+from a signal handler.
+
+\section{Author}
+
+\noindent
+Thomas Hallgren\\
+BEA Systems\\
+Stockholm, Sweden\\
+Email: \Email{thallgre@bea.com}\\
+\LatexManEnd
+
+\end{document}
diff --git a/src/pal/src/libunwind/include/compiler.h b/src/pal/src/libunwind/include/compiler.h
new file mode 100644
index 0000000000..2fa59eff7f
--- /dev/null
+++ b/src/pal/src/libunwind/include/compiler.h
@@ -0,0 +1,72 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2005 Hewlett-Packard Co
+ Copyright (C) 2007 David Mosberger-Tang
+ Contributed by David Mosberger-Tang <dmosberger@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Compiler specific useful bits that are used in libunwind, and also in the
+ * tests. */
+
+#ifndef COMPILER_H
+#define COMPILER_H
+
+#ifdef __GNUC__
+# define ALIGNED(x) __attribute__((aligned(x)))
+# define CONST_ATTR __attribute__((__const__))
+# define UNUSED __attribute__((unused))
+# define NOINLINE __attribute__((noinline))
+# define NORETURN __attribute__((noreturn))
+# define ALIAS2(name) #name
+# define ALIAS(name) __attribute__((alias (ALIAS2(name))))
+# if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+# define ALWAYS_INLINE inline __attribute__((always_inline))
+# define HIDDEN __attribute__((visibility ("hidden")))
+# else
+# define ALWAYS_INLINE
+# define HIDDEN
+# endif
+# define WEAK __attribute__((weak))
+# if (__GNUC__ >= 3)
+# define likely(x) __builtin_expect ((x), 1)
+# define unlikely(x) __builtin_expect ((x), 0)
+# else
+# define likely(x) (x)
+# define unlikely(x) (x)
+# endif
+#else
+# define ALIGNED(x)
+# define ALWAYS_INLINE
+# define CONST_ATTR
+# define UNUSED
+# define NOINLINE
+# define NORETURN
+# define ALIAS(name)
+# define HIDDEN
+# define WEAK
+# define likely(x) (x)
+# define unlikely(x) (x)
+#endif
+
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
+
+#endif /* COMPILER_H */
diff --git a/src/pal/src/libunwind/include/dwarf-eh.h b/src/pal/src/libunwind/include/dwarf-eh.h
new file mode 100644
index 0000000000..e03750760c
--- /dev/null
+++ b/src/pal/src/libunwind/include/dwarf-eh.h
@@ -0,0 +1,128 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef dwarf_eh_h
+#define dwarf_eh_h
+
+#include "dwarf.h"
+
+/* This header file defines the format of a DWARF exception-header
+ section (.eh_frame_hdr, pointed to by program-header
+ PT_GNU_EH_FRAME). The exception-header is self-describing in the
+ sense that the format of the addresses contained in it is expressed
+ as a one-byte type-descriptor called a "pointer-encoding" (PE).
+
+ The exception header encodes the address of the .eh_frame section
+ and optionally contains a binary search table for the
+ Frame Descriptor Entries (FDEs) in the .eh_frame. The contents of
+ .eh_frame has the format described by the DWARF v3 standard
+ (http://www.eagercon.com/dwarf/dwarf3std.htm), except that code
+ addresses may be encoded in different ways. Also, .eh_frame has
+ augmentations that allow encoding a language-specific data-area
+ (LSDA) pointer and a pointer to a personality-routine.
+
+ Details:
+
+ The Common Information Entry (CIE) associated with an FDE may
+ contain an augmentation string. Each character in this string has
+ a specific meaning and either one or two associated operands. The
+ operands are stored in an augmentation body which appears right
+ after the "return_address_register" member and before the
+ "initial_instructions" member. The operands appear in the order
+ in which the characters appear in the string. For example, if the
+ augmentation string is "zL", the operand for 'z' would be first in
+ the augmentation body and the operand for 'L' would be second.
+ The following characters are supported for the CIE augmentation
+ string:
+
+ 'z': The operand for this character is a uleb128 value that gives the
+ length of the CIE augmentation body, not counting the length
+ of the uleb128 operand itself. If present, this code must
+ appear as the first character in the augmentation body.
+
+ 'L': Indicates that the FDE's augmentation body contains an LSDA
+ pointer. The operand for this character is a single byte
+ that specifies the pointer-encoding (PE) that is used for
+ the LSDA pointer.
+
+ 'R': Indicates that the code-pointers (FDE members
+ "initial_location" and "address_range" and the operand for
+ DW_CFA_set_loc) in the FDE have a non-default encoding. The
+ operand for this character is a single byte that specifies
+ the pointer-encoding (PE) that is used for the
+ code-pointers. Note: the "address_range" member is always
+ encoded as an absolute value. Apart from that, the specified
+ FDE pointer-encoding applies.
+
+ 'P': Indicates the presence of a personality routine (handler).
+ The first operand for this character specifies the
+ pointer-encoding (PE) that is used for the second operand,
+ which specifies the address of the personality routine.
+
+ If the augmentation string contains any other characters, the
+ remainder of the augmentation string should be ignored.
+ Furthermore, if the size of the augmentation body is unknown
+ (i.e., 'z' is not the first character of the augmentation string),
+ then the entire CIE as well all associated FDEs must be ignored.
+
+ A Frame Descriptor Entries (FDE) may contain an augmentation body
+ which, if present, appears right after the "address_range" member
+ and before the "instructions" member. The contents of this body
+ is implicitly defined by the augmentation string of the associated
+ CIE. The meaning of the characters in the CIE's augmentation
+ string as far as FDEs are concerned is as follows:
+
+ 'z': The first operand in the FDE's augmentation body specifies
+ the total length of the augmentation body as a uleb128 (not
+ counting the length of the uleb128 operand itself).
+
+ 'L': The operand for this character is an LSDA pointer, encoded
+ in the format specified by the corresponding operand in the
+ CIE's augmentation body.
+
+*/
+
+#define DW_EH_VERSION 1 /* The version we're implementing */
+
+struct __attribute__((packed)) dwarf_eh_frame_hdr
+ {
+ unsigned char version;
+ unsigned char eh_frame_ptr_enc;
+ unsigned char fde_count_enc;
+ unsigned char table_enc;
+ Elf_W (Addr) eh_frame;
+ /* The rest of the header is variable-length and consists of the
+ following members:
+
+ encoded_t fde_count;
+ struct
+ {
+ encoded_t start_ip; // first address covered by this FDE
+ encoded_t fde_addr; // address of the FDE
+ }
+ binary_search_table[fde_count]; */
+ };
+
+#endif /* dwarf_eh_h */
diff --git a/src/pal/src/libunwind/include/dwarf.h b/src/pal/src/libunwind/include/dwarf.h
new file mode 100644
index 0000000000..fab93c6145
--- /dev/null
+++ b/src/pal/src/libunwind/include/dwarf.h
@@ -0,0 +1,450 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef dwarf_h
+#define dwarf_h
+
+#include <libunwind.h>
+
+struct dwarf_cursor; /* forward-declaration */
+struct elf_dyn_info;
+
+#include "dwarf-config.h"
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifndef UNW_REMOTE_ONLY
+ #if defined(HAVE_LINK_H)
+ #include <link.h>
+ #elif defined(HAVE_SYS_LINK_H)
+ #include <sys/link.h>
+ #else
+ #error Could not find <link.h>
+ #endif
+#endif
+
+#include <pthread.h>
+
+/* DWARF expression opcodes. */
+
+typedef enum
+ {
+ DW_OP_addr = 0x03,
+ DW_OP_deref = 0x06,
+ DW_OP_const1u = 0x08,
+ DW_OP_const1s = 0x09,
+ DW_OP_const2u = 0x0a,
+ DW_OP_const2s = 0x0b,
+ DW_OP_const4u = 0x0c,
+ DW_OP_const4s = 0x0d,
+ DW_OP_const8u = 0x0e,
+ DW_OP_const8s = 0x0f,
+ DW_OP_constu = 0x10,
+ DW_OP_consts = 0x11,
+ DW_OP_dup = 0x12,
+ DW_OP_drop = 0x13,
+ DW_OP_over = 0x14,
+ DW_OP_pick = 0x15,
+ 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,
+ DW_OP_shl = 0x24,
+ DW_OP_shr = 0x25,
+ DW_OP_shra = 0x26,
+ DW_OP_xor = 0x27,
+ DW_OP_skip = 0x2f,
+ DW_OP_bra = 0x28,
+ 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,
+ DW_OP_lit1, DW_OP_lit2, DW_OP_lit3, DW_OP_lit4, DW_OP_lit5,
+ DW_OP_lit6, DW_OP_lit7, DW_OP_lit8, DW_OP_lit9, DW_OP_lit10,
+ DW_OP_lit11, DW_OP_lit12, DW_OP_lit13, DW_OP_lit14, DW_OP_lit15,
+ DW_OP_lit16, DW_OP_lit17, DW_OP_lit18, DW_OP_lit19, DW_OP_lit20,
+ DW_OP_lit21, DW_OP_lit22, DW_OP_lit23, DW_OP_lit24, DW_OP_lit25,
+ DW_OP_lit26, DW_OP_lit27, DW_OP_lit28, DW_OP_lit29, DW_OP_lit30,
+ DW_OP_lit31,
+ DW_OP_reg0 = 0x50,
+ DW_OP_reg1, DW_OP_reg2, DW_OP_reg3, DW_OP_reg4, DW_OP_reg5,
+ DW_OP_reg6, DW_OP_reg7, DW_OP_reg8, DW_OP_reg9, DW_OP_reg10,
+ DW_OP_reg11, DW_OP_reg12, DW_OP_reg13, DW_OP_reg14, DW_OP_reg15,
+ DW_OP_reg16, DW_OP_reg17, DW_OP_reg18, DW_OP_reg19, DW_OP_reg20,
+ DW_OP_reg21, DW_OP_reg22, DW_OP_reg23, DW_OP_reg24, DW_OP_reg25,
+ DW_OP_reg26, DW_OP_reg27, DW_OP_reg28, DW_OP_reg29, DW_OP_reg30,
+ DW_OP_reg31,
+ DW_OP_breg0 = 0x70,
+ DW_OP_breg1, DW_OP_breg2, DW_OP_breg3, DW_OP_breg4, DW_OP_breg5,
+ DW_OP_breg6, DW_OP_breg7, DW_OP_breg8, DW_OP_breg9, DW_OP_breg10,
+ DW_OP_breg11, DW_OP_breg12, DW_OP_breg13, DW_OP_breg14, DW_OP_breg15,
+ DW_OP_breg16, DW_OP_breg17, DW_OP_breg18, DW_OP_breg19, DW_OP_breg20,
+ DW_OP_breg21, DW_OP_breg22, DW_OP_breg23, DW_OP_breg24, DW_OP_breg25,
+ DW_OP_breg26, DW_OP_breg27, DW_OP_breg28, DW_OP_breg29, DW_OP_breg30,
+ DW_OP_breg31,
+ DW_OP_regx = 0x90,
+ DW_OP_fbreg = 0x91,
+ DW_OP_bregx = 0x92,
+ DW_OP_piece = 0x93,
+ DW_OP_deref_size = 0x94,
+ DW_OP_xderef_size = 0x95,
+ DW_OP_nop = 0x96,
+ DW_OP_push_object_address = 0x97,
+ DW_OP_call2 = 0x98,
+ DW_OP_call4 = 0x99,
+ DW_OP_call_ref = 0x9a,
+ DW_OP_lo_user = 0xe0,
+ DW_OP_hi_user = 0xff
+ }
+dwarf_expr_op_t;
+
+#define DWARF_CIE_VERSION 3
+#define DWARF_CIE_VERSION_MAX 4
+
+#define DWARF_CFA_OPCODE_MASK 0xc0
+#define DWARF_CFA_OPERAND_MASK 0x3f
+
+typedef enum
+ {
+ DW_CFA_advance_loc = 0x40,
+ DW_CFA_offset = 0x80,
+ DW_CFA_restore = 0xc0,
+ DW_CFA_nop = 0x00,
+ DW_CFA_set_loc = 0x01,
+ DW_CFA_advance_loc1 = 0x02,
+ DW_CFA_advance_loc2 = 0x03,
+ DW_CFA_advance_loc4 = 0x04,
+ DW_CFA_offset_extended = 0x05,
+ DW_CFA_restore_extended = 0x06,
+ DW_CFA_undefined = 0x07,
+ DW_CFA_same_value = 0x08,
+ DW_CFA_register = 0x09,
+ DW_CFA_remember_state = 0x0a,
+ DW_CFA_restore_state = 0x0b,
+ DW_CFA_def_cfa = 0x0c,
+ DW_CFA_def_cfa_register = 0x0d,
+ DW_CFA_def_cfa_offset = 0x0e,
+ DW_CFA_def_cfa_expression = 0x0f,
+ 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_expression = 0x16,
+ DW_CFA_lo_user = 0x1c,
+ DW_CFA_MIPS_advance_loc8 = 0x1d,
+ DW_CFA_GNU_window_save = 0x2d,
+ DW_CFA_GNU_args_size = 0x2e,
+ DW_CFA_GNU_negative_offset_extended = 0x2f,
+ DW_CFA_hi_user = 0x3c
+ }
+dwarf_cfa_t;
+
+/* DWARF Pointer-Encoding (PEs).
+
+ Pointer-Encodings were invented for the GCC exception-handling
+ support for C++, but they represent a rather generic way of
+ describing the format in which an address/pointer is stored and
+ hence we include the definitions here, in the main dwarf.h file.
+ The Pointer-Encoding format is partially documented in Linux Base
+ Spec v1.3 (http://www.linuxbase.org/spec/). The rest is reverse
+ engineered from GCC.
+
+*/
+#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */
+#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */
+/* Flag bit. If set, the resulting pointer is the address of the word
+ that contains the final address. */
+#define DW_EH_PE_indirect 0x80
+
+/* Pointer-encoding formats: */
+#define DW_EH_PE_omit 0xff
+#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */
+#define DW_EH_PE_uleb128 0x01 /* unsigned LE base-128 value */
+#define DW_EH_PE_udata2 0x02 /* unsigned 16-bit value */
+#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */
+#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */
+#define DW_EH_PE_sleb128 0x09 /* signed LE base-128 value */
+#define DW_EH_PE_sdata2 0x0a /* signed 16-bit value */
+#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */
+#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */
+
+/* Pointer-encoding application: */
+#define DW_EH_PE_absptr 0x00 /* absolute value */
+#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */
+#define DW_EH_PE_textrel 0x20 /* text-relative (GCC-specific???) */
+#define DW_EH_PE_datarel 0x30 /* data-relative */
+/* The following are not documented by LSB v1.3, yet they are used by
+ GCC, presumably they aren't documented by LSB since they aren't
+ used on Linux: */
+#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */
+#define DW_EH_PE_aligned 0x50 /* aligned pointer */
+
+extern struct mempool dwarf_reg_state_pool;
+extern struct mempool dwarf_cie_info_pool;
+
+typedef enum
+ {
+ DWARF_WHERE_UNDEF, /* register isn't saved at all */
+ DWARF_WHERE_SAME, /* register has same value as in prev. frame */
+ DWARF_WHERE_CFAREL, /* register saved at CFA-relative address */
+ DWARF_WHERE_REG, /* register saved in another register */
+ DWARF_WHERE_EXPR, /* register saved */
+ DWARF_WHERE_VAL_EXPR, /* register has computed value */
+ }
+dwarf_where_t;
+
+/* For uniformity, we'd like to treat the CFA save-location like any
+ other register save-location, but this doesn't quite work, because
+ the CFA can be expressed as a (REGISTER,OFFSET) pair. To handle
+ this, we use two dwarf_save_loc structures to describe the CFA.
+ The first one (CFA_REG_COLUMN), tells us where the CFA is saved.
+ In the case of DWARF_WHERE_EXPR, the CFA is defined by a DWARF
+ location expression whose address is given by member "val". In the
+ case of DWARF_WHERE_REG, member "val" gives the number of the
+ base-register and the "val" member of DWARF_CFA_OFF_COLUMN gives
+ the offset value. */
+#define DWARF_CFA_REG_COLUMN DWARF_NUM_PRESERVED_REGS
+#define DWARF_CFA_OFF_COLUMN (DWARF_NUM_PRESERVED_REGS + 1)
+
+typedef struct dwarf_reg_only_state
+ {
+ char where[DWARF_NUM_PRESERVED_REGS + 2]; /* how is the register saved? */
+ unw_word_t val[DWARF_NUM_PRESERVED_REGS + 2]; /* where it's saved */
+ }
+dwarf_reg_only_state_t;
+
+typedef struct dwarf_reg_state
+ {
+ unw_word_t ret_addr_column; /* which column in rule table represents return address */
+ dwarf_reg_only_state_t reg;
+ }
+dwarf_reg_state_t;
+
+typedef struct dwarf_stackable_reg_state
+ {
+ struct dwarf_stackable_reg_state *next; /* for rs_stack */
+ dwarf_reg_state_t state;
+ }
+dwarf_stackable_reg_state_t;
+
+typedef struct dwarf_reg_cache_entry
+ {
+ unw_word_t ip; /* ip this rs is for */
+ unsigned short coll_chain; /* used for hash collisions */
+ unsigned short hint; /* hint for next rs to try (or -1) */
+ unsigned short valid : 1; /* optional machine-dependent signal info */
+ unsigned short signal_frame : 1; /* optional machine-dependent signal info */
+ }
+dwarf_reg_cache_entry_t;
+
+typedef struct dwarf_cie_info
+ {
+ unw_word_t cie_instr_start; /* start addr. of CIE "initial_instructions" */
+ unw_word_t cie_instr_end; /* end addr. of CIE "initial_instructions" */
+ unw_word_t fde_instr_start; /* start addr. of FDE "instructions" */
+ unw_word_t fde_instr_end; /* end addr. of FDE "instructions" */
+ unw_word_t code_align; /* code-alignment factor */
+ unw_word_t data_align; /* data-alignment factor */
+ unw_word_t ret_addr_column; /* column of return-address register */
+ unw_word_t handler; /* address of personality-routine */
+ uint16_t abi;
+ uint16_t tag;
+ uint8_t fde_encoding;
+ uint8_t lsda_encoding;
+ unsigned int sized_augmentation : 1;
+ unsigned int have_abi_marker : 1;
+ unsigned int signal_frame : 1;
+ }
+dwarf_cie_info_t;
+
+typedef struct dwarf_state_record
+ {
+ unsigned char fde_encoding;
+ unw_word_t args_size;
+
+ dwarf_reg_state_t rs_initial; /* reg-state after CIE instructions */
+ dwarf_reg_state_t rs_current; /* current reg-state */
+ }
+dwarf_state_record_t;
+
+typedef struct dwarf_cursor
+ {
+ void *as_arg; /* argument to address-space callbacks */
+ unw_addr_space_t as; /* reference to per-address-space info */
+
+ unw_word_t cfa; /* canonical frame address; aka frame-/stack-pointer */
+ unw_word_t ip; /* instruction pointer */
+ unw_word_t args_size; /* size of arguments */
+ unw_word_t eh_args[UNW_TDEP_NUM_EH_REGS];
+ unsigned int eh_valid_mask;
+
+ dwarf_loc_t loc[DWARF_NUM_PRESERVED_REGS];
+
+ unsigned int stash_frames :1; /* stash frames for fast lookup */
+ unsigned int use_prev_instr :1; /* use previous (= call) or current (= signal) instruction? */
+ unsigned int pi_valid :1; /* is proc_info valid? */
+ unsigned int pi_is_dynamic :1; /* proc_info found via dynamic proc info? */
+ unw_proc_info_t pi; /* info about current procedure */
+
+ short hint; /* faster lookup of the rs cache */
+ short prev_rs;
+ }
+dwarf_cursor_t;
+
+#define DWARF_DEFAULT_LOG_UNW_CACHE_SIZE 7
+#define DWARF_DEFAULT_UNW_CACHE_SIZE (1 << DWARF_DEFAULT_LOG_UNW_CACHE_SIZE)
+
+#define DWARF_DEFAULT_LOG_UNW_HASH_SIZE (DWARF_DEFAULT_LOG_UNW_CACHE_SIZE + 1)
+#define DWARF_DEFAULT_UNW_HASH_SIZE (1 << DWARF_DEFAULT_LOG_UNW_HASH_SIZE)
+
+typedef unsigned char unw_hash_index_t;
+
+struct dwarf_rs_cache
+ {
+ pthread_mutex_t lock;
+ unsigned short rr_head; /* index of least-recently allocated rs */
+
+ unsigned short log_size;
+ unsigned short prev_log_size;
+
+ /* hash table that maps instruction pointer to rs index: */
+ unsigned short *hash;
+
+ uint32_t generation; /* generation number */
+
+ /* rs cache: */
+ dwarf_reg_state_t *buckets;
+ dwarf_reg_cache_entry_t *links;
+
+ /* default memory, loaded in BSS segment */
+ unsigned short default_hash[DWARF_DEFAULT_UNW_HASH_SIZE];
+ dwarf_reg_state_t default_buckets[DWARF_DEFAULT_UNW_CACHE_SIZE];
+ dwarf_reg_cache_entry_t default_links[DWARF_DEFAULT_UNW_CACHE_SIZE];
+ };
+
+/* A list of descriptors for loaded .debug_frame sections. */
+
+struct unw_debug_frame_list
+ {
+ /* The start (inclusive) and end (exclusive) of the described region. */
+ unw_word_t start;
+ unw_word_t end;
+ /* The debug frame itself. */
+ char *debug_frame;
+ size_t debug_frame_size;
+ /* Index (for binary search). */
+ struct table_entry *index;
+ size_t index_size;
+ /* Pointer to next descriptor. */
+ struct unw_debug_frame_list *next;
+ };
+
+/* Convenience macros: */
+#define dwarf_init UNW_ARCH_OBJ (dwarf_init)
+#define dwarf_callback UNW_OBJ (dwarf_callback)
+#define dwarf_find_proc_info UNW_OBJ (dwarf_find_proc_info)
+#define dwarf_find_debug_frame UNW_OBJ (dwarf_find_debug_frame)
+#define dwarf_search_unwind_table UNW_OBJ (dwarf_search_unwind_table)
+#define dwarf_find_unwind_table UNW_OBJ (dwarf_find_unwind_table)
+#define dwarf_put_unwind_info UNW_OBJ (dwarf_put_unwind_info)
+#define dwarf_put_unwind_info UNW_OBJ (dwarf_put_unwind_info)
+#define dwarf_eval_expr UNW_OBJ (dwarf_eval_expr)
+#define dwarf_stack_aligned UNW_OBJ (dwarf_stack_aligned)
+#define dwarf_extract_proc_info_from_fde \
+ UNW_OBJ (dwarf_extract_proc_info_from_fde)
+#define dwarf_find_save_locs UNW_OBJ (dwarf_find_save_locs)
+#define dwarf_make_proc_info UNW_OBJ (dwarf_make_proc_info)
+#define dwarf_apply_reg_state UNW_OBJ (dwarf_apply_reg_state)
+#define dwarf_reg_states_iterate UNW_OBJ (dwarf_reg_states_iterate)
+#define dwarf_read_encoded_pointer UNW_OBJ (dwarf_read_encoded_pointer)
+#define dwarf_step UNW_OBJ (dwarf_step)
+#define dwarf_flush_rs_cache UNW_OBJ (dwarf_flush_rs_cache)
+
+extern int dwarf_init (void);
+#ifndef UNW_REMOTE_ONLY
+extern int dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr);
+extern int dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
+ unw_proc_info_t *pi,
+ int need_unwind_info, void *arg);
+#endif /* !UNW_REMOTE_ONLY */
+extern int dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug,
+ unw_word_t ip, unw_word_t segbase,
+ const char* obj_name, unw_word_t start,
+ unw_word_t end);
+extern int dwarf_search_unwind_table (unw_addr_space_t as,
+ unw_word_t ip,
+ unw_dyn_info_t *di,
+ unw_proc_info_t *pi,
+ int need_unwind_info, void *arg);
+
+extern int dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
+ char *path, unw_word_t segbase, unw_word_t mapoff,
+ unw_word_t ip);
+extern void dwarf_put_unwind_info (unw_addr_space_t as,
+ unw_proc_info_t *pi, void *arg);
+extern int dwarf_eval_expr (struct dwarf_cursor *c, unw_word_t *addr,
+ unw_word_t len, unw_word_t *valp,
+ int *is_register);
+extern int
+dwarf_stack_aligned(struct dwarf_cursor *c, unw_word_t cfa_addr,
+ unw_word_t rbp_addr, unw_word_t *offset);
+
+extern int dwarf_extract_proc_info_from_fde (unw_addr_space_t as,
+ unw_accessors_t *a,
+ unw_word_t *fde_addr,
+ unw_proc_info_t *pi,
+ unw_word_t base,
+ int need_unwind_info,
+ int is_debug_frame,
+ void *arg);
+extern int dwarf_find_save_locs (struct dwarf_cursor *c);
+extern int dwarf_make_proc_info (struct dwarf_cursor *c);
+extern int dwarf_apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs);
+extern int dwarf_reg_states_iterate (struct dwarf_cursor *c, unw_reg_states_callback cb, void *token);
+extern int dwarf_read_encoded_pointer (unw_addr_space_t as,
+ unw_accessors_t *a,
+ unw_word_t *addr,
+ unsigned char encoding,
+ const unw_proc_info_t *pi,
+ unw_word_t *valp, void *arg);
+extern int dwarf_step (struct dwarf_cursor *c);
+extern int dwarf_flush_rs_cache (struct dwarf_rs_cache *cache);
+
+#endif /* dwarf_h */
diff --git a/src/pal/src/libunwind/include/dwarf_i.h b/src/pal/src/libunwind/include/dwarf_i.h
new file mode 100644
index 0000000000..983b9f5c2a
--- /dev/null
+++ b/src/pal/src/libunwind/include/dwarf_i.h
@@ -0,0 +1,490 @@
+#ifndef DWARF_I_H
+#define DWARF_I_H
+
+/* This file contains definitions that cannot be used in code outside
+ of libunwind. In particular, most inline functions are here
+ because otherwise they'd generate unresolved references when the
+ files are compiled with inlining disabled. */
+
+#include "dwarf.h"
+#include "libunwind_i.h"
+
+/* Unless we are told otherwise, assume that a "machine address" is
+ the size of an unw_word_t. */
+#ifndef dwarf_addr_size
+# define dwarf_addr_size(as) (sizeof (unw_word_t))
+#endif
+
+#ifndef dwarf_to_unw_regnum
+# define dwarf_to_unw_regnum_map UNW_OBJ (dwarf_to_unw_regnum_map)
+extern const uint8_t dwarf_to_unw_regnum_map[DWARF_REGNUM_MAP_LENGTH];
+/* REG is evaluated multiple times; it better be side-effects free! */
+# define dwarf_to_unw_regnum(reg) \
+ (((reg) < DWARF_REGNUM_MAP_LENGTH) ? dwarf_to_unw_regnum_map[reg] : 0)
+#endif
+
+#ifdef UNW_LOCAL_ONLY
+
+/* In the local-only case, we can let the compiler directly access
+ memory and don't need to worry about differing byte-order. */
+
+typedef union __attribute__ ((packed))
+ {
+ int8_t s8;
+ int16_t s16;
+ int32_t s32;
+ int64_t s64;
+ uint8_t u8;
+ uint16_t u16;
+ uint32_t u32;
+ uint64_t u64;
+ void *ptr;
+ }
+dwarf_misaligned_value_t;
+
+static inline int
+dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ int8_t *val, void *arg)
+{
+ dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
+
+ *val = mvp->s8;
+ *addr += sizeof (mvp->s8);
+ return 0;
+}
+
+static inline int
+dwarf_reads16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ int16_t *val, void *arg)
+{
+ dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
+
+ *val = mvp->s16;
+ *addr += sizeof (mvp->s16);
+ return 0;
+}
+
+static inline int
+dwarf_reads32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ int32_t *val, void *arg)
+{
+ dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
+
+ *val = mvp->s32;
+ *addr += sizeof (mvp->s32);
+ return 0;
+}
+
+static inline int
+dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ int64_t *val, void *arg)
+{
+ dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
+
+ *val = mvp->s64;
+ *addr += sizeof (mvp->s64);
+ return 0;
+}
+
+static inline int
+dwarf_readu8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ uint8_t *val, void *arg)
+{
+ dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
+
+ *val = mvp->u8;
+ *addr += sizeof (mvp->u8);
+ return 0;
+}
+
+static inline int
+dwarf_readu16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ uint16_t *val, void *arg)
+{
+ dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
+
+ *val = mvp->u16;
+ *addr += sizeof (mvp->u16);
+ return 0;
+}
+
+static inline int
+dwarf_readu32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ uint32_t *val, void *arg)
+{
+ dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
+
+ *val = mvp->u32;
+ *addr += sizeof (mvp->u32);
+ return 0;
+}
+
+static inline int
+dwarf_readu64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ uint64_t *val, void *arg)
+{
+ dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
+
+ *val = mvp->u64;
+ *addr += sizeof (mvp->u64);
+ return 0;
+}
+
+#else /* !UNW_LOCAL_ONLY */
+
+static inline int
+dwarf_readu8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ uint8_t *valp, void *arg)
+{
+ unw_word_t val, aligned_addr = *addr & -sizeof (unw_word_t);
+ unw_word_t off = *addr - aligned_addr;
+ int ret;
+
+ *addr += 1;
+ ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg);
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ val >>= 8*off;
+#else
+ val >>= 8*(sizeof (unw_word_t) - 1 - off);
+#endif
+ *valp = (uint8_t) val;
+ return ret;
+}
+
+static inline int
+dwarf_readu16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ uint16_t *val, void *arg)
+{
+ uint8_t v0, v1;
+ int ret;
+
+ if ((ret = dwarf_readu8 (as, a, addr, &v0, arg)) < 0
+ || (ret = dwarf_readu8 (as, a, addr, &v1, arg)) < 0)
+ return ret;
+
+ if (tdep_big_endian (as))
+ *val = (uint16_t) v0 << 8 | v1;
+ else
+ *val = (uint16_t) v1 << 8 | v0;
+ return 0;
+}
+
+static inline int
+dwarf_readu32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ uint32_t *val, void *arg)
+{
+ uint16_t v0, v1;
+ int ret;
+
+ if ((ret = dwarf_readu16 (as, a, addr, &v0, arg)) < 0
+ || (ret = dwarf_readu16 (as, a, addr, &v1, arg)) < 0)
+ return ret;
+
+ if (tdep_big_endian (as))
+ *val = (uint32_t) v0 << 16 | v1;
+ else
+ *val = (uint32_t) v1 << 16 | v0;
+ return 0;
+}
+
+static inline int
+dwarf_readu64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ uint64_t *val, void *arg)
+{
+ uint32_t v0, v1;
+ int ret;
+
+ if ((ret = dwarf_readu32 (as, a, addr, &v0, arg)) < 0
+ || (ret = dwarf_readu32 (as, a, addr, &v1, arg)) < 0)
+ return ret;
+
+ if (tdep_big_endian (as))
+ *val = (uint64_t) v0 << 32 | v1;
+ else
+ *val = (uint64_t) v1 << 32 | v0;
+ return 0;
+}
+
+static inline int
+dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ int8_t *val, void *arg)
+{
+ uint8_t uval;
+ int ret;
+
+ if ((ret = dwarf_readu8 (as, a, addr, &uval, arg)) < 0)
+ return ret;
+ *val = (int8_t) uval;
+ return 0;
+}
+
+static inline int
+dwarf_reads16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ int16_t *val, void *arg)
+{
+ uint16_t uval;
+ int ret;
+
+ if ((ret = dwarf_readu16 (as, a, addr, &uval, arg)) < 0)
+ return ret;
+ *val = (int16_t) uval;
+ return 0;
+}
+
+static inline int
+dwarf_reads32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ int32_t *val, void *arg)
+{
+ uint32_t uval;
+ int ret;
+
+ if ((ret = dwarf_readu32 (as, a, addr, &uval, arg)) < 0)
+ return ret;
+ *val = (int32_t) uval;
+ return 0;
+}
+
+static inline int
+dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ int64_t *val, void *arg)
+{
+ uint64_t uval;
+ int ret;
+
+ if ((ret = dwarf_readu64 (as, a, addr, &uval, arg)) < 0)
+ return ret;
+ *val = (int64_t) uval;
+ return 0;
+}
+
+#endif /* !UNW_LOCAL_ONLY */
+
+static inline int
+dwarf_readw (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ unw_word_t *val, void *arg)
+{
+ uint32_t u32;
+ uint64_t u64;
+ int ret;
+
+ switch (dwarf_addr_size (as))
+ {
+ case 4:
+ ret = dwarf_readu32 (as, a, addr, &u32, arg);
+ if (ret < 0)
+ return ret;
+ *val = u32;
+ return ret;
+
+ case 8:
+ ret = dwarf_readu64 (as, a, addr, &u64, arg);
+ if (ret < 0)
+ return ret;
+ *val = u64;
+ return ret;
+
+ default:
+ abort ();
+ }
+}
+
+/* Read an unsigned "little-endian base 128" value. See Chapter 7.6
+ of DWARF spec v3. */
+
+static inline int
+dwarf_read_uleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ unw_word_t *valp, void *arg)
+{
+ unw_word_t val = 0, shift = 0;
+ unsigned char byte;
+ int ret;
+
+ do
+ {
+ if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0)
+ return ret;
+
+ val |= ((unw_word_t) byte & 0x7f) << shift;
+ shift += 7;
+ }
+ while (byte & 0x80);
+
+ *valp = val;
+ return 0;
+}
+
+/* Read a signed "little-endian base 128" value. See Chapter 7.6 of
+ DWARF spec v3. */
+
+static inline int
+dwarf_read_sleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ unw_word_t *valp, void *arg)
+{
+ unw_word_t val = 0, shift = 0;
+ unsigned char byte;
+ int ret;
+
+ do
+ {
+ if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0)
+ return ret;
+
+ val |= ((unw_word_t) byte & 0x7f) << shift;
+ shift += 7;
+ }
+ while (byte & 0x80);
+
+ if (shift < 8 * sizeof (unw_word_t) && (byte & 0x40) != 0)
+ /* sign-extend negative value */
+ val |= ((unw_word_t) -1) << shift;
+
+ *valp = val;
+ return 0;
+}
+
+static ALWAYS_INLINE int
+dwarf_read_encoded_pointer_inlined (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t *addr, unsigned char encoding,
+ const unw_proc_info_t *pi,
+ unw_word_t *valp, void *arg)
+{
+ unw_word_t val, initial_addr = *addr;
+ uint16_t uval16;
+ uint32_t uval32;
+ uint64_t uval64;
+ int16_t sval16 = 0;
+ int32_t sval32 = 0;
+ int64_t sval64 = 0;
+ int ret;
+
+ /* DW_EH_PE_omit and DW_EH_PE_aligned don't follow the normal
+ format/application encoding. Handle them first. */
+ if (encoding == DW_EH_PE_omit)
+ {
+ *valp = 0;
+ return 0;
+ }
+ else if (encoding == DW_EH_PE_aligned)
+ {
+ int size = dwarf_addr_size (as);
+ *addr = (initial_addr + size - 1) & -size;
+ return dwarf_readw (as, a, addr, valp, arg);
+ }
+
+ switch (encoding & DW_EH_PE_FORMAT_MASK)
+ {
+ case DW_EH_PE_ptr:
+ if ((ret = dwarf_readw (as, a, addr, &val, arg)) < 0)
+ return ret;
+ break;
+
+ case DW_EH_PE_uleb128:
+ if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
+ return ret;
+ break;
+
+ case DW_EH_PE_udata2:
+ if ((ret = dwarf_readu16 (as, a, addr, &uval16, arg)) < 0)
+ return ret;
+ val = uval16;
+ break;
+
+ case DW_EH_PE_udata4:
+ if ((ret = dwarf_readu32 (as, a, addr, &uval32, arg)) < 0)
+ return ret;
+ val = uval32;
+ break;
+
+ case DW_EH_PE_udata8:
+ if ((ret = dwarf_readu64 (as, a, addr, &uval64, arg)) < 0)
+ return ret;
+ val = uval64;
+ break;
+
+ case DW_EH_PE_sleb128:
+ if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
+ return ret;
+ break;
+
+ case DW_EH_PE_sdata2:
+ if ((ret = dwarf_reads16 (as, a, addr, &sval16, arg)) < 0)
+ return ret;
+ val = sval16;
+ break;
+
+ case DW_EH_PE_sdata4:
+ if ((ret = dwarf_reads32 (as, a, addr, &sval32, arg)) < 0)
+ return ret;
+ val = sval32;
+ break;
+
+ case DW_EH_PE_sdata8:
+ if ((ret = dwarf_reads64 (as, a, addr, &sval64, arg)) < 0)
+ return ret;
+ val = sval64;
+ break;
+
+ default:
+ Debug (1, "unexpected encoding format 0x%x\n",
+ encoding & DW_EH_PE_FORMAT_MASK);
+ return -UNW_EINVAL;
+ }
+
+ if (val == 0)
+ {
+ /* 0 is a special value and always absolute. */
+ *valp = 0;
+ return 0;
+ }
+
+ switch (encoding & DW_EH_PE_APPL_MASK)
+ {
+ case DW_EH_PE_absptr:
+ break;
+
+ case DW_EH_PE_pcrel:
+ val += initial_addr;
+ break;
+
+ case DW_EH_PE_datarel:
+ /* XXX For now, assume that data-relative addresses are relative
+ to the global pointer. */
+ val += pi->gp;
+ break;
+
+ case DW_EH_PE_funcrel:
+ val += pi->start_ip;
+ break;
+
+ case DW_EH_PE_textrel:
+ /* XXX For now we don't support text-rel values. If there is a
+ platform which needs this, we probably would have to add a
+ "segbase" member to unw_proc_info_t. */
+ default:
+ Debug (1, "unexpected application type 0x%x\n",
+ encoding & DW_EH_PE_APPL_MASK);
+ return -UNW_EINVAL;
+ }
+
+ /* Trim off any extra bits. Assume that sign extension isn't
+ required; the only place it is needed is MIPS kernel space
+ addresses. */
+ if (sizeof (val) > dwarf_addr_size (as))
+ {
+ assert (dwarf_addr_size (as) == 4);
+ val = (uint32_t) val;
+ }
+
+ if (encoding & DW_EH_PE_indirect)
+ {
+ unw_word_t indirect_addr = val;
+
+ if ((ret = dwarf_readw (as, a, &indirect_addr, &val, arg)) < 0)
+ return ret;
+ }
+
+ *valp = val;
+ return 0;
+}
+
+#endif /* DWARF_I_H */
diff --git a/src/pal/src/libunwind/include/libunwind-aarch64.h b/src/pal/src/libunwind/include/libunwind-aarch64.h
new file mode 100644
index 0000000000..85812e151d
--- /dev/null
+++ b/src/pal/src/libunwind/include/libunwind-aarch64.h
@@ -0,0 +1,210 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+ Copyright (C) 2013 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef LIBUNWIND_H
+#define LIBUNWIND_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <ucontext.h>
+
+#define UNW_TARGET aarch64
+#define UNW_TARGET_AARCH64 1
+
+#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
+
+/* This needs to be big enough to accommodate "struct cursor", while
+ leaving some slack for future expansion. Changing this value will
+ require recompiling all users of this library. Stack allocation is
+ relatively cheap and unwind-state copying is relatively rare, so we
+ want to err on making it rather too big than too small. */
+
+#define UNW_TDEP_CURSOR_LEN 512
+
+typedef uint64_t unw_word_t;
+typedef int64_t unw_sword_t;
+
+typedef long double unw_tdep_fpreg_t;
+
+typedef struct
+ {
+ /* no aarch64-specific auxiliary proc-info */
+ }
+unw_tdep_proc_info_t;
+
+typedef enum
+ {
+ /* 64-bit general registers. */
+ UNW_AARCH64_X0,
+ UNW_AARCH64_X1,
+ UNW_AARCH64_X2,
+ UNW_AARCH64_X3,
+ UNW_AARCH64_X4,
+ UNW_AARCH64_X5,
+ UNW_AARCH64_X6,
+ UNW_AARCH64_X7,
+ UNW_AARCH64_X8,
+
+ /* Temporary registers. */
+ UNW_AARCH64_X9,
+ UNW_AARCH64_X10,
+ UNW_AARCH64_X11,
+ UNW_AARCH64_X12,
+ UNW_AARCH64_X13,
+ UNW_AARCH64_X14,
+ UNW_AARCH64_X15,
+
+ /* Intra-procedure-call temporary registers. */
+ UNW_AARCH64_X16,
+ UNW_AARCH64_X17,
+
+ /* Callee-saved registers. */
+ UNW_AARCH64_X18,
+ UNW_AARCH64_X19,
+ UNW_AARCH64_X20,
+ UNW_AARCH64_X21,
+ UNW_AARCH64_X22,
+ UNW_AARCH64_X23,
+ UNW_AARCH64_X24,
+ UNW_AARCH64_X25,
+ UNW_AARCH64_X26,
+ UNW_AARCH64_X27,
+ UNW_AARCH64_X28,
+
+ /* 64-bit frame pointer. */
+ UNW_AARCH64_X29,
+
+ /* 64-bit link register. */
+ UNW_AARCH64_X30,
+
+ /* 64-bit stack pointer. */
+ UNW_AARCH64_SP = 31,
+ UNW_AARCH64_PC,
+ UNW_AARCH64_PSTATE,
+
+ /* 128-bit FP/Advanced SIMD registers. */
+ UNW_AARCH64_V0 = 64,
+ UNW_AARCH64_V1,
+ UNW_AARCH64_V2,
+ UNW_AARCH64_V3,
+ UNW_AARCH64_V4,
+ UNW_AARCH64_V5,
+ UNW_AARCH64_V6,
+ UNW_AARCH64_V7,
+ UNW_AARCH64_V8,
+ UNW_AARCH64_V9,
+ UNW_AARCH64_V10,
+ UNW_AARCH64_V11,
+ UNW_AARCH64_V12,
+ UNW_AARCH64_V13,
+ UNW_AARCH64_V14,
+ UNW_AARCH64_V15,
+ UNW_AARCH64_V16,
+ UNW_AARCH64_V17,
+ UNW_AARCH64_V18,
+ UNW_AARCH64_V19,
+ UNW_AARCH64_V20,
+ UNW_AARCH64_V21,
+ UNW_AARCH64_V22,
+ UNW_AARCH64_V23,
+ UNW_AARCH64_V24,
+ UNW_AARCH64_V25,
+ UNW_AARCH64_V26,
+ UNW_AARCH64_V27,
+ UNW_AARCH64_V28,
+ UNW_AARCH64_V29,
+ UNW_AARCH64_V30,
+ UNW_AARCH64_V31,
+
+ UNW_AARCH64_FPSR,
+ UNW_AARCH64_FPCR,
+
+ /* For AArch64, the CFA is the value of SP (x31) at the call site of the
+ previous frame. */
+ UNW_AARCH64_CFA = UNW_AARCH64_SP,
+
+ UNW_TDEP_LAST_REG = UNW_AARCH64_FPCR,
+
+ UNW_TDEP_IP = UNW_AARCH64_X30,
+ UNW_TDEP_SP = UNW_AARCH64_SP,
+ UNW_TDEP_EH = UNW_AARCH64_X0,
+
+ }
+aarch64_regnum_t;
+
+/* Use R0 through R3 to pass exception handling information. */
+#define UNW_TDEP_NUM_EH_REGS 4
+
+typedef struct unw_tdep_save_loc
+ {
+ /* Additional target-dependent info on a save location. */
+ }
+unw_tdep_save_loc_t;
+
+
+/* On AArch64, we can directly use ucontext_t as the unwind context. */
+typedef ucontext_t unw_tdep_context_t;
+
+#include "libunwind-common.h"
+#include "libunwind-dynamic.h"
+
+#define unw_tdep_getcontext(uc) (({ \
+ unw_tdep_context_t *unw_ctx = (uc); \
+ register uint64_t *unw_base asm ("x0") = (uint64_t*) unw_ctx->uc_mcontext.regs; \
+ __asm__ __volatile__ ( \
+ "stp x0, x1, [%[base], #0]\n" \
+ "stp x2, x3, [%[base], #16]\n" \
+ "stp x4, x5, [%[base], #32]\n" \
+ "stp x6, x7, [%[base], #48]\n" \
+ "stp x8, x9, [%[base], #64]\n" \
+ "stp x10, x11, [%[base], #80]\n" \
+ "stp x12, x13, [%[base], #96]\n" \
+ "stp x14, x13, [%[base], #112]\n" \
+ "stp x16, x17, [%[base], #128]\n" \
+ "stp x18, x19, [%[base], #144]\n" \
+ "stp x20, x21, [%[base], #160]\n" \
+ "stp x22, x23, [%[base], #176]\n" \
+ "stp x24, x25, [%[base], #192]\n" \
+ "stp x26, x27, [%[base], #208]\n" \
+ "stp x28, x29, [%[base], #224]\n" \
+ "str x30, [%[base], #240]\n" \
+ "mov x1, sp\n" \
+ "stp x1, x30, [%[base], #248]\n" \
+ : [base] "+r" (unw_base) : : "x1", "memory"); \
+ }), 0)
+#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
+
+extern int unw_tdep_is_fpreg (int);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* LIBUNWIND_H */
diff --git a/src/pal/src/libunwind/include/libunwind-arm.h b/src/pal/src/libunwind/include/libunwind-arm.h
new file mode 100644
index 0000000000..6709b7abae
--- /dev/null
+++ b/src/pal/src/libunwind/include/libunwind-arm.h
@@ -0,0 +1,303 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef LIBUNWIND_H
+#define LIBUNWIND_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include <inttypes.h>
+#include <stddef.h>
+
+#define UNW_TARGET arm
+#define UNW_TARGET_ARM 1
+
+#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
+
+/* This needs to be big enough to accommodate "struct cursor", while
+ leaving some slack for future expansion. Changing this value will
+ require recompiling all users of this library. Stack allocation is
+ relatively cheap and unwind-state copying is relatively rare, so we
+ want to err on making it rather too big than too small. */
+
+/* FIXME for ARM. Too big? What do other things use for similar tasks? */
+#define UNW_TDEP_CURSOR_LEN 4096
+
+typedef uint32_t unw_word_t;
+typedef int32_t unw_sword_t;
+
+typedef long double unw_tdep_fpreg_t;
+
+typedef enum
+ {
+ UNW_ARM_R0,
+ UNW_ARM_R1,
+ UNW_ARM_R2,
+ UNW_ARM_R3,
+ UNW_ARM_R4,
+ UNW_ARM_R5,
+ UNW_ARM_R6,
+ UNW_ARM_R7,
+ UNW_ARM_R8,
+ UNW_ARM_R9,
+ UNW_ARM_R10,
+ UNW_ARM_R11,
+ UNW_ARM_R12,
+ UNW_ARM_R13,
+ UNW_ARM_R14,
+ UNW_ARM_R15,
+
+ /* VFPv2 s0-s31 (obsolescent numberings). */
+ UNW_ARM_S0 = 64,
+ UNW_ARM_S1,
+ UNW_ARM_S2,
+ UNW_ARM_S3,
+ UNW_ARM_S4,
+ UNW_ARM_S5,
+ UNW_ARM_S6,
+ UNW_ARM_S7,
+ UNW_ARM_S8,
+ UNW_ARM_S9,
+ UNW_ARM_S10,
+ UNW_ARM_S11,
+ UNW_ARM_S12,
+ UNW_ARM_S13,
+ UNW_ARM_S14,
+ UNW_ARM_S15,
+ UNW_ARM_S16,
+ UNW_ARM_S17,
+ UNW_ARM_S18,
+ UNW_ARM_S19,
+ UNW_ARM_S20,
+ UNW_ARM_S21,
+ UNW_ARM_S22,
+ UNW_ARM_S23,
+ UNW_ARM_S24,
+ UNW_ARM_S25,
+ UNW_ARM_S26,
+ UNW_ARM_S27,
+ UNW_ARM_S28,
+ UNW_ARM_S29,
+ UNW_ARM_S30,
+ UNW_ARM_S31,
+
+ /* FPA register numberings. */
+ UNW_ARM_F0 = 96,
+ UNW_ARM_F1,
+ UNW_ARM_F2,
+ UNW_ARM_F3,
+ UNW_ARM_F4,
+ UNW_ARM_F5,
+ UNW_ARM_F6,
+ UNW_ARM_F7,
+
+ /* iWMMXt GR register numberings. */
+ UNW_ARM_wCGR0 = 104,
+ UNW_ARM_wCGR1,
+ UNW_ARM_wCGR2,
+ UNW_ARM_wCGR3,
+ UNW_ARM_wCGR4,
+ UNW_ARM_wCGR5,
+ UNW_ARM_wCGR6,
+ UNW_ARM_wCGR7,
+
+ /* iWMMXt register numberings. */
+ UNW_ARM_wR0 = 112,
+ UNW_ARM_wR1,
+ UNW_ARM_wR2,
+ UNW_ARM_wR3,
+ UNW_ARM_wR4,
+ UNW_ARM_wR5,
+ UNW_ARM_wR6,
+ UNW_ARM_wR7,
+ UNW_ARM_wR8,
+ UNW_ARM_wR9,
+ UNW_ARM_wR10,
+ UNW_ARM_wR11,
+ UNW_ARM_wR12,
+ UNW_ARM_wR13,
+ UNW_ARM_wR14,
+ UNW_ARM_wR15,
+
+ /* Two-byte encodings from here on. */
+
+ /* SPSR. */
+ UNW_ARM_SPSR = 128,
+ UNW_ARM_SPSR_FIQ,
+ UNW_ARM_SPSR_IRQ,
+ UNW_ARM_SPSR_ABT,
+ UNW_ARM_SPSR_UND,
+ UNW_ARM_SPSR_SVC,
+
+ /* User mode registers. */
+ UNW_ARM_R8_USR = 144,
+ UNW_ARM_R9_USR,
+ UNW_ARM_R10_USR,
+ UNW_ARM_R11_USR,
+ UNW_ARM_R12_USR,
+ UNW_ARM_R13_USR,
+ UNW_ARM_R14_USR,
+
+ /* FIQ registers. */
+ UNW_ARM_R8_FIQ = 151,
+ UNW_ARM_R9_FIQ,
+ UNW_ARM_R10_FIQ,
+ UNW_ARM_R11_FIQ,
+ UNW_ARM_R12_FIQ,
+ UNW_ARM_R13_FIQ,
+ UNW_ARM_R14_FIQ,
+
+ /* IRQ registers. */
+ UNW_ARM_R13_IRQ = 158,
+ UNW_ARM_R14_IRQ,
+
+ /* ABT registers. */
+ UNW_ARM_R13_ABT = 160,
+ UNW_ARM_R14_ABT,
+
+ /* UND registers. */
+ UNW_ARM_R13_UND = 162,
+ UNW_ARM_R14_UND,
+
+ /* SVC registers. */
+ UNW_ARM_R13_SVC = 164,
+ UNW_ARM_R14_SVC,
+
+ /* iWMMXt control registers. */
+ UNW_ARM_wC0 = 192,
+ UNW_ARM_wC1,
+ UNW_ARM_wC2,
+ UNW_ARM_wC3,
+ UNW_ARM_wC4,
+ UNW_ARM_wC5,
+ UNW_ARM_wC6,
+ UNW_ARM_wC7,
+
+ /* VFPv3/Neon 64-bit registers. */
+ UNW_ARM_D0 = 256,
+ UNW_ARM_D1,
+ UNW_ARM_D2,
+ UNW_ARM_D3,
+ UNW_ARM_D4,
+ UNW_ARM_D5,
+ UNW_ARM_D6,
+ UNW_ARM_D7,
+ UNW_ARM_D8,
+ UNW_ARM_D9,
+ UNW_ARM_D10,
+ UNW_ARM_D11,
+ UNW_ARM_D12,
+ UNW_ARM_D13,
+ UNW_ARM_D14,
+ UNW_ARM_D15,
+ UNW_ARM_D16,
+ UNW_ARM_D17,
+ UNW_ARM_D18,
+ UNW_ARM_D19,
+ UNW_ARM_D20,
+ UNW_ARM_D21,
+ UNW_ARM_D22,
+ UNW_ARM_D23,
+ UNW_ARM_D24,
+ UNW_ARM_D25,
+ UNW_ARM_D26,
+ UNW_ARM_D27,
+ UNW_ARM_D28,
+ UNW_ARM_D29,
+ UNW_ARM_D30,
+ UNW_ARM_D31,
+
+ /* For ARM, the CFA is the value of SP (r13) at the call site in the
+ previous frame. */
+ UNW_ARM_CFA,
+
+ UNW_TDEP_LAST_REG = UNW_ARM_D31,
+
+ UNW_TDEP_IP = UNW_ARM_R14, /* A little white lie. */
+ UNW_TDEP_SP = UNW_ARM_R13,
+ UNW_TDEP_EH = UNW_ARM_R0 /* FIXME. */
+ }
+arm_regnum_t;
+
+#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for ARM. */
+
+typedef struct unw_tdep_save_loc
+ {
+ /* Additional target-dependent info on a save location. */
+ }
+unw_tdep_save_loc_t;
+
+/* On ARM, we define our own unw_tdep_context instead of using ucontext_t.
+ This allows us to support systems that don't support getcontext and
+ therefore do not define ucontext_t. */
+typedef struct unw_tdep_context
+ {
+ unsigned long regs[16];
+ }
+unw_tdep_context_t;
+
+/* There is no getcontext() on ARM. Use a stub version which only saves GP
+ registers. FIXME: Not ideal, may not be sufficient for all libunwind
+ use cases. Stores pc+8, which is only approximately correct, really. */
+#ifndef __thumb__
+#define unw_tdep_getcontext(uc) (({ \
+ unw_tdep_context_t *unw_ctx = (uc); \
+ register unsigned long *unw_base __asm__ ("r0") = unw_ctx->regs; \
+ __asm__ __volatile__ ( \
+ "stmia %[base], {r0-r15}" \
+ : : [base] "r" (unw_base) : "memory"); \
+ }), 0)
+#else /* __thumb__ */
+#define unw_tdep_getcontext(uc) (({ \
+ unw_tdep_context_t *unw_ctx = (uc); \
+ register unsigned long *unw_base __asm__ ("r0") = unw_ctx->regs; \
+ __asm__ __volatile__ ( \
+ ".align 2\nbx pc\nnop\n.code 32\n" \
+ "stmia %[base], {r0-r15}\n" \
+ "orr %[base], pc, #1\nbx %[base]\n" \
+ ".code 16\n" \
+ : [base] "+r" (unw_base) : : "memory", "cc"); \
+ }), 0)
+#endif
+
+#include "libunwind-dynamic.h"
+
+typedef struct
+ {
+ /* no arm-specific auxiliary proc-info */
+ }
+unw_tdep_proc_info_t;
+
+#include "libunwind-common.h"
+
+#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
+extern int unw_tdep_is_fpreg (int);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* LIBUNWIND_H */
diff --git a/src/pal/src/libunwind/include/libunwind-common.h.in b/src/pal/src/libunwind/include/libunwind-common.h.in
new file mode 100644
index 0000000000..8d96ddca2a
--- /dev/null
+++ b/src/pal/src/libunwind/include/libunwind-common.h.in
@@ -0,0 +1,281 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#define UNW_VERSION_MAJOR @PKG_MAJOR@
+#define UNW_VERSION_MINOR @PKG_MINOR@
+#define UNW_VERSION_EXTRA @PKG_EXTRA@
+
+#define UNW_VERSION_CODE(maj,min) (((maj) << 16) | (min))
+#define UNW_VERSION UNW_VERSION_CODE(UNW_VERSION_MAJOR, UNW_VERSION_MINOR)
+
+#define UNW_PASTE2(x,y) x##y
+#define UNW_PASTE(x,y) UNW_PASTE2(x,y)
+#define UNW_OBJ(fn) UNW_PASTE(UNW_PREFIX, fn)
+#define UNW_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_), fn)
+
+#ifdef UNW_LOCAL_ONLY
+# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_UL,UNW_TARGET),_)
+#else /* !UNW_LOCAL_ONLY */
+# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_)
+#endif /* !UNW_LOCAL_ONLY */
+
+/* Error codes. The unwind routines return the *negated* values of
+ these error codes on error and a non-negative value on success. */
+typedef enum
+ {
+ UNW_ESUCCESS = 0, /* no error */
+ UNW_EUNSPEC, /* unspecified (general) error */
+ UNW_ENOMEM, /* out of memory */
+ UNW_EBADREG, /* bad register number */
+ UNW_EREADONLYREG, /* attempt to write read-only register */
+ UNW_ESTOPUNWIND, /* stop unwinding */
+ UNW_EINVALIDIP, /* invalid IP */
+ UNW_EBADFRAME, /* bad frame */
+ UNW_EINVAL, /* unsupported operation or bad value */
+ UNW_EBADVERSION, /* unwind info has unsupported version */
+ UNW_ENOINFO /* no unwind info found */
+ }
+unw_error_t;
+
+/* The following enum defines the indices for a couple of
+ (pseudo-)registers which have the same meaning across all
+ platforms. (RO) means read-only. (RW) means read-write. General
+ registers (aka "integer registers") are expected to start with
+ index 0. The number of such registers is architecture-dependent.
+ The remaining indices can be used as an architecture sees fit. The
+ last valid register index is given by UNW_REG_LAST. */
+typedef enum
+ {
+ UNW_REG_IP = UNW_TDEP_IP, /* (rw) instruction pointer (pc) */
+ UNW_REG_SP = UNW_TDEP_SP, /* (ro) stack pointer */
+ UNW_REG_EH = UNW_TDEP_EH, /* (rw) exception-handling reg base */
+ UNW_REG_LAST = UNW_TDEP_LAST_REG
+ }
+unw_frame_regnum_t;
+
+/* Number of exception-handler argument registers: */
+#define UNW_NUM_EH_REGS UNW_TDEP_NUM_EH_REGS
+
+typedef enum
+ {
+ UNW_CACHE_NONE, /* no caching */
+ UNW_CACHE_GLOBAL, /* shared global cache */
+ UNW_CACHE_PER_THREAD /* per-thread caching */
+ }
+unw_caching_policy_t;
+
+typedef enum
+ {
+ UNW_INIT_SIGNAL_FRAME = 1, /* We know this is a signal frame */
+ }
+unw_init_local2_flags_t;
+
+typedef int unw_regnum_t;
+
+/* The unwind cursor starts at the youngest (most deeply nested) frame
+ and is used to track the frame state as the unwinder steps from
+ frame to frame. It is safe to make (shallow) copies of variables
+ of this type. */
+typedef struct unw_cursor
+ {
+ unw_word_t opaque[UNW_TDEP_CURSOR_LEN];
+ }
+unw_cursor_t;
+
+/* This type encapsulates the entire (preserved) machine-state. */
+typedef unw_tdep_context_t unw_context_t;
+
+/* unw_getcontext() fills the unw_context_t pointed to by UC with the
+ machine state as it exists at the call-site. For implementation
+ reasons, this needs to be a target-dependent macro. It's easiest
+ to think of unw_getcontext() as being identical to getcontext(). */
+#define unw_getcontext(uc) unw_tdep_getcontext(uc)
+
+/* Return 1 if register number R is a floating-point register, zero
+ otherwise.
+ This routine is signal-safe. */
+#define unw_is_fpreg(r) unw_tdep_is_fpreg(r)
+
+typedef unw_tdep_fpreg_t unw_fpreg_t;
+
+typedef struct unw_addr_space *unw_addr_space_t;
+
+/* Each target may define it's own set of flags, but bits 0-15 are
+ reserved for general libunwind-use. */
+#define UNW_PI_FLAG_FIRST_TDEP_BIT 16
+/* The information comes from a .debug_frame section. */
+#define UNW_PI_FLAG_DEBUG_FRAME 32
+
+typedef struct unw_proc_info
+ {
+ unw_word_t start_ip; /* first IP covered by this procedure */
+ unw_word_t end_ip; /* first IP NOT covered by this procedure */
+#if defined(NEED_LAST_IP)
+ unw_word_t last_ip; /* first IP that could begin another procedure */
+#endif
+ unw_word_t lsda; /* address of lang.-spec. data area (if any) */
+ unw_word_t handler; /* optional personality routine */
+ unw_word_t gp; /* global-pointer value for this procedure */
+ unw_word_t flags; /* misc. flags */
+
+ int format; /* unwind-info format (arch-specific) */
+ int unwind_info_size; /* size of the information (if applicable) */
+ void *unwind_info; /* unwind-info (arch-specific) */
+ unw_tdep_proc_info_t extra; /* target-dependent auxiliary proc-info */
+ }
+unw_proc_info_t;
+
+typedef int (*unw_reg_states_callback)(void *token,
+ void *reg_states_data,
+ size_t reg_states_data_size,
+ unw_word_t start_ip, unw_word_t end_ip);
+
+/* These are backend callback routines that provide access to the
+ state of a "remote" process. This can be used, for example, to
+ unwind another process through the ptrace() interface. */
+typedef struct unw_accessors
+ {
+ /* Look up the unwind info associated with instruction-pointer IP.
+ On success, the routine fills in the PROC_INFO structure. */
+ int (*find_proc_info) (unw_addr_space_t, unw_word_t, unw_proc_info_t *,
+ int, void *);
+
+ /* Release any resources (e.g., memory) that were allocated for
+ the unwind info returned in by a previous call to
+ find_proc_info() with NEED_UNWIND_INFO set to 1. */
+ void (*put_unwind_info) (unw_addr_space_t, unw_proc_info_t *, void *);
+
+ /* Return the list-head of the dynamically registered unwind
+ info. */
+ int (*get_dyn_info_list_addr) (unw_addr_space_t, unw_word_t *, void *);
+
+ /* Access aligned word at address ADDR. The value is returned
+ according to the endianness of the host (e.g., if the host is
+ little-endian and the target is big-endian, access_mem() needs
+ to byte-swap the value before returning it). */
+ int (*access_mem) (unw_addr_space_t, unw_word_t, unw_word_t *, int,
+ void *);
+
+ /* Access register number REG at address ADDR. */
+ int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *, int,
+ void *);
+
+ /* Access register number REG at address ADDR. */
+ int (*access_fpreg) (unw_addr_space_t, unw_regnum_t,
+ unw_fpreg_t *, int, void *);
+
+ int (*resume) (unw_addr_space_t, unw_cursor_t *, void *);
+
+ /* Optional call back to obtain the name of a (static) procedure.
+ Dynamically generated procedures are handled automatically by
+ libunwind. This callback is optional and may be set to
+ NULL. */
+ int (*get_proc_name) (unw_addr_space_t, unw_word_t, char *, size_t,
+ unw_word_t *, void *);
+ }
+unw_accessors_t;
+
+typedef enum unw_save_loc_type
+ {
+ UNW_SLT_NONE, /* register is not saved ("not an l-value") */
+ UNW_SLT_MEMORY, /* register has been saved in memory */
+ UNW_SLT_REG /* register has been saved in (another) register */
+ }
+unw_save_loc_type_t;
+
+typedef struct unw_save_loc
+ {
+ unw_save_loc_type_t type;
+ union
+ {
+ unw_word_t addr; /* valid if type==UNW_SLT_MEMORY */
+ unw_regnum_t regnum; /* valid if type==UNW_SLT_REG */
+ }
+ u;
+ unw_tdep_save_loc_t extra; /* target-dependent additional information */
+ }
+unw_save_loc_t;
+
+/* These routines work both for local and remote unwinding. */
+
+#define unw_local_addr_space UNW_OBJ(local_addr_space)
+#define unw_create_addr_space UNW_OBJ(create_addr_space)
+#define unw_destroy_addr_space UNW_OBJ(destroy_addr_space)
+#define unw_get_accessors UNW_ARCH_OBJ(get_accessors)
+#define unw_get_accessors_int UNW_ARCH_OBJ(get_accessors_int)
+#define unw_init_local UNW_OBJ(init_local)
+#define unw_init_local2 UNW_OBJ(init_local2)
+#define unw_init_remote UNW_OBJ(init_remote)
+#define unw_step UNW_OBJ(step)
+#define unw_resume UNW_OBJ(resume)
+#define unw_get_proc_info UNW_OBJ(get_proc_info)
+#define unw_get_proc_info_by_ip UNW_OBJ(get_proc_info_by_ip)
+#define unw_reg_states_iterate UNW_OBJ(reg_states_iterate)
+#define unw_apply_reg_state UNW_OBJ(apply_reg_state)
+#define unw_get_reg UNW_OBJ(get_reg)
+#define unw_set_reg UNW_OBJ(set_reg)
+#define unw_get_fpreg UNW_OBJ(get_fpreg)
+#define unw_set_fpreg UNW_OBJ(set_fpreg)
+#define unw_get_save_loc UNW_OBJ(get_save_loc)
+#define unw_is_signal_frame UNW_OBJ(is_signal_frame)
+#define unw_handle_signal_frame UNW_OBJ(handle_signal_frame)
+#define unw_get_proc_name UNW_OBJ(get_proc_name)
+#define unw_set_caching_policy UNW_OBJ(set_caching_policy)
+#define unw_set_cache_size UNW_OBJ(set_cache_size)
+#define unw_regname UNW_ARCH_OBJ(regname)
+#define unw_flush_cache UNW_ARCH_OBJ(flush_cache)
+#define unw_strerror UNW_ARCH_OBJ(strerror)
+
+extern unw_addr_space_t unw_create_addr_space (unw_accessors_t *, int);
+extern void unw_destroy_addr_space (unw_addr_space_t);
+extern unw_accessors_t *unw_get_accessors (unw_addr_space_t);
+extern unw_accessors_t *unw_get_accessors_int (unw_addr_space_t);
+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 int unw_set_cache_size (unw_addr_space_t, size_t, int);
+extern const char *unw_regname (unw_regnum_t);
+
+extern int unw_init_local (unw_cursor_t *, unw_context_t *);
+extern int unw_init_local2 (unw_cursor_t *, unw_context_t *, int);
+extern int unw_init_remote (unw_cursor_t *, unw_addr_space_t, void *);
+extern int unw_step (unw_cursor_t *);
+extern int unw_resume (unw_cursor_t *);
+extern int unw_get_proc_info (unw_cursor_t *, unw_proc_info_t *);
+extern int unw_get_proc_info_by_ip (unw_addr_space_t, unw_word_t,
+ unw_proc_info_t *, void *);
+extern int unw_reg_states_iterate (unw_cursor_t *, unw_reg_states_callback, void *);
+extern int unw_apply_reg_state (unw_cursor_t *, void *);
+extern int unw_get_reg (unw_cursor_t *, int, unw_word_t *);
+extern int unw_set_reg (unw_cursor_t *, int, unw_word_t);
+extern int unw_get_fpreg (unw_cursor_t *, int, unw_fpreg_t *);
+extern int unw_set_fpreg (unw_cursor_t *, int, unw_fpreg_t);
+extern int unw_get_save_loc (unw_cursor_t *, int, unw_save_loc_t *);
+extern int unw_is_signal_frame (unw_cursor_t *);
+extern int unw_handle_signal_frame (unw_cursor_t *);
+extern int unw_get_proc_name (unw_cursor_t *, char *, size_t, unw_word_t *);
+extern const char *unw_strerror (int);
+extern int unw_backtrace (void **, int);
+
+extern unw_addr_space_t unw_local_addr_space;
diff --git a/src/pal/src/libunwind/include/libunwind-coredump.h b/src/pal/src/libunwind/include/libunwind-coredump.h
new file mode 100644
index 0000000000..3c7814140f
--- /dev/null
+++ b/src/pal/src/libunwind/include/libunwind-coredump.h
@@ -0,0 +1,73 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef libunwind_coredump_h
+#define libunwind_coredump_h
+
+#include <libunwind.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+/* Helper routines which make it easy to use libunwind on a coredump.
+ They're available only if UNW_REMOTE_ONLY is _not_ defined and they
+ aren't really part of the libunwind API. They are implemented in a
+ archive library called libunwind-coredump.a. */
+
+struct UCD_info;
+
+extern struct UCD_info *_UCD_create(const char *filename);
+extern void _UCD_destroy(struct UCD_info *);
+
+extern int _UCD_get_num_threads(struct UCD_info *);
+extern void _UCD_select_thread(struct UCD_info *, int);
+extern pid_t _UCD_get_pid(struct UCD_info *);
+extern int _UCD_get_cursig(struct UCD_info *);
+extern int _UCD_add_backing_file_at_segment(struct UCD_info *, int phdr_no, const char *filename);
+extern int _UCD_add_backing_file_at_vaddr(struct UCD_info *,
+ unsigned long vaddr,
+ const char *filename);
+
+extern int _UCD_find_proc_info (unw_addr_space_t, unw_word_t,
+ unw_proc_info_t *, int, void *);
+extern void _UCD_put_unwind_info (unw_addr_space_t, unw_proc_info_t *, void *);
+extern int _UCD_get_dyn_info_list_addr (unw_addr_space_t, unw_word_t *,
+ void *);
+extern int _UCD_access_mem (unw_addr_space_t, unw_word_t, unw_word_t *, int,
+ void *);
+extern int _UCD_access_reg (unw_addr_space_t, unw_regnum_t, unw_word_t *,
+ int, void *);
+extern int _UCD_access_fpreg (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *,
+ int, void *);
+extern int _UCD_get_proc_name (unw_addr_space_t, unw_word_t, char *, size_t,
+ unw_word_t *, void *);
+extern int _UCD_resume (unw_addr_space_t, unw_cursor_t *, void *);
+extern unw_accessors_t _UCD_accessors;
+
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* libunwind_coredump_h */
diff --git a/src/pal/src/libunwind/include/libunwind-dynamic.h b/src/pal/src/libunwind/include/libunwind-dynamic.h
new file mode 100644
index 0000000000..edb0bbd343
--- /dev/null
+++ b/src/pal/src/libunwind/include/libunwind-dynamic.h
@@ -0,0 +1,214 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* This file defines the runtime-support routines for dynamically
+generated code. Even though it is implemented as part of libunwind,
+it is logically separate from the interface to perform the actual
+unwinding. In particular, this interface is always used in the
+context of the unwind target, whereas the rest of the unwind API is
+used in context of the process that is doing the unwind (which may be
+a debugger running on another machine, for example).
+
+Note that the data-structures declared here server a dual purpose:
+when a program registers a dynamically generated procedure, it uses
+these structures directly. On the other hand, with remote-unwinding,
+the data-structures are read from the remote process's memory and
+translated into internalized versions. To facilitate remote-access,
+the following rules should be followed in declaring these structures:
+
+ (1) Declare a member as a pointer only if the the information the
+ member points to needs to be internalized as well (e.g., a
+ string representing a procedure name should be declared as
+ "const char *", but the instruction pointer should be declared
+ as unw_word_t).
+
+ (2) Provide sufficient padding to ensure that no implicit padding
+ will be needed on any of the supported target architectures. For
+ the time being, padding data structures with the assumption that
+ sizeof (unw_word_t) == 8 should be sufficient. (Note: it's not
+ impossible to internalize structures with internal padding, but
+ it does make the process a bit harder).
+
+ (3) Don't declare members that contain bitfields or floating-point
+ values.
+
+ (4) Don't declare members with enumeration types. Declare them as
+ int32_t instead. */
+
+typedef enum
+ {
+ UNW_DYN_STOP = 0, /* end-of-unwind-info marker */
+ UNW_DYN_SAVE_REG, /* save register to another register */
+ UNW_DYN_SPILL_FP_REL, /* frame-pointer-relative register spill */
+ UNW_DYN_SPILL_SP_REL, /* stack-pointer-relative register spill */
+ UNW_DYN_ADD, /* add constant value to a register */
+ UNW_DYN_POP_FRAMES, /* drop one or more stack frames */
+ UNW_DYN_LABEL_STATE, /* name the current state */
+ UNW_DYN_COPY_STATE, /* set the region's entry-state */
+ UNW_DYN_ALIAS /* get unwind info from an alias */
+ }
+unw_dyn_operation_t;
+
+typedef enum
+ {
+ UNW_INFO_FORMAT_DYNAMIC, /* unw_dyn_proc_info_t */
+ UNW_INFO_FORMAT_TABLE, /* unw_dyn_table_t */
+ UNW_INFO_FORMAT_REMOTE_TABLE, /* unw_dyn_remote_table_t */
+ UNW_INFO_FORMAT_ARM_EXIDX, /* ARM specific unwind info */
+ UNW_INFO_FORMAT_IP_OFFSET, /* Like UNW_INFO_FORMAT_REMOTE_TABLE, but
+ table entries are considered
+ relative to di->start_ip, rather
+ than di->segbase */
+ }
+unw_dyn_info_format_t;
+
+typedef struct unw_dyn_op
+ {
+ int8_t tag; /* what operation? */
+ int8_t qp; /* qualifying predicate register */
+ int16_t reg; /* what register */
+ int32_t when; /* when does it take effect? */
+ unw_word_t val; /* auxiliary value */
+ }
+unw_dyn_op_t;
+
+typedef struct unw_dyn_region_info
+ {
+ struct unw_dyn_region_info *next; /* linked list of regions */
+ int32_t insn_count; /* region length (# of instructions) */
+ uint32_t op_count; /* length of op-array */
+ unw_dyn_op_t op[1]; /* variable-length op-array */
+ }
+unw_dyn_region_info_t;
+
+typedef struct unw_dyn_proc_info
+ {
+ unw_word_t name_ptr; /* address of human-readable procedure name */
+ unw_word_t handler; /* address of personality routine */
+ uint32_t flags;
+ int32_t pad0;
+ unw_dyn_region_info_t *regions;
+ }
+unw_dyn_proc_info_t;
+
+typedef struct unw_dyn_table_info
+ {
+ unw_word_t name_ptr; /* addr. of table name (e.g., library name) */
+ unw_word_t segbase; /* segment base */
+ unw_word_t table_len; /* must be a multiple of sizeof(unw_word_t)! */
+ unw_word_t *table_data;
+ }
+unw_dyn_table_info_t;
+
+typedef struct unw_dyn_remote_table_info
+ {
+ unw_word_t name_ptr; /* addr. of table name (e.g., library name) */
+ unw_word_t segbase; /* segment base */
+ unw_word_t table_len; /* must be a multiple of sizeof(unw_word_t)! */
+ unw_word_t table_data;
+ }
+unw_dyn_remote_table_info_t;
+
+typedef struct unw_dyn_info
+ {
+ /* doubly-linked list of dyn-info structures: */
+ struct unw_dyn_info *next;
+ struct unw_dyn_info *prev;
+ unw_word_t start_ip; /* first IP covered by this entry */
+ unw_word_t end_ip; /* first IP NOT covered by this entry */
+ unw_word_t gp; /* global-pointer in effect for this entry */
+ int32_t format; /* real type: unw_dyn_info_format_t */
+ int32_t pad;
+ union
+ {
+ unw_dyn_proc_info_t pi;
+ unw_dyn_table_info_t ti;
+ unw_dyn_remote_table_info_t rti;
+ }
+ u;
+ }
+unw_dyn_info_t;
+
+typedef struct unw_dyn_info_list
+ {
+ uint32_t version;
+ uint32_t generation;
+ unw_dyn_info_t *first;
+ }
+unw_dyn_info_list_t;
+
+/* Return the size (in bytes) of an unw_dyn_region_info_t structure that can
+ hold OP_COUNT ops. */
+#define _U_dyn_region_info_size(op_count) \
+ ((char *) (((unw_dyn_region_info_t *) NULL)->op + (op_count)) \
+ - (char *) NULL)
+
+/* Register the unwind info for a single procedure.
+ This routine is NOT signal-safe. */
+extern void _U_dyn_register (unw_dyn_info_t *);
+
+/* Cancel the unwind info for a single procedure.
+ This routine is NOT signal-safe. */
+extern void _U_dyn_cancel (unw_dyn_info_t *);
+
+
+/* Convenience routines. */
+
+#define _U_dyn_op(_tag, _qp, _when, _reg, _val) \
+ ((unw_dyn_op_t) { (_tag), (_qp), (_reg), (_when), (_val) })
+
+#define _U_dyn_op_save_reg(op, qp, when, reg, dst) \
+ (*(op) = _U_dyn_op (UNW_DYN_SAVE_REG, (qp), (when), (reg), (dst)))
+
+#define _U_dyn_op_spill_fp_rel(op, qp, when, reg, offset) \
+ (*(op) = _U_dyn_op (UNW_DYN_SPILL_FP_REL, (qp), (when), (reg), \
+ (offset)))
+
+#define _U_dyn_op_spill_sp_rel(op, qp, when, reg, offset) \
+ (*(op) = _U_dyn_op (UNW_DYN_SPILL_SP_REL, (qp), (when), (reg), \
+ (offset)))
+
+#define _U_dyn_op_add(op, qp, when, reg, value) \
+ (*(op) = _U_dyn_op (UNW_DYN_ADD, (qp), (when), (reg), (value)))
+
+#define _U_dyn_op_pop_frames(op, qp, when, num_frames) \
+ (*(op) = _U_dyn_op (UNW_DYN_POP_FRAMES, (qp), (when), 0, (num_frames)))
+
+#define _U_dyn_op_label_state(op, label) \
+ (*(op) = _U_dyn_op (UNW_DYN_LABEL_STATE, _U_QP_TRUE, -1, 0, (label)))
+
+#define _U_dyn_op_copy_state(op, label) \
+ (*(op) = _U_dyn_op (UNW_DYN_COPY_STATE, _U_QP_TRUE, -1, 0, (label)))
+
+#define _U_dyn_op_alias(op, qp, when, addr) \
+ (*(op) = _U_dyn_op (UNW_DYN_ALIAS, (qp), (when), 0, (addr)))
+
+#define _U_dyn_op_stop(op) \
+ (*(op) = _U_dyn_op (UNW_DYN_STOP, _U_QP_TRUE, -1, 0, 0))
+
+/* The target-dependent qualifying predicate which is always TRUE. On
+ IA-64, that's p0 (0), on non-predicated architectures, the value is
+ ignored. */
+#define _U_QP_TRUE _U_TDEP_QP_TRUE
diff --git a/src/pal/src/libunwind/include/libunwind-hppa.h b/src/pal/src/libunwind/include/libunwind-hppa.h
new file mode 100644
index 0000000000..7013aa7726
--- /dev/null
+++ b/src/pal/src/libunwind/include/libunwind-hppa.h
@@ -0,0 +1,125 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef LIBUNWIND_H
+#define LIBUNWIND_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include <inttypes.h>
+#include <ucontext.h>
+
+#define UNW_TARGET hppa
+#define UNW_TARGET_HPPA 1
+
+#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
+
+/* This needs to be big enough to accommodate "struct cursor", while
+ leaving some slack for future expansion. Changing this value will
+ require recompiling all users of this library. Stack allocation is
+ relatively cheap and unwind-state copying is relatively rare, so we
+ want to err on making it rather too big than too small. */
+#define UNW_TDEP_CURSOR_LEN 511
+
+typedef uint32_t unw_word_t;
+typedef int32_t unw_sword_t;
+
+typedef union
+ {
+ struct { unw_word_t bits[2]; } raw;
+ double val;
+ }
+unw_tdep_fpreg_t;
+
+typedef enum
+ {
+ /* Note: general registers are expected to start with index 0.
+ This convention facilitates architecture-independent
+ implementation of the C++ exception handling ABI. See
+ _Unwind_SetGR() and _Unwind_GetGR() for details. */
+ UNW_HPPA_GR = 0,
+ UNW_HPPA_RP = 2, /* return pointer */
+ UNW_HPPA_FP = 3, /* frame pointer */
+ UNW_HPPA_SP = UNW_HPPA_GR + 30,
+
+ UNW_HPPA_FR = UNW_HPPA_GR + 32,
+
+ UNW_HPPA_IP = UNW_HPPA_FR + 32, /* instruction pointer */
+
+ /* other "preserved" registers (fpsr etc.)... */
+
+ /* PA-RISC has 4 exception-argument registers but they're not
+ contiguous. To deal with this, we define 4 pseudo
+ exception-handling registers which we then alias to the actual
+ physical register. */
+
+ UNW_HPPA_EH0 = UNW_HPPA_IP + 1, /* alias for UNW_HPPA_GR + 20 */
+ UNW_HPPA_EH1 = UNW_HPPA_EH0 + 1, /* alias for UNW_HPPA_GR + 21 */
+ UNW_HPPA_EH2 = UNW_HPPA_EH1 + 1, /* alias for UNW_HPPA_GR + 22 */
+ UNW_HPPA_EH3 = UNW_HPPA_EH2 + 1, /* alias for UNW_HPPA_GR + 31 */
+
+ /* frame info (read-only) */
+ UNW_HPPA_CFA,
+
+ UNW_TDEP_LAST_REG = UNW_HPPA_IP,
+
+ UNW_TDEP_IP = UNW_HPPA_IP,
+ UNW_TDEP_SP = UNW_HPPA_SP,
+ UNW_TDEP_EH = UNW_HPPA_EH0
+ }
+hppa_regnum_t;
+
+#define UNW_TDEP_NUM_EH_REGS 4
+
+typedef struct unw_tdep_save_loc
+ {
+ /* Additional target-dependent info on a save location. */
+ }
+unw_tdep_save_loc_t;
+
+/* On PA-RISC, we can directly use ucontext_t as the unwind context. */
+typedef ucontext_t unw_tdep_context_t;
+
+#define unw_tdep_is_fpreg(r) ((unsigned) ((r) - UNW_HPPA_FR) < 32)
+
+#include "libunwind-dynamic.h"
+
+typedef struct
+ {
+ /* no PA-RISC-specific auxiliary proc-info */
+ }
+unw_tdep_proc_info_t;
+
+#include "libunwind-common.h"
+
+#define unw_tdep_getcontext UNW_ARCH_OBJ (getcontext)
+extern int unw_tdep_getcontext (unw_tdep_context_t *);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* LIBUNWIND_H */
diff --git a/src/pal/src/libunwind/include/libunwind-ia64.h b/src/pal/src/libunwind/include/libunwind-ia64.h
new file mode 100644
index 0000000000..0cc4f39eaa
--- /dev/null
+++ b/src/pal/src/libunwind/include/libunwind-ia64.h
@@ -0,0 +1,194 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef LIBUNWIND_H
+#define LIBUNWIND_H
+
+#include <inttypes.h>
+#include <ucontext.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#ifdef ia64
+ /* This works around a bug in Intel's ECC v7.0 which defines "ia64"
+ as "1". */
+# undef ia64
+#endif
+
+#ifdef __hpux
+ /* On HP-UX, there is no hope of supporting UNW_LOCAL_ONLY, because
+ it's impossible to obtain the address of the members in the
+ sigcontext structure. */
+# undef UNW_LOCAL_ONLY
+# define UNW_GENERIC_ONLY
+#endif
+
+#define UNW_TARGET ia64
+#define UNW_TARGET_IA64 1
+
+#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
+
+/* This needs to be big enough to accommodate "struct cursor", while
+ leaving some slack for future expansion. Changing this value will
+ require recompiling all users of this library. Stack allocation is
+ relatively cheap and unwind-state copying is relatively rare, so we
+ want to err on making it rather too big than too small. */
+#define UNW_TDEP_CURSOR_LEN 511
+
+/* If this bit is it indicates that the procedure saved all of ar.bsp,
+ ar.bspstore, and ar.rnat. If, additionally, ar.bsp != saved ar.bsp,
+ then this procedure has performed a register-backing-store switch. */
+#define UNW_PI_FLAG_IA64_RBS_SWITCH_BIT (UNW_PI_FLAG_FIRST_TDEP_BIT + 0)
+
+#define UNW_PI_FLAG_IA64_RBS_SWITCH (1 << UNW_PI_FLAG_IA64_RBS_SWITCH_BIT)
+
+typedef uint64_t unw_word_t;
+typedef int64_t unw_sword_t;
+
+/* On IA-64, we want to access the contents of floating-point
+ registers as a pair of "words", but to ensure 16-byte alignment, we
+ make it a union that contains a "long double". This will do the
+ Right Thing on all known IA-64 platforms, including HP-UX. */
+typedef union
+ {
+ struct { unw_word_t bits[2]; } raw;
+ long double dummy; /* dummy to force 16-byte alignment */
+ }
+unw_tdep_fpreg_t;
+
+typedef struct
+ {
+ /* no ia64-specific auxiliary proc-info */
+ }
+unw_tdep_proc_info_t;
+
+typedef enum
+ {
+ /* Note: general registers are excepted to start with index 0.
+ This convention facilitates architecture-independent
+ implementation of the C++ exception handling ABI. See
+ _Unwind_SetGR() and _Unwind_GetGR() for details. */
+ UNW_IA64_GR = 0, /* general registers (r0..r127) */
+ UNW_IA64_GP = UNW_IA64_GR + 1,
+ UNW_IA64_TP = UNW_IA64_GR + 13,
+
+ UNW_IA64_NAT = UNW_IA64_GR + 128, /* NaT registers (nat0..nat127) */
+
+ UNW_IA64_FR = UNW_IA64_NAT + 128, /* fp registers (f0..f127) */
+
+ UNW_IA64_AR = UNW_IA64_FR + 128, /* application registers (ar0..r127) */
+ UNW_IA64_AR_RSC = UNW_IA64_AR + 16,
+ UNW_IA64_AR_BSP = UNW_IA64_AR + 17,
+ UNW_IA64_AR_BSPSTORE = UNW_IA64_AR + 18,
+ UNW_IA64_AR_RNAT = UNW_IA64_AR + 19,
+ UNW_IA64_AR_CSD = UNW_IA64_AR + 25,
+ UNW_IA64_AR_26 = UNW_IA64_AR + 26,
+ UNW_IA64_AR_SSD = UNW_IA64_AR_26,
+ UNW_IA64_AR_CCV = UNW_IA64_AR + 32,
+ UNW_IA64_AR_UNAT = UNW_IA64_AR + 36,
+ UNW_IA64_AR_FPSR = UNW_IA64_AR + 40,
+ UNW_IA64_AR_PFS = UNW_IA64_AR + 64,
+ UNW_IA64_AR_LC = UNW_IA64_AR + 65,
+ UNW_IA64_AR_EC = UNW_IA64_AR + 66,
+
+ UNW_IA64_BR = UNW_IA64_AR + 128, /* branch registers (b0..p7) */
+ UNW_IA64_RP = UNW_IA64_BR + 0, /* return pointer (rp) */
+ UNW_IA64_PR = UNW_IA64_BR + 8, /* predicate registers (p0..p63) */
+ UNW_IA64_CFM,
+
+ /* frame info: */
+ UNW_IA64_BSP,
+ UNW_IA64_IP,
+ UNW_IA64_SP,
+
+ UNW_TDEP_LAST_REG = UNW_IA64_SP,
+
+ UNW_TDEP_IP = UNW_IA64_IP,
+ UNW_TDEP_SP = UNW_IA64_SP,
+ UNW_TDEP_EH = UNW_IA64_GR + 15
+ }
+ia64_regnum_t;
+
+#define UNW_TDEP_NUM_EH_REGS 4 /* r15-r18 are exception args */
+
+typedef struct unw_tdep_save_loc
+ {
+ /* Additional target-dependent info on a save location. On IA-64,
+ we use this to provide the bit number in which a NaT bit gets
+ saved. */
+ uint8_t nat_bitnr;
+
+ /* Padding reserved for future use. */
+ uint8_t reserved[7];
+ }
+unw_tdep_save_loc_t;
+
+/* On IA-64, we can directly use ucontext_t as the unwind context. */
+typedef ucontext_t unw_tdep_context_t;
+
+#define unw_tdep_is_fpreg(r) ((unsigned) ((r) - UNW_IA64_FR) < 128)
+
+#include "libunwind-dynamic.h"
+#include "libunwind-common.h"
+
+#ifdef __hpux
+ /* In theory, we could use _Uia64_getcontext() on HP-UX as well, but
+ the benefit of doing so would be marginal given that it can't
+ support UNW_LOCAL_ONLY. */
+# define unw_tdep_getcontext getcontext
+#else
+# define unw_tdep_getcontext UNW_ARCH_OBJ (getcontext)
+ extern int unw_tdep_getcontext (unw_tdep_context_t *);
+#endif
+
+/* This is a helper routine to search an ia64 unwind table. If the
+ address-space argument AS points to something other than the local
+ address-space, the memory for the unwind-info will be allocated
+ with malloc(), and should be free()d during the put_unwind_info()
+ callback. This routine is signal-safe for the local-address-space
+ case ONLY. */
+#define unw_search_ia64_unwind_table UNW_OBJ(search_unwind_table)
+extern int unw_search_ia64_unwind_table (unw_addr_space_t, unw_word_t,
+ unw_dyn_info_t *, unw_proc_info_t *,
+ int, void *);
+
+/* This is a helper routine which the get_dyn_info_list_addr()
+ callback can use to locate the special dynamic-info list entry in
+ an IA-64 unwind table. If the entry exists in the table, the
+ list-address is returned. In all other cases, 0 is returned. */
+extern unw_word_t _Uia64_find_dyn_list (unw_addr_space_t, unw_dyn_info_t *,
+ void *);
+
+/* This is a helper routine to obtain the kernel-unwind info. It is
+ signal-safe. */
+extern int _Uia64_get_kernel_table (unw_dyn_info_t *);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* LIBUNWIND_H */
diff --git a/src/pal/src/libunwind/include/libunwind-mips.h b/src/pal/src/libunwind/include/libunwind-mips.h
new file mode 100644
index 0000000000..97c95e2463
--- /dev/null
+++ b/src/pal/src/libunwind/include/libunwind-mips.h
@@ -0,0 +1,160 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef LIBUNWIND_H
+#define LIBUNWIND_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include <inttypes.h>
+#include <sys/ucontext.h>
+
+#ifdef mips
+# undef mips
+#endif
+
+#define UNW_TARGET mips
+#define UNW_TARGET_MIPS 1
+
+#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
+
+/* This needs to be big enough to accommodate "struct cursor", while
+ leaving some slack for future expansion. Changing this value will
+ require recompiling all users of this library. Stack allocation is
+ relatively cheap and unwind-state copying is relatively rare, so we
+ want to err on making it rather too big than too small. */
+
+/* FIXME for MIPS. Too big? What do other things use for similar tasks? */
+#define UNW_TDEP_CURSOR_LEN 4096
+
+/* The size of a "word" varies on MIPS. This type is used for memory
+ addresses and register values, which are 32-bit wide for O32 and N32
+ ABIs, and 64-bit wide for N64 ABI. */
+#if _MIPS_SIM == _ABI64
+typedef uint64_t unw_word_t;
+#else
+typedef uint32_t unw_word_t;
+#endif
+typedef int32_t unw_sword_t;
+
+/* FIXME: MIPS ABIs. */
+typedef long double unw_tdep_fpreg_t;
+
+typedef enum
+ {
+ UNW_MIPS_R0,
+ UNW_MIPS_R1,
+ UNW_MIPS_R2,
+ UNW_MIPS_R3,
+ UNW_MIPS_R4,
+ UNW_MIPS_R5,
+ UNW_MIPS_R6,
+ UNW_MIPS_R7,
+ UNW_MIPS_R8,
+ UNW_MIPS_R9,
+ UNW_MIPS_R10,
+ UNW_MIPS_R11,
+ UNW_MIPS_R12,
+ UNW_MIPS_R13,
+ UNW_MIPS_R14,
+ UNW_MIPS_R15,
+ UNW_MIPS_R16,
+ UNW_MIPS_R17,
+ UNW_MIPS_R18,
+ UNW_MIPS_R19,
+ UNW_MIPS_R20,
+ UNW_MIPS_R21,
+ UNW_MIPS_R22,
+ UNW_MIPS_R23,
+ UNW_MIPS_R24,
+ UNW_MIPS_R25,
+ UNW_MIPS_R26,
+ UNW_MIPS_R27,
+ UNW_MIPS_R28,
+ UNW_MIPS_R29,
+ UNW_MIPS_R30,
+ UNW_MIPS_R31,
+
+ UNW_MIPS_PC = 34,
+
+ /* FIXME: Other registers! */
+
+ /* For MIPS, the CFA is the value of SP (r29) at the call site in the
+ previous frame. */
+ UNW_MIPS_CFA,
+
+ UNW_TDEP_LAST_REG = UNW_MIPS_PC,
+
+ UNW_TDEP_IP = UNW_MIPS_R31,
+ UNW_TDEP_SP = UNW_MIPS_R29,
+ UNW_TDEP_EH = UNW_MIPS_R0 /* FIXME. */
+ }
+mips_regnum_t;
+
+typedef enum
+ {
+ UNW_MIPS_ABI_O32,
+ UNW_MIPS_ABI_N32,
+ UNW_MIPS_ABI_N64
+ }
+mips_abi_t;
+
+#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for MIPS. */
+
+typedef struct unw_tdep_save_loc
+ {
+ /* Additional target-dependent info on a save location. */
+ }
+unw_tdep_save_loc_t;
+
+/* On x86, we can directly use ucontext_t as the unwind context. FIXME for
+ MIPS. */
+typedef ucontext_t unw_tdep_context_t;
+
+#include "libunwind-dynamic.h"
+
+typedef struct
+ {
+ /* no mips-specific auxiliary proc-info */
+ }
+unw_tdep_proc_info_t;
+
+#include "libunwind-common.h"
+
+/* There is no getcontext() on MIPS. Use a stub version which only saves GP
+ registers. FIXME: Not ideal, may not be sufficient for all libunwind
+ use cases. */
+#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext)
+extern int unw_tdep_getcontext (ucontext_t *uc);
+
+#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
+extern int unw_tdep_is_fpreg (int);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* LIBUNWIND_H */
diff --git a/src/pal/src/libunwind/include/libunwind-ppc32.h b/src/pal/src/libunwind/include/libunwind-ppc32.h
new file mode 100644
index 0000000000..47ebfde5a3
--- /dev/null
+++ b/src/pal/src/libunwind/include/libunwind-ppc32.h
@@ -0,0 +1,207 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+ Copied from libunwind-x86_64.h, modified slightly for building
+ frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
+ Will be replaced when libunwind is ready on ppc64 platform.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef LIBUNWIND_H
+#define LIBUNWIND_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include <inttypes.h>
+#include <ucontext.h>
+
+#define UNW_TARGET ppc32
+#define UNW_TARGET_PPC32 1
+
+#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
+
+/*
+ * This needs to be big enough to accommodate "struct cursor", while
+ * leaving some slack for future expansion. Changing this value will
+ * require recompiling all users of this library. Stack allocation is
+ * relatively cheap and unwind-state copying is relatively rare, so we want
+ * to err on making it rather too big than too small.
+ *
+ * To simplify this whole process, we are at least initially taking the
+ * tack that UNW_PPC32_* map straight across to the .eh_frame column register
+ * numbers. These register numbers come from gcc's source in
+ * gcc/config/rs6000/rs6000.h
+ *
+ * UNW_TDEP_CURSOR_LEN is in terms of unw_word_t size. Since we have 115
+ * elements in the loc array, each sized 2 * unw_word_t, plus the rest of
+ * the cursor struct, this puts us at about 2 * 115 + 40 = 270. Let's
+ * round that up to 280.
+ */
+
+#define UNW_TDEP_CURSOR_LEN 280
+
+#if __WORDSIZE==32
+typedef uint32_t unw_word_t;
+typedef int32_t unw_sword_t;
+#else
+typedef uint64_t unw_word_t;
+typedef int64_t unw_sword_t;
+#endif
+
+typedef long double unw_tdep_fpreg_t;
+
+typedef enum
+ {
+ UNW_PPC32_R0,
+ UNW_PPC32_R1, /* called STACK_POINTER in gcc */
+ UNW_PPC32_R2,
+ UNW_PPC32_R3,
+ UNW_PPC32_R4,
+ UNW_PPC32_R5,
+ UNW_PPC32_R6,
+ UNW_PPC32_R7,
+ UNW_PPC32_R8,
+ UNW_PPC32_R9,
+ UNW_PPC32_R10,
+ UNW_PPC32_R11, /* called STATIC_CHAIN in gcc */
+ UNW_PPC32_R12,
+ UNW_PPC32_R13,
+ UNW_PPC32_R14,
+ UNW_PPC32_R15,
+ UNW_PPC32_R16,
+ UNW_PPC32_R17,
+ UNW_PPC32_R18,
+ UNW_PPC32_R19,
+ UNW_PPC32_R20,
+ UNW_PPC32_R21,
+ UNW_PPC32_R22,
+ UNW_PPC32_R23,
+ UNW_PPC32_R24,
+ UNW_PPC32_R25,
+ UNW_PPC32_R26,
+ UNW_PPC32_R27,
+ UNW_PPC32_R28,
+ UNW_PPC32_R29,
+ UNW_PPC32_R30,
+ UNW_PPC32_R31, /* called HARD_FRAME_POINTER in gcc */
+
+ /* Count Register */
+ UNW_PPC32_CTR = 32,
+ /* Fixed-Point Status and Control Register */
+ UNW_PPC32_XER = 33,
+ /* Condition Register */
+ UNW_PPC32_CCR = 34,
+ /* Machine State Register */
+ //UNW_PPC32_MSR = 35,
+ /* MQ or SPR0, not part of generic Power, part of MPC601 */
+ //UNW_PPC32_MQ = 36,
+ /* Link Register */
+ UNW_PPC32_LR = 36,
+ /* Floating Pointer Status and Control Register */
+ UNW_PPC32_FPSCR = 37,
+
+ UNW_PPC32_F0 = 48,
+ UNW_PPC32_F1,
+ UNW_PPC32_F2,
+ UNW_PPC32_F3,
+ UNW_PPC32_F4,
+ UNW_PPC32_F5,
+ UNW_PPC32_F6,
+ UNW_PPC32_F7,
+ UNW_PPC32_F8,
+ UNW_PPC32_F9,
+ UNW_PPC32_F10,
+ UNW_PPC32_F11,
+ UNW_PPC32_F12,
+ UNW_PPC32_F13,
+ UNW_PPC32_F14,
+ UNW_PPC32_F15,
+ UNW_PPC32_F16,
+ UNW_PPC32_F17,
+ UNW_PPC32_F18,
+ UNW_PPC32_F19,
+ UNW_PPC32_F20,
+ UNW_PPC32_F21,
+ UNW_PPC32_F22,
+ UNW_PPC32_F23,
+ UNW_PPC32_F24,
+ UNW_PPC32_F25,
+ UNW_PPC32_F26,
+ UNW_PPC32_F27,
+ UNW_PPC32_F28,
+ UNW_PPC32_F29,
+ UNW_PPC32_F30,
+ UNW_PPC32_F31,
+
+ UNW_TDEP_LAST_REG = UNW_PPC32_F31,
+
+ UNW_TDEP_IP = UNW_PPC32_LR,
+ UNW_TDEP_SP = UNW_PPC32_R1,
+ UNW_TDEP_EH = UNW_PPC32_R12
+ }
+ppc32_regnum_t;
+
+/*
+ * According to David Edelsohn, GNU gcc uses R3, R4, R5, and maybe R6 for
+ * passing parameters to exception handlers.
+ */
+
+#define UNW_TDEP_NUM_EH_REGS 4
+
+typedef struct unw_tdep_save_loc
+ {
+ /* Additional target-dependent info on a save location. */
+ }
+unw_tdep_save_loc_t;
+
+/* On ppc, we can directly use ucontext_t as the unwind context. */
+typedef ucontext_t unw_tdep_context_t;
+
+/* XXX this is not ideal: an application should not be prevented from
+ using the "getcontext" name just because it's using libunwind. We
+ can't just use __getcontext() either, because that isn't exported
+ by glibc... */
+#define unw_tdep_getcontext(uc) (getcontext (uc), 0)
+
+#include "libunwind-dynamic.h"
+
+typedef struct
+ {
+ /* no ppc32-specific auxiliary proc-info */
+ }
+unw_tdep_proc_info_t;
+
+#include "libunwind-common.h"
+
+#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
+extern int unw_tdep_is_fpreg (int);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* LIBUNWIND_H */
diff --git a/src/pal/src/libunwind/include/libunwind-ppc64.h b/src/pal/src/libunwind/include/libunwind-ppc64.h
new file mode 100644
index 0000000000..9944628da0
--- /dev/null
+++ b/src/pal/src/libunwind/include/libunwind-ppc64.h
@@ -0,0 +1,271 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+ Copied from libunwind-x86_64.h, modified slightly for building
+ frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
+ Will be replaced when libunwind is ready on ppc64 platform.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef LIBUNWIND_H
+#define LIBUNWIND_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include <inttypes.h>
+#include <ucontext.h>
+
+#define UNW_TARGET ppc64
+#define UNW_TARGET_PPC64 1
+
+#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
+
+/*
+ * This needs to be big enough to accommodate "struct cursor", while
+ * leaving some slack for future expansion. Changing this value will
+ * require recompiling all users of this library. Stack allocation is
+ * relatively cheap and unwind-state copying is relatively rare, so we want
+ * to err on making it rather too big than too small.
+ *
+ * To simplify this whole process, we are at least initially taking the
+ * tack that UNW_PPC64_* map straight across to the .eh_frame column register
+ * numbers. These register numbers come from gcc's source in
+ * gcc/config/rs6000/rs6000.h
+ *
+ * UNW_TDEP_CURSOR_LEN is in terms of unw_word_t size. Since we have 115
+ * elements in the loc array, each sized 2 * unw_word_t, plus the rest of
+ * the cursor struct, this puts us at about 2 * 115 + 40 = 270. Let's
+ * round that up to 280.
+ */
+
+#define UNW_TDEP_CURSOR_LEN 280
+
+#if __WORDSIZE==32
+typedef uint32_t unw_word_t;
+typedef int32_t unw_sword_t;
+#else
+typedef uint64_t unw_word_t;
+typedef int64_t unw_sword_t;
+#endif
+
+typedef long double unw_tdep_fpreg_t;
+
+/*
+ * Vector register (in PowerPC64 used for AltiVec registers)
+ */
+typedef struct {
+ uint64_t halves[2];
+} unw_tdep_vreg_t;
+
+typedef enum
+ {
+ UNW_PPC64_R0,
+ UNW_PPC64_R1, /* called STACK_POINTER in gcc */
+ UNW_PPC64_R2,
+ UNW_PPC64_R3,
+ UNW_PPC64_R4,
+ UNW_PPC64_R5,
+ UNW_PPC64_R6,
+ UNW_PPC64_R7,
+ UNW_PPC64_R8,
+ UNW_PPC64_R9,
+ UNW_PPC64_R10,
+ UNW_PPC64_R11, /* called STATIC_CHAIN in gcc */
+ UNW_PPC64_R12,
+ UNW_PPC64_R13,
+ UNW_PPC64_R14,
+ UNW_PPC64_R15,
+ UNW_PPC64_R16,
+ UNW_PPC64_R17,
+ UNW_PPC64_R18,
+ UNW_PPC64_R19,
+ UNW_PPC64_R20,
+ UNW_PPC64_R21,
+ UNW_PPC64_R22,
+ UNW_PPC64_R23,
+ UNW_PPC64_R24,
+ UNW_PPC64_R25,
+ UNW_PPC64_R26,
+ UNW_PPC64_R27,
+ UNW_PPC64_R28,
+ UNW_PPC64_R29,
+ UNW_PPC64_R30,
+ UNW_PPC64_R31, /* called HARD_FRAME_POINTER in gcc */
+
+ UNW_PPC64_F0 = 32,
+ UNW_PPC64_F1,
+ UNW_PPC64_F2,
+ UNW_PPC64_F3,
+ UNW_PPC64_F4,
+ UNW_PPC64_F5,
+ UNW_PPC64_F6,
+ UNW_PPC64_F7,
+ UNW_PPC64_F8,
+ UNW_PPC64_F9,
+ UNW_PPC64_F10,
+ UNW_PPC64_F11,
+ UNW_PPC64_F12,
+ UNW_PPC64_F13,
+ UNW_PPC64_F14,
+ UNW_PPC64_F15,
+ UNW_PPC64_F16,
+ UNW_PPC64_F17,
+ UNW_PPC64_F18,
+ UNW_PPC64_F19,
+ UNW_PPC64_F20,
+ UNW_PPC64_F21,
+ UNW_PPC64_F22,
+ UNW_PPC64_F23,
+ UNW_PPC64_F24,
+ UNW_PPC64_F25,
+ UNW_PPC64_F26,
+ UNW_PPC64_F27,
+ UNW_PPC64_F28,
+ UNW_PPC64_F29,
+ UNW_PPC64_F30,
+ UNW_PPC64_F31,
+ /* Note that there doesn't appear to be an .eh_frame register column
+ for the FPSCR register. I don't know why this is. Since .eh_frame
+ info is what this implementation uses for unwinding, we have no way
+ to unwind this register, and so we will not expose an FPSCR register
+ number in the libunwind API.
+ */
+
+ UNW_PPC64_LR = 65,
+ UNW_PPC64_CTR = 66,
+ UNW_PPC64_ARG_POINTER = 67,
+
+ UNW_PPC64_CR0 = 68,
+ UNW_PPC64_CR1,
+ UNW_PPC64_CR2,
+ UNW_PPC64_CR3,
+ UNW_PPC64_CR4,
+ /* CR5 .. CR7 are currently unused */
+ UNW_PPC64_CR5,
+ UNW_PPC64_CR6,
+ UNW_PPC64_CR7,
+
+ UNW_PPC64_XER = 76,
+
+ UNW_PPC64_V0 = 77,
+ UNW_PPC64_V1,
+ UNW_PPC64_V2,
+ UNW_PPC64_V3,
+ UNW_PPC64_V4,
+ UNW_PPC64_V5,
+ UNW_PPC64_V6,
+ UNW_PPC64_V7,
+ UNW_PPC64_V8,
+ UNW_PPC64_V9,
+ UNW_PPC64_V10,
+ UNW_PPC64_V11,
+ UNW_PPC64_V12,
+ UNW_PPC64_V13,
+ UNW_PPC64_V14,
+ UNW_PPC64_V15,
+ UNW_PPC64_V16,
+ UNW_PPC64_V17,
+ UNW_PPC64_V18,
+ UNW_PPC64_V19,
+ UNW_PPC64_V20,
+ UNW_PPC64_V21,
+ UNW_PPC64_V22,
+ UNW_PPC64_V23,
+ UNW_PPC64_V24,
+ UNW_PPC64_V25,
+ UNW_PPC64_V26,
+ UNW_PPC64_V27,
+ UNW_PPC64_V28,
+ UNW_PPC64_V29,
+ UNW_PPC64_V30,
+ UNW_PPC64_V31,
+
+ UNW_PPC64_VRSAVE = 109,
+ UNW_PPC64_VSCR = 110,
+ UNW_PPC64_SPE_ACC = 111,
+ UNW_PPC64_SPEFSCR = 112,
+
+ /* frame info (read-only) */
+ UNW_PPC64_FRAME_POINTER,
+ UNW_PPC64_NIP,
+
+
+ UNW_TDEP_LAST_REG = UNW_PPC64_NIP,
+
+ UNW_TDEP_IP = UNW_PPC64_NIP,
+ UNW_TDEP_SP = UNW_PPC64_R1,
+ UNW_TDEP_EH = UNW_PPC64_R12
+ }
+ppc64_regnum_t;
+
+typedef enum
+ {
+ UNW_PPC64_ABI_ELFv1,
+ UNW_PPC64_ABI_ELFv2
+ }
+ppc64_abi_t;
+
+/*
+ * According to David Edelsohn, GNU gcc uses R3, R4, R5, and maybe R6 for
+ * passing parameters to exception handlers.
+ */
+
+#define UNW_TDEP_NUM_EH_REGS 4
+
+typedef struct unw_tdep_save_loc
+ {
+ /* Additional target-dependent info on a save location. */
+ }
+unw_tdep_save_loc_t;
+
+/* On ppc64, we can directly use ucontext_t as the unwind context. */
+typedef ucontext_t unw_tdep_context_t;
+
+/* XXX this is not ideal: an application should not be prevented from
+ using the "getcontext" name just because it's using libunwind. We
+ can't just use __getcontext() either, because that isn't exported
+ by glibc... */
+#define unw_tdep_getcontext(uc) (getcontext (uc), 0)
+
+#include "libunwind-dynamic.h"
+
+typedef struct
+ {
+ /* no ppc64-specific auxiliary proc-info */
+ }
+unw_tdep_proc_info_t;
+
+#include "libunwind-common.h"
+
+#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
+extern int unw_tdep_is_fpreg (int);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* LIBUNWIND_H */
diff --git a/src/pal/src/libunwind/include/libunwind-ptrace.h b/src/pal/src/libunwind/include/libunwind-ptrace.h
new file mode 100644
index 0000000000..801325c4d4
--- /dev/null
+++ b/src/pal/src/libunwind/include/libunwind-ptrace.h
@@ -0,0 +1,63 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef libunwind_ptrace_h
+#define libunwind_ptrace_h
+
+#include <libunwind.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+/* Helper routines which make it easy to use libunwind via ptrace().
+ They're available only if UNW_REMOTE_ONLY is _not_ defined and they
+ aren't really part of the libunwind API. They are implemented in a
+ archive library called libunwind-ptrace.a. */
+
+extern void *_UPT_create (pid_t);
+extern void _UPT_destroy (void *);
+extern int _UPT_find_proc_info (unw_addr_space_t, unw_word_t,
+ unw_proc_info_t *, int, void *);
+extern void _UPT_put_unwind_info (unw_addr_space_t, unw_proc_info_t *, void *);
+extern int _UPT_get_dyn_info_list_addr (unw_addr_space_t, unw_word_t *,
+ void *);
+extern int _UPT_access_mem (unw_addr_space_t, unw_word_t, unw_word_t *, int,
+ void *);
+extern int _UPT_access_reg (unw_addr_space_t, unw_regnum_t, unw_word_t *,
+ int, void *);
+extern int _UPT_access_fpreg (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *,
+ int, void *);
+extern int _UPT_get_proc_name (unw_addr_space_t, unw_word_t, char *, size_t,
+ unw_word_t *, void *);
+extern int _UPT_resume (unw_addr_space_t, unw_cursor_t *, void *);
+extern unw_accessors_t _UPT_accessors;
+
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* libunwind_ptrace_h */
diff --git a/src/pal/src/libunwind/include/libunwind-sh.h b/src/pal/src/libunwind/include/libunwind-sh.h
new file mode 100644
index 0000000000..927f61ff42
--- /dev/null
+++ b/src/pal/src/libunwind/include/libunwind-sh.h
@@ -0,0 +1,114 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef LIBUNWIND_H
+#define LIBUNWIND_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <ucontext.h>
+
+#define UNW_TARGET sh
+#define UNW_TARGET_SH 1
+
+#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
+
+/* This needs to be big enough to accommodate "struct cursor", while
+ leaving some slack for future expansion. Changing this value will
+ require recompiling all users of this library. Stack allocation is
+ relatively cheap and unwind-state copying is relatively rare, so we
+ want to err on making it rather too big than too small. */
+
+#define UNW_TDEP_CURSOR_LEN 4096
+
+typedef uint32_t unw_word_t;
+typedef int32_t unw_sword_t;
+
+typedef long double unw_tdep_fpreg_t;
+
+typedef enum
+ {
+ UNW_SH_R0,
+ UNW_SH_R1,
+ UNW_SH_R2,
+ UNW_SH_R3,
+ UNW_SH_R4,
+ UNW_SH_R5,
+ UNW_SH_R6,
+ UNW_SH_R7,
+ UNW_SH_R8,
+ UNW_SH_R9,
+ UNW_SH_R10,
+ UNW_SH_R11,
+ UNW_SH_R12,
+ UNW_SH_R13,
+ UNW_SH_R14,
+ UNW_SH_R15,
+
+ UNW_SH_PC,
+ UNW_SH_PR,
+
+ UNW_TDEP_LAST_REG = UNW_SH_PR,
+
+ UNW_TDEP_IP = UNW_SH_PR,
+ UNW_TDEP_SP = UNW_SH_R15,
+ UNW_TDEP_EH = UNW_SH_R0
+ }
+sh_regnum_t;
+
+#define UNW_TDEP_NUM_EH_REGS 2
+
+typedef ucontext_t unw_tdep_context_t;
+
+#define unw_tdep_getcontext(uc) (getcontext (uc), 0)
+
+typedef struct unw_tdep_save_loc
+ {
+ /* Additional target-dependent info on a save location. */
+ }
+unw_tdep_save_loc_t;
+
+#include "libunwind-dynamic.h"
+
+typedef struct
+ {
+ /* no sh-specific auxiliary proc-info */
+ }
+unw_tdep_proc_info_t;
+
+#include "libunwind-common.h"
+
+#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
+extern int unw_tdep_is_fpreg (int);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* LIBUNWIND_H */
diff --git a/src/pal/src/libunwind/include/libunwind-tilegx.h b/src/pal/src/libunwind/include/libunwind-tilegx.h
new file mode 100644
index 0000000000..0f84ea65ee
--- /dev/null
+++ b/src/pal/src/libunwind/include/libunwind-tilegx.h
@@ -0,0 +1,161 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2014 Tilera Corp.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef LIBUNWIND_H
+#define LIBUNWIND_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include <inttypes.h>
+#include <ucontext.h>
+
+#define UNW_TARGET tilegx
+#define UNW_TARGET_TILEGX 1
+
+#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
+
+/* This needs to be big enough to accommodate "struct cursor", while
+ leaving some slack for future expansion. Changing this value will
+ require recompiling all users of this library. Stack allocation is
+ relatively cheap and unwind-state copying is relatively rare, so we
+ want to err on making it rather too big than too small. */
+
+#define UNW_TDEP_CURSOR_LEN 4096
+
+/* The size of a "word" varies on TILEGX. This type is used for memory
+ addresses and register values. */
+typedef uint64_t unw_word_t;
+typedef int64_t unw_sword_t;
+
+typedef long double unw_tdep_fpreg_t;
+
+typedef enum
+{
+ UNW_TILEGX_R0,
+ UNW_TILEGX_R1,
+ UNW_TILEGX_R2,
+ UNW_TILEGX_R3,
+ UNW_TILEGX_R4,
+ UNW_TILEGX_R5,
+ UNW_TILEGX_R6,
+ UNW_TILEGX_R7,
+ UNW_TILEGX_R8,
+ UNW_TILEGX_R9,
+ UNW_TILEGX_R10,
+ UNW_TILEGX_R11,
+ UNW_TILEGX_R12,
+ UNW_TILEGX_R13,
+ UNW_TILEGX_R14,
+ UNW_TILEGX_R15,
+ UNW_TILEGX_R16,
+ UNW_TILEGX_R17,
+ UNW_TILEGX_R18,
+ UNW_TILEGX_R19,
+ UNW_TILEGX_R20,
+ UNW_TILEGX_R21,
+ UNW_TILEGX_R22,
+ UNW_TILEGX_R23,
+ UNW_TILEGX_R24,
+ UNW_TILEGX_R25,
+ UNW_TILEGX_R26,
+ UNW_TILEGX_R27,
+ UNW_TILEGX_R28,
+ UNW_TILEGX_R29,
+ UNW_TILEGX_R30,
+ UNW_TILEGX_R31,
+ UNW_TILEGX_R32,
+ UNW_TILEGX_R33,
+ UNW_TILEGX_R34,
+ UNW_TILEGX_R35,
+ UNW_TILEGX_R36,
+ UNW_TILEGX_R37,
+ UNW_TILEGX_R38,
+ UNW_TILEGX_R39,
+ UNW_TILEGX_R40,
+ UNW_TILEGX_R41,
+ UNW_TILEGX_R42,
+ UNW_TILEGX_R43,
+ UNW_TILEGX_R44,
+ UNW_TILEGX_R45,
+ UNW_TILEGX_R46,
+ UNW_TILEGX_R47,
+ UNW_TILEGX_R48,
+ UNW_TILEGX_R49,
+ UNW_TILEGX_R50,
+ UNW_TILEGX_R51,
+ UNW_TILEGX_R52,
+ UNW_TILEGX_R53,
+ UNW_TILEGX_R54,
+ UNW_TILEGX_R55,
+
+ /* FIXME: Other registers! */
+
+ UNW_TILEGX_PC,
+ /* For TILEGX, the CFA is the value of SP (r54) at the call site in the
+ previous frame. */
+ UNW_TILEGX_CFA,
+
+ UNW_TDEP_LAST_REG = UNW_TILEGX_PC,
+
+ UNW_TDEP_IP = UNW_TILEGX_R55, /* R55 is link register for Tilegx */
+ UNW_TDEP_SP = UNW_TILEGX_R54,
+ UNW_TDEP_EH = UNW_TILEGX_R0 /* FIXME. */
+} tilegx_regnum_t;
+
+typedef enum
+{
+ UNW_TILEGX_ABI_N64 = 2
+} tilegx_abi_t;
+
+#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for TILEGX. */
+
+typedef struct unw_tdep_save_loc
+{
+ /* Additional target-dependent info on a save location. */
+} unw_tdep_save_loc_t;
+
+typedef ucontext_t unw_tdep_context_t;
+
+#include "libunwind-dynamic.h"
+
+typedef struct
+{
+ /* no tilegx-specific auxiliary proc-info */
+} unw_tdep_proc_info_t;
+
+#include "libunwind-common.h"
+
+#define unw_tdep_getcontext getcontext
+
+#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
+extern int unw_tdep_is_fpreg (int);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* LIBUNWIND_H */
diff --git a/src/pal/src/libunwind/include/libunwind-x86.h b/src/pal/src/libunwind/include/libunwind-x86.h
new file mode 100644
index 0000000000..40fe0464f2
--- /dev/null
+++ b/src/pal/src/libunwind/include/libunwind-x86.h
@@ -0,0 +1,187 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef LIBUNWIND_H
+#define LIBUNWIND_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <ucontext.h>
+
+#define UNW_TARGET x86
+#define UNW_TARGET_X86 1
+
+#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
+
+/* This needs to be big enough to accommodate "struct cursor", while
+ leaving some slack for future expansion. Changing this value will
+ require recompiling all users of this library. Stack allocation is
+ relatively cheap and unwind-state copying is relatively rare, so we
+ want to err on making it rather too big than too small. */
+#define UNW_TDEP_CURSOR_LEN 127
+
+typedef uint32_t unw_word_t;
+typedef int32_t unw_sword_t;
+
+typedef union {
+ struct { uint8_t b[4]; } val32;
+ struct { uint8_t b[10]; } val80;
+ struct { uint8_t b[16]; } val128;
+} unw_tdep_fpreg_t;
+
+typedef enum
+ {
+ /* Note: general registers are expected to start with index 0.
+ This convention facilitates architecture-independent
+ implementation of the C++ exception handling ABI. See
+ _Unwind_SetGR() and _Unwind_GetGR() for details.
+
+ The described register usage convention is based on "System V
+ Application Binary Interface, Intel386 Architecture Processor
+ Supplement, Fourth Edition" at
+
+ http://www.linuxbase.org/spec/refspecs/elf/abi386-4.pdf
+
+ It would have been nice to use the same register numbering as
+ DWARF, but that doesn't work because the libunwind requires
+ that the exception argument registers be consecutive, which the
+ wouldn't be with the DWARF numbering. */
+ UNW_X86_EAX, /* scratch (exception argument 1) */
+ UNW_X86_EDX, /* scratch (exception argument 2) */
+ UNW_X86_ECX, /* scratch */
+ UNW_X86_EBX, /* preserved */
+ UNW_X86_ESI, /* preserved */
+ UNW_X86_EDI, /* preserved */
+ UNW_X86_EBP, /* (optional) frame-register */
+ UNW_X86_ESP, /* (optional) frame-register */
+ UNW_X86_EIP, /* frame-register */
+ UNW_X86_EFLAGS, /* scratch (except for "direction", which is fixed */
+ UNW_X86_TRAPNO, /* scratch */
+
+ /* MMX/stacked-fp registers */
+ UNW_X86_ST0, /* fp return value */
+ UNW_X86_ST1, /* scratch */
+ UNW_X86_ST2, /* scratch */
+ UNW_X86_ST3, /* scratch */
+ UNW_X86_ST4, /* scratch */
+ UNW_X86_ST5, /* scratch */
+ UNW_X86_ST6, /* scratch */
+ UNW_X86_ST7, /* scratch */
+
+ UNW_X86_FCW, /* scratch */
+ UNW_X86_FSW, /* scratch */
+ UNW_X86_FTW, /* scratch */
+ UNW_X86_FOP, /* scratch */
+ UNW_X86_FCS, /* scratch */
+ UNW_X86_FIP, /* scratch */
+ UNW_X86_FEA, /* scratch */
+ UNW_X86_FDS, /* scratch */
+
+ /* SSE registers */
+ UNW_X86_XMM0_lo, /* scratch */
+ UNW_X86_XMM0_hi, /* scratch */
+ UNW_X86_XMM1_lo, /* scratch */
+ UNW_X86_XMM1_hi, /* scratch */
+ UNW_X86_XMM2_lo, /* scratch */
+ UNW_X86_XMM2_hi, /* scratch */
+ UNW_X86_XMM3_lo, /* scratch */
+ UNW_X86_XMM3_hi, /* scratch */
+ UNW_X86_XMM4_lo, /* scratch */
+ UNW_X86_XMM4_hi, /* scratch */
+ UNW_X86_XMM5_lo, /* scratch */
+ UNW_X86_XMM5_hi, /* scratch */
+ UNW_X86_XMM6_lo, /* scratch */
+ UNW_X86_XMM6_hi, /* scratch */
+ UNW_X86_XMM7_lo, /* scratch */
+ UNW_X86_XMM7_hi, /* scratch */
+
+ UNW_X86_MXCSR, /* scratch */
+
+ /* segment registers */
+ UNW_X86_GS, /* special */
+ UNW_X86_FS, /* special */
+ UNW_X86_ES, /* special */
+ UNW_X86_DS, /* special */
+ UNW_X86_SS, /* special */
+ UNW_X86_CS, /* special */
+ UNW_X86_TSS, /* special */
+ UNW_X86_LDT, /* special */
+
+ /* frame info (read-only) */
+ UNW_X86_CFA,
+
+ UNW_X86_XMM0, /* scratch */
+ UNW_X86_XMM1, /* scratch */
+ UNW_X86_XMM2, /* scratch */
+ UNW_X86_XMM3, /* scratch */
+ UNW_X86_XMM4, /* scratch */
+ UNW_X86_XMM5, /* scratch */
+ UNW_X86_XMM6, /* scratch */
+ UNW_X86_XMM7, /* scratch */
+
+ UNW_TDEP_LAST_REG = UNW_X86_XMM7,
+
+ UNW_TDEP_IP = UNW_X86_EIP,
+ UNW_TDEP_SP = UNW_X86_ESP,
+ UNW_TDEP_EH = UNW_X86_EAX
+ }
+x86_regnum_t;
+
+#define UNW_TDEP_NUM_EH_REGS 2 /* eax and edx are exception args */
+
+typedef struct unw_tdep_save_loc
+ {
+ /* Additional target-dependent info on a save location. */
+ }
+unw_tdep_save_loc_t;
+
+/* On x86, we can directly use ucontext_t as the unwind context. */
+typedef ucontext_t unw_tdep_context_t;
+
+#include "libunwind-dynamic.h"
+
+typedef struct
+ {
+ /* no x86-specific auxiliary proc-info */
+ }
+unw_tdep_proc_info_t;
+
+#include "libunwind-common.h"
+
+#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext)
+extern int unw_tdep_getcontext (unw_tdep_context_t *);
+
+#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
+extern int unw_tdep_is_fpreg (int);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* LIBUNWIND_H */
diff --git a/src/pal/src/libunwind/include/libunwind-x86_64.h b/src/pal/src/libunwind/include/libunwind-x86_64.h
new file mode 100644
index 0000000000..78eb541afb
--- /dev/null
+++ b/src/pal/src/libunwind/include/libunwind-x86_64.h
@@ -0,0 +1,141 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef LIBUNWIND_H
+#define LIBUNWIND_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <ucontext.h>
+
+#define UNW_TARGET x86_64
+#define UNW_TARGET_X86_64 1
+
+#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
+
+/* This needs to be big enough to accommodate "struct cursor", while
+ leaving some slack for future expansion. Changing this value will
+ require recompiling all users of this library. Stack allocation is
+ relatively cheap and unwind-state copying is relatively rare, so we
+ want to err on making it rather too big than too small. */
+#define UNW_TDEP_CURSOR_LEN 127
+
+typedef uint64_t unw_word_t;
+typedef int64_t unw_sword_t;
+
+typedef long double unw_tdep_fpreg_t;
+
+typedef enum
+ {
+ UNW_X86_64_RAX,
+ UNW_X86_64_RDX,
+ UNW_X86_64_RCX,
+ UNW_X86_64_RBX,
+ UNW_X86_64_RSI,
+ UNW_X86_64_RDI,
+ UNW_X86_64_RBP,
+ UNW_X86_64_RSP,
+ UNW_X86_64_R8,
+ UNW_X86_64_R9,
+ UNW_X86_64_R10,
+ UNW_X86_64_R11,
+ UNW_X86_64_R12,
+ UNW_X86_64_R13,
+ UNW_X86_64_R14,
+ UNW_X86_64_R15,
+ UNW_X86_64_RIP,
+#ifdef CONFIG_MSABI_SUPPORT
+ UNW_X86_64_XMM0,
+ UNW_X86_64_XMM1,
+ UNW_X86_64_XMM2,
+ UNW_X86_64_XMM3,
+ UNW_X86_64_XMM4,
+ UNW_X86_64_XMM5,
+ UNW_X86_64_XMM6,
+ UNW_X86_64_XMM7,
+ UNW_X86_64_XMM8,
+ UNW_X86_64_XMM9,
+ UNW_X86_64_XMM10,
+ UNW_X86_64_XMM11,
+ UNW_X86_64_XMM12,
+ UNW_X86_64_XMM13,
+ UNW_X86_64_XMM14,
+ UNW_X86_64_XMM15,
+ UNW_TDEP_LAST_REG = UNW_X86_64_XMM15,
+#else
+ UNW_TDEP_LAST_REG = UNW_X86_64_RIP,
+#endif
+
+ /* XXX Add other regs here */
+
+ /* frame info (read-only) */
+ UNW_X86_64_CFA,
+
+ UNW_TDEP_IP = UNW_X86_64_RIP,
+ UNW_TDEP_SP = UNW_X86_64_RSP,
+ UNW_TDEP_BP = UNW_X86_64_RBP,
+ UNW_TDEP_EH = UNW_X86_64_RAX
+ }
+x86_64_regnum_t;
+
+#define UNW_TDEP_NUM_EH_REGS 2 /* XXX Not sure what this means */
+
+typedef struct unw_tdep_save_loc
+ {
+ /* Additional target-dependent info on a save location. */
+ char unused;
+ }
+unw_tdep_save_loc_t;
+
+/* On x86_64, we can directly use ucontext_t as the unwind context. */
+typedef ucontext_t unw_tdep_context_t;
+
+typedef struct
+ {
+ /* no x86-64-specific auxiliary proc-info */
+ char unused;
+ }
+unw_tdep_proc_info_t;
+
+#include "libunwind-dynamic.h"
+#include "libunwind-common.h"
+
+#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext)
+#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
+
+extern int unw_tdep_getcontext (unw_tdep_context_t *);
+extern int unw_tdep_is_fpreg (int);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* LIBUNWIND_H */
diff --git a/src/pal/src/libunwind/include/libunwind.h.in b/src/pal/src/libunwind/include/libunwind.h.in
new file mode 100644
index 0000000000..7a56168c8b
--- /dev/null
+++ b/src/pal/src/libunwind/include/libunwind.h.in
@@ -0,0 +1,36 @@
+/* Provide a real file - not a symlink - as it would cause multiarch conflicts
+ when multiple different arch releases are installed simultaneously. */
+
+#ifndef UNW_REMOTE_ONLY
+
+#if defined __aarch64__
+#include "libunwind-aarch64.h"
+#elif defined __arm__
+# include "libunwind-arm.h"
+#elif defined __hppa__
+# include "libunwind-hppa.h"
+#elif defined __ia64__
+# include "libunwind-ia64.h"
+#elif defined __mips__
+# include "libunwind-mips.h"
+#elif defined __powerpc__ && !defined __powerpc64__
+# include "libunwind-ppc32.h"
+#elif defined __powerpc64__
+# include "libunwind-ppc64.h"
+#elif defined __sh__
+# include "libunwind-sh.h"
+#elif defined __i386__
+# include "libunwind-x86.h"
+#elif defined __x86_64__
+# include "libunwind-x86_64.h"
+#elif defined __tilegx__
+# include "libunwind-tilegx.h"
+#else
+# error "Unsupported arch"
+#endif
+
+#else /* UNW_REMOTE_ONLY */
+
+# include "libunwind-@arch@.h"
+
+#endif /* UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/include/libunwind_i.h b/src/pal/src/libunwind/include/libunwind_i.h
new file mode 100644
index 0000000000..0fcf32695e
--- /dev/null
+++ b/src/pal/src/libunwind/include/libunwind_i.h
@@ -0,0 +1,366 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2005 Hewlett-Packard Co
+ Copyright (C) 2007 David Mosberger-Tang
+ Contributed by David Mosberger-Tang <dmosberger@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* This files contains libunwind-internal definitions which are
+ subject to frequent change and are not to be exposed to
+ libunwind-users. */
+
+#ifndef libunwind_i_h
+#define libunwind_i_h
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "compiler.h"
+
+#if defined(HAVE___THREAD) && HAVE___THREAD
+#define UNWI_DEFAULT_CACHING_POLICY UNW_CACHE_PER_THREAD
+#else
+#define UNWI_DEFAULT_CACHING_POLICY UNW_CACHE_GLOBAL
+#endif
+
+/* Platform-independent libunwind-internal declarations. */
+
+#include <sys/types.h> /* HP-UX needs this before include of pthread.h */
+
+#include <assert.h>
+#include <libunwind.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+#if defined(HAVE_ELF_H)
+# include <elf.h>
+#elif defined(HAVE_SYS_ELF_H)
+# include <sys/elf.h>
+#else
+# error Could not locate <elf.h>
+#endif
+
+#if defined(HAVE_ENDIAN_H)
+# include <endian.h>
+#elif defined(HAVE_SYS_ENDIAN_H)
+# include <sys/endian.h>
+# if defined(_LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN)
+# define __LITTLE_ENDIAN _LITTLE_ENDIAN
+# endif
+# if defined(_BIG_ENDIAN) && !defined(__BIG_ENDIAN)
+# define __BIG_ENDIAN _BIG_ENDIAN
+# endif
+# if defined(_BYTE_ORDER) && !defined(__BYTE_ORDER)
+# define __BYTE_ORDER _BYTE_ORDER
+# endif
+#else
+# define __LITTLE_ENDIAN 1234
+# define __BIG_ENDIAN 4321
+# if defined(__hpux)
+# define __BYTE_ORDER __BIG_ENDIAN
+# elif defined(__QNX__)
+# if defined(__BIGENDIAN__)
+# define __BYTE_ORDER __BIG_ENDIAN
+# elif defined(__LITTLEENDIAN__)
+# define __BYTE_ORDER __LITTLE_ENDIAN
+# else
+# error Host has unknown byte-order.
+# endif
+# else
+# error Host has unknown byte-order.
+# endif
+#endif
+
+#if defined(HAVE__BUILTIN_UNREACHABLE)
+# define unreachable() __builtin_unreachable()
+#else
+# define unreachable() do { } while (1)
+#endif
+
+#ifdef DEBUG
+# define UNW_DEBUG 1
+#else
+# define UNW_DEBUG 0
+#endif
+
+/* Make it easy to write thread-safe code which may or may not be
+ linked against libpthread. The macros below can be used
+ unconditionally and if -lpthread is around, they'll call the
+ corresponding routines otherwise, they do nothing. */
+
+#pragma weak pthread_mutex_init
+#pragma weak pthread_mutex_lock
+#pragma weak pthread_mutex_unlock
+
+#define mutex_init(l) \
+ (pthread_mutex_init != NULL ? pthread_mutex_init ((l), NULL) : 0)
+#define mutex_lock(l) \
+ (pthread_mutex_lock != NULL ? pthread_mutex_lock (l) : 0)
+#define mutex_unlock(l) \
+ (pthread_mutex_unlock != NULL ? pthread_mutex_unlock (l) : 0)
+
+#ifdef HAVE_ATOMIC_OPS_H
+# include <atomic_ops.h>
+static inline int
+cmpxchg_ptr (void *addr, void *old, void *new)
+{
+ union
+ {
+ void *vp;
+ AO_t *aop;
+ }
+ u;
+
+ u.vp = addr;
+ return AO_compare_and_swap(u.aop, (AO_t) old, (AO_t) new);
+}
+# define fetch_and_add1(_ptr) AO_fetch_and_add1(_ptr)
+# define fetch_and_add(_ptr, value) AO_fetch_and_add(_ptr, value)
+ /* GCC 3.2.0 on HP-UX crashes on cmpxchg_ptr() */
+# if !(defined(__hpux) && __GNUC__ == 3 && __GNUC_MINOR__ == 2)
+# define HAVE_CMPXCHG
+# endif
+# define HAVE_FETCH_AND_ADD
+#elif defined(HAVE_SYNC_ATOMICS) || defined(HAVE_IA64INTRIN_H)
+# ifdef HAVE_IA64INTRIN_H
+# include <ia64intrin.h>
+# endif
+static inline int
+cmpxchg_ptr (void *addr, void *old, void *new)
+{
+ union
+ {
+ void *vp;
+ long *vlp;
+ }
+ u;
+
+ u.vp = addr;
+ return __sync_bool_compare_and_swap(u.vlp, (long) old, (long) new);
+}
+# define fetch_and_add1(_ptr) __sync_fetch_and_add(_ptr, 1)
+# define fetch_and_add(_ptr, value) __sync_fetch_and_add(_ptr, value)
+# define HAVE_CMPXCHG
+# define HAVE_FETCH_AND_ADD
+#endif
+#define atomic_read(ptr) (*(ptr))
+
+#define UNWI_OBJ(fn) UNW_PASTE(UNW_PREFIX,UNW_PASTE(I,fn))
+#define UNWI_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_UI,UNW_TARGET),_), fn)
+
+#define unwi_full_mask UNWI_ARCH_OBJ(full_mask)
+
+/* Type of a mask that can be used to inhibit preemption. At the
+ userlevel, preemption is caused by signals and hence sigset_t is
+ appropriate. In constrast, the Linux kernel uses "unsigned long"
+ to hold the processor "flags" instead. */
+typedef sigset_t intrmask_t;
+
+extern intrmask_t unwi_full_mask;
+
+/* Silence compiler warnings about variables which are used only if libunwind
+ is configured in a certain way */
+static inline void mark_as_used(void *v UNUSED) {
+}
+
+#if defined(CONFIG_BLOCK_SIGNALS)
+# define SIGPROCMASK(how, new_mask, old_mask) \
+ sigprocmask((how), (new_mask), (old_mask))
+#else
+# define SIGPROCMASK(how, new_mask, old_mask) mark_as_used(old_mask)
+#endif
+
+/* Prefer adaptive mutexes if available */
+#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
+#define UNW_PTHREAD_MUTEX_INITIALIZER PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
+#else
+#define UNW_PTHREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+#endif
+
+#define define_lock(name) \
+ pthread_mutex_t name = UNW_PTHREAD_MUTEX_INITIALIZER
+#define lock_init(l) mutex_init (l)
+#define lock_acquire(l,m) \
+do { \
+ SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &(m)); \
+ mutex_lock (l); \
+} while (0)
+#define lock_release(l,m) \
+do { \
+ mutex_unlock (l); \
+ SIGPROCMASK (SIG_SETMASK, &(m), NULL); \
+} while (0)
+
+#define SOS_MEMORY_SIZE 16384 /* see src/mi/mempool.c */
+
+#ifndef MAP_ANONYMOUS
+# define MAP_ANONYMOUS MAP_ANON
+#endif
+#define GET_MEMORY(mem, size) \
+do { \
+ /* Hopefully, mmap() goes straight through to a system call stub... */ \
+ mem = mmap (NULL, size, PROT_READ | PROT_WRITE, \
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \
+ if (mem == MAP_FAILED) \
+ mem = NULL; \
+} while (0)
+
+#define unwi_find_dynamic_proc_info UNWI_OBJ(find_dynamic_proc_info)
+#define unwi_extract_dynamic_proc_info UNWI_OBJ(extract_dynamic_proc_info)
+#define unwi_put_dynamic_unwind_info UNWI_OBJ(put_dynamic_unwind_info)
+#define unwi_dyn_remote_find_proc_info UNWI_OBJ(dyn_remote_find_proc_info)
+#define unwi_dyn_remote_put_unwind_info UNWI_OBJ(dyn_remote_put_unwind_info)
+#define unwi_dyn_validate_cache UNWI_OBJ(dyn_validate_cache)
+
+extern int unwi_find_dynamic_proc_info (unw_addr_space_t as,
+ unw_word_t ip,
+ unw_proc_info_t *pi,
+ int need_unwind_info, void *arg);
+extern int unwi_extract_dynamic_proc_info (unw_addr_space_t as,
+ unw_word_t ip,
+ unw_proc_info_t *pi,
+ unw_dyn_info_t *di,
+ int need_unwind_info,
+ void *arg);
+extern void unwi_put_dynamic_unwind_info (unw_addr_space_t as,
+ unw_proc_info_t *pi, void *arg);
+
+/* These handle the remote (cross-address-space) case of accessing
+ dynamic unwind info. */
+
+extern int unwi_dyn_remote_find_proc_info (unw_addr_space_t as,
+ unw_word_t ip,
+ unw_proc_info_t *pi,
+ int need_unwind_info,
+ void *arg);
+extern void unwi_dyn_remote_put_unwind_info (unw_addr_space_t as,
+ unw_proc_info_t *pi,
+ void *arg);
+extern int unwi_dyn_validate_cache (unw_addr_space_t as, void *arg);
+
+extern unw_dyn_info_list_t _U_dyn_info_list;
+extern pthread_mutex_t _U_dyn_info_list_lock;
+
+#if UNW_DEBUG
+#define unwi_debug_level UNWI_ARCH_OBJ(debug_level)
+extern long unwi_debug_level;
+
+# include <stdio.h>
+# define Debug(level,format...) \
+do { \
+ if (unwi_debug_level >= level) \
+ { \
+ int _n = level; \
+ if (_n > 16) \
+ _n = 16; \
+ fprintf (stderr, "%*c>%s: ", _n, ' ', __FUNCTION__); \
+ fprintf (stderr, format); \
+ } \
+} while (0)
+# define Dprintf(format...) fprintf (stderr, format)
+#else
+# define Debug(level,format...)
+# define Dprintf(format...)
+#endif
+
+static ALWAYS_INLINE int
+print_error (const char *string)
+{
+ return write (2, string, strlen (string));
+}
+
+#define mi_init UNWI_ARCH_OBJ(mi_init)
+
+extern void mi_init (void); /* machine-independent initializations */
+extern unw_word_t _U_dyn_info_list_addr (void);
+
+/* This is needed/used by ELF targets only. */
+
+struct elf_image
+ {
+ void *image; /* pointer to mmap'd image */
+ size_t size; /* (file-) size of the image */
+ };
+
+struct elf_dyn_info
+ {
+ struct elf_image ei;
+ unw_dyn_info_t di_cache;
+ unw_dyn_info_t di_debug; /* additional table info for .debug_frame */
+#if UNW_TARGET_IA64
+ unw_dyn_info_t ktab;
+#endif
+#if UNW_TARGET_ARM
+ unw_dyn_info_t di_arm; /* additional table info for .ARM.exidx */
+#endif
+ };
+
+static inline void invalidate_edi (struct elf_dyn_info *edi)
+{
+ if (edi->ei.image)
+ munmap (edi->ei.image, edi->ei.size);
+ memset (edi, 0, sizeof (*edi));
+ edi->di_cache.format = -1;
+ edi->di_debug.format = -1;
+#if UNW_TARGET_ARM
+ edi->di_arm.format = -1;
+#endif
+}
+
+
+/* Provide a place holder for architecture to override for fast access
+ to memory when known not to need to validate and know the access
+ will be local to the process. A suitable override will improve
+ unw_tdep_trace() performance in particular. */
+#define ACCESS_MEM_FAST(ret,validate,cur,addr,to) \
+ do { (ret) = dwarf_get ((cur), DWARF_MEM_LOC ((cur), (addr)), &(to)); } \
+ while (0)
+
+/* Define GNU and processor specific values for the Phdr p_type field in case
+ they aren't defined by <elf.h>. */
+#ifndef PT_GNU_EH_FRAME
+# define PT_GNU_EH_FRAME 0x6474e550
+#endif /* !PT_GNU_EH_FRAME */
+#ifndef PT_ARM_EXIDX
+# define PT_ARM_EXIDX 0x70000001 /* ARM unwind segment */
+#endif /* !PT_ARM_EXIDX */
+
+#include "tdep/libunwind_i.h"
+
+#ifndef tdep_get_func_addr
+# define tdep_get_func_addr(as,addr,v) (*(v) = addr, 0)
+#endif
+
+#ifndef DWARF_VAL_LOC
+# define DWARF_IS_VAL_LOC(l) 0
+# define DWARF_VAL_LOC(c,v) DWARF_NULL_LOC
+#endif
+
+#define UNW_ALIGN(x,a) (((x)+(a)-1UL)&~((a)-1UL))
+
+#endif /* libunwind_i_h */
+
diff --git a/src/pal/src/libunwind/include/mempool.h b/src/pal/src/libunwind/include/mempool.h
new file mode 100644
index 0000000000..1f1c770099
--- /dev/null
+++ b/src/pal/src/libunwind/include/mempool.h
@@ -0,0 +1,89 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef mempool_h
+#define mempool_h
+
+/* Memory pools provide simple memory management of fixed-size
+ objects. Memory pools are used for two purposes:
+
+ o To ensure a stack can be unwound even when a process
+ is out of memory.
+
+ o To ensure a stack can be unwound at any time in a
+ multi-threaded process (e.g., even at a time when the normal
+ malloc-lock is taken, possibly by the very thread that is
+ being unwind).
+
+
+ To achieve the second objective, memory pools allocate memory
+ directly via mmap() system call (or an equivalent facility).
+
+ The first objective is accomplished by reserving memory ahead of
+ time. Since the memory requirements of stack unwinding generally
+ depends on the complexity of the procedures being unwind, there is
+ no absolute guarantee that unwinding will always work, but in
+ practice, this should not be a serious problem. */
+
+#include <sys/types.h>
+
+#include "libunwind_i.h"
+
+#define sos_alloc(s) UNWI_ARCH_OBJ(_sos_alloc)(s)
+#define mempool_init(p,s,r) UNWI_ARCH_OBJ(_mempool_init)(p,s,r)
+#define mempool_alloc(p) UNWI_ARCH_OBJ(_mempool_alloc)(p)
+#define mempool_free(p,o) UNWI_ARCH_OBJ(_mempool_free)(p,o)
+
+/* The mempool structure should be treated as an opaque object. It's
+ declared here only to enable static allocation of mempools. */
+struct mempool
+ {
+ pthread_mutex_t lock;
+ size_t obj_size; /* object size (rounded up for alignment) */
+ size_t chunk_size; /* allocation granularity */
+ unsigned int reserve; /* minimum (desired) size of the free-list */
+ unsigned int num_free; /* number of objects on the free-list */
+ struct object
+ {
+ struct object *next;
+ }
+ *free_list;
+ };
+
+/* Emergency allocation for one-time stuff that doesn't fit the memory
+ pool model. A limited amount of memory is available in this
+ fashion and once allocated, there is no way to free it. */
+extern void *sos_alloc (size_t size);
+
+/* Initialize POOL for an object size of OBJECT_SIZE bytes. RESERVE
+ is the number of objects that should be reserved for use under
+ tight memory situations. If it is zero, mempool attempts to pick a
+ reasonable default value. */
+extern void mempool_init (struct mempool *pool,
+ size_t obj_size, size_t reserve);
+extern void *mempool_alloc (struct mempool *pool);
+extern void mempool_free (struct mempool *pool, void *object);
+
+#endif /* mempool_h */
diff --git a/src/pal/src/libunwind/include/remote.h b/src/pal/src/libunwind/include/remote.h
new file mode 100644
index 0000000000..064d6309ad
--- /dev/null
+++ b/src/pal/src/libunwind/include/remote.h
@@ -0,0 +1,129 @@
+#ifndef REMOTE_H
+#define REMOTE_H
+
+/* Helper functions for accessing (remote) memory. These functions
+ assume that all addresses are naturally aligned (e.g., 32-bit
+ quantity is stored at a 32-bit-aligned address. */
+
+#ifdef UNW_LOCAL_ONLY
+
+static inline int
+fetch8 (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t *addr, int8_t *valp, void *arg)
+{
+ *valp = *(int8_t *) (uintptr_t) *addr;
+ *addr += 1;
+ return 0;
+}
+
+static inline int
+fetch16 (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t *addr, int16_t *valp, void *arg)
+{
+ *valp = *(int16_t *) (uintptr_t) *addr;
+ *addr += 2;
+ return 0;
+}
+
+static inline int
+fetch32 (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t *addr, int32_t *valp, void *arg)
+{
+ *valp = *(int32_t *) (uintptr_t) *addr;
+ *addr += 4;
+ return 0;
+}
+
+static inline int
+fetchw (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t *addr, unw_word_t *valp, void *arg)
+{
+ *valp = *(unw_word_t *) (uintptr_t) *addr;
+ *addr += sizeof (unw_word_t);
+ return 0;
+}
+
+#else /* !UNW_LOCAL_ONLY */
+
+#define WSIZE (sizeof (unw_word_t))
+
+static inline int
+fetch8 (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t *addr, int8_t *valp, void *arg)
+{
+ unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr;
+ int ret;
+
+ *addr += 1;
+
+ ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg);
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ val >>= 8*off;
+#else
+ val >>= 8*(WSIZE - 1 - off);
+#endif
+ *valp = val & 0xff;
+ return ret;
+}
+
+static inline int
+fetch16 (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t *addr, int16_t *valp, void *arg)
+{
+ unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr;
+ int ret;
+
+ if ((off & 0x1) != 0)
+ return -UNW_EINVAL;
+
+ *addr += 2;
+
+ ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg);
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ val >>= 8*off;
+#else
+ val >>= 8*(WSIZE - 2 - off);
+#endif
+ *valp = val & 0xffff;
+ return ret;
+}
+
+static inline int
+fetch32 (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t *addr, int32_t *valp, void *arg)
+{
+ unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr;
+ int ret;
+
+ if ((off & 0x3) != 0)
+ return -UNW_EINVAL;
+
+ *addr += 4;
+
+ ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg);
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ val >>= 8*off;
+#else
+ val >>= 8*(WSIZE - 4 - off);
+#endif
+ *valp = val & 0xffffffff;
+ return ret;
+}
+
+static inline int
+fetchw (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t *addr, unw_word_t *valp, void *arg)
+{
+ int ret;
+
+ ret = (*a->access_mem) (as, *addr, valp, 0, arg);
+ *addr += WSIZE;
+ return ret;
+}
+
+#endif /* !UNW_LOCAL_ONLY */
+
+#endif /* REMOTE_H */
diff --git a/src/pal/src/libunwind/include/tdep-aarch64/dwarf-config.h b/src/pal/src/libunwind/include/tdep-aarch64/dwarf-config.h
new file mode 100644
index 0000000000..f65db17ee6
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-aarch64/dwarf-config.h
@@ -0,0 +1,52 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+ Copyright (C) 2013 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef dwarf_config_h
+#define dwarf_config_h
+
+/* This matches the value udes by GCC (see
+ gcc/config/aarch64/aarch64.h:DWARF_FRAME_REGISTERS. */
+#define DWARF_NUM_PRESERVED_REGS 97
+
+/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
+#define dwarf_is_big_endian(addr_space) 0
+
+#define dwarf_to_unw_regnum(reg) (((reg) <= UNW_AARCH64_V31) ? (reg) : 0)
+
+/* Convert a pointer to a dwarf_cursor structure to a pointer to
+ unw_cursor_t. */
+#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
+
+typedef struct dwarf_loc
+ {
+ unw_word_t val;
+#ifndef UNW_LOCAL_ONLY
+ unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */
+#endif
+ }
+dwarf_loc_t;
+
+#endif /* dwarf_config_h */
diff --git a/src/pal/src/libunwind/include/tdep-aarch64/jmpbuf.h b/src/pal/src/libunwind/include/tdep-aarch64/jmpbuf.h
new file mode 100644
index 0000000000..3f01a442ba
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-aarch64/jmpbuf.h
@@ -0,0 +1,33 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2013 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
+
+/* FIXME for AArch64 */
+
+#define JB_SP 13
+#define JB_RP 14
+#define JB_MASK_SAVED 15
+#define JB_MASK 16
diff --git a/src/pal/src/libunwind/include/tdep-aarch64/libunwind_i.h b/src/pal/src/libunwind/include/tdep-aarch64/libunwind_i.h
new file mode 100644
index 0000000000..b91273fa1c
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-aarch64/libunwind_i.h
@@ -0,0 +1,320 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+ Copyright (C) 2013 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef AARCH64_LIBUNWIND_I_H
+#define AARCH64_LIBUNWIND_I_H
+
+/* Target-dependent definitions that are internal to libunwind but need
+ to be shared with target-independent code. */
+
+#include <stdlib.h>
+#include <libunwind.h>
+
+#include "elf64.h"
+#include "mempool.h"
+#include "dwarf.h"
+
+typedef enum
+ {
+ UNW_AARCH64_FRAME_STANDARD = -2, /* regular fp, sp +/- offset */
+ UNW_AARCH64_FRAME_SIGRETURN = -1, /* special sigreturn frame */
+ UNW_AARCH64_FRAME_OTHER = 0, /* not cacheable (special or unrecognised) */
+ UNW_AARCH64_FRAME_GUESSED = 1 /* guessed it was regular, but not known */
+ }
+unw_tdep_frame_type_t;
+
+typedef struct
+ {
+ uint64_t virtual_address;
+ int64_t frame_type : 2; /* unw_tdep_frame_type_t classification */
+ int64_t last_frame : 1; /* non-zero if last frame in chain */
+ int64_t cfa_reg_sp : 1; /* cfa dwarf base register is sp vs. fp */
+ int64_t cfa_reg_offset : 30; /* cfa is at this offset from base register value */
+ int64_t fp_cfa_offset : 30; /* fp saved at this offset from cfa (-1 = not saved) */
+ int64_t lr_cfa_offset : 30; /* lr saved at this offset from cfa (-1 = not saved) */
+ int64_t sp_cfa_offset : 30; /* sp saved at this offset from cfa (-1 = not saved) */
+ }
+unw_tdep_frame_t;
+
+#ifdef UNW_LOCAL_ONLY
+
+typedef unw_word_t aarch64_loc_t;
+
+#else /* !UNW_LOCAL_ONLY */
+
+typedef struct aarch64_loc
+ {
+ unw_word_t w0, w1;
+ }
+aarch64_loc_t;
+
+#endif /* !UNW_LOCAL_ONLY */
+
+struct unw_addr_space
+ {
+ struct unw_accessors acc;
+ int big_endian;
+ unw_caching_policy_t caching_policy;
+#ifdef HAVE_ATOMIC_OPS_H
+ AO_t cache_generation;
+#else
+ uint32_t cache_generation;
+#endif
+ unw_word_t dyn_generation; /* see dyn-common.h */
+ unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
+ struct dwarf_rs_cache global_cache;
+ struct unw_debug_frame_list *debug_frames;
+ };
+
+struct cursor
+ {
+ struct dwarf_cursor dwarf; /* must be first */
+
+ unw_tdep_frame_t frame_info; /* quick tracing assist info */
+
+ enum
+ {
+ AARCH64_SCF_NONE,
+ AARCH64_SCF_LINUX_RT_SIGFRAME,
+ }
+ sigcontext_format;
+ unw_word_t sigcontext_addr;
+ unw_word_t sigcontext_sp;
+ unw_word_t sigcontext_pc;
+ int validate;
+ };
+
+#define DWARF_GET_LOC(l) ((l).val)
+
+#ifdef UNW_LOCAL_ONLY
+# define DWARF_NULL_LOC DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
+# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
+# define DWARF_IS_REG_LOC(l) 0
+# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
+ tdep_uc_addr((c)->as_arg, (r)), 0))
+# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
+# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
+ tdep_uc_addr((c)->as_arg, (r)), 0))
+
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
+ return 0;
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *(unw_fpreg_t *) DWARF_GET_LOC (loc) = val;
+ return 0;
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *val = *(unw_word_t *) DWARF_GET_LOC (loc);
+ return 0;
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *(unw_word_t *) DWARF_GET_LOC (loc) = val;
+ return 0;
+}
+
+#else /* !UNW_LOCAL_ONLY */
+# define DWARF_LOC_TYPE_FP (1 << 0)
+# define DWARF_LOC_TYPE_REG (1 << 1)
+# define DWARF_NULL_LOC DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l) \
+ ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
+# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
+# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
+# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
+# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
+# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
+# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
+ | DWARF_LOC_TYPE_FP))
+
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+ char *valp = (char *) &val;
+ unw_word_t addr;
+ int ret;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ val, 0, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+ if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
+ 0, c->as_arg)) < 0)
+ return ret;
+
+ return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
+ c->as_arg);
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ char *valp = (char *) &val;
+ unw_word_t addr;
+ int ret;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ &val, 1, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+ if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
+ 1, c->as_arg)) < 0)
+ return ret;
+
+ return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
+ 1, c->as_arg);
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ /* If a code-generator were to save a value of type unw_word_t in a
+ floating-point register, we would have to support this case. I
+ suppose it could happen with MMX registers, but does it really
+ happen? */
+ assert (!DWARF_IS_FP_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ /* If a code-generator were to save a value of type unw_word_t in a
+ floating-point register, we would have to support this case. I
+ suppose it could happen with MMX registers, but does it really
+ happen? */
+ assert (!DWARF_IS_FP_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+}
+
+#endif /* !UNW_LOCAL_ONLY */
+
+
+
+#define tdep_getcontext_trace UNW_ARCH_OBJ(getcontext_trace)
+#define tdep_init_done UNW_OBJ(init_done)
+#define tdep_init UNW_OBJ(init)
+/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
+ tdep_search_unwind_table. */
+#define tdep_search_unwind_table dwarf_search_unwind_table
+#define tdep_find_unwind_table dwarf_find_unwind_table
+#define tdep_uc_addr UNW_OBJ(uc_addr)
+#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
+#define tdep_access_reg UNW_OBJ(access_reg)
+#define tdep_access_fpreg UNW_OBJ(access_fpreg)
+#define tdep_fetch_frame(c,ip,n) do {} while(0)
+#define tdep_cache_frame(c) 0
+#define tdep_reuse_frame(c,frame) do {} while(0)
+#define tdep_stash_frame UNW_OBJ(tdep_stash_frame)
+#define tdep_trace UNW_OBJ(tdep_trace)
+
+#ifdef UNW_LOCAL_ONLY
+# define tdep_find_proc_info(c,ip,n) \
+ dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define tdep_put_unwind_info(as,pi,arg) \
+ dwarf_put_unwind_info((as), (pi), (arg))
+#else
+# define tdep_find_proc_info(c,ip,n) \
+ (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define tdep_put_unwind_info(as,pi,arg) \
+ (*(as)->acc.put_unwind_info)((as), (pi), (arg))
+#endif
+
+#define tdep_get_as(c) ((c)->dwarf.as)
+#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
+#define tdep_get_ip(c) ((c)->dwarf.ip)
+#define tdep_big_endian(as) ((as)->big_endian)
+
+extern int tdep_init_done;
+
+extern void tdep_init (void);
+extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
+ unw_dyn_info_t *di, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg);
+extern void *tdep_uc_addr (unw_tdep_context_t *uc, int reg);
+extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
+ unsigned long *segbase, unsigned long *mapoff,
+ char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
+extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
+ unw_word_t *valp, int write);
+extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
+ unw_fpreg_t *valp, int write);
+extern int tdep_trace (unw_cursor_t *cursor, void **addresses, int *n);
+extern void tdep_stash_frame (struct dwarf_cursor *c,
+ struct dwarf_reg_state *rs);
+extern int tdep_getcontext_trace (unw_tdep_context_t *);
+
+#endif /* AARCH64_LIBUNWIND_I_H */
diff --git a/src/pal/src/libunwind/include/tdep-arm/dwarf-config.h b/src/pal/src/libunwind/include/tdep-arm/dwarf-config.h
new file mode 100644
index 0000000000..f50228975e
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-arm/dwarf-config.h
@@ -0,0 +1,51 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef dwarf_config_h
+#define dwarf_config_h
+
+/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not
+ explicitly defined. */
+#define DWARF_NUM_PRESERVED_REGS 128
+
+#define dwarf_to_unw_regnum(reg) (((reg) < 16) ? (reg) : 0)
+
+/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
+#define dwarf_is_big_endian(addr_space) 0
+
+/* Convert a pointer to a dwarf_cursor structure to a pointer to
+ unw_cursor_t. */
+#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
+
+typedef struct dwarf_loc
+ {
+ unw_word_t val;
+#ifndef UNW_LOCAL_ONLY
+ unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */
+#endif
+ }
+dwarf_loc_t;
+
+#endif /* dwarf_config_h */
diff --git a/src/pal/src/libunwind/include/tdep-arm/ex_tables.h b/src/pal/src/libunwind/include/tdep-arm/ex_tables.h
new file mode 100644
index 0000000000..9df5e0a9fa
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-arm/ex_tables.h
@@ -0,0 +1,55 @@
+/* libunwind - a platform-independent unwind library
+ Copyright 2011 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef ARM_EX_TABLES_H
+#define ARM_EX_TABLES_H
+
+typedef enum arm_exbuf_cmd {
+ ARM_EXIDX_CMD_FINISH,
+ ARM_EXIDX_CMD_DATA_PUSH,
+ ARM_EXIDX_CMD_DATA_POP,
+ ARM_EXIDX_CMD_REG_POP,
+ ARM_EXIDX_CMD_REG_TO_SP,
+ ARM_EXIDX_CMD_VFP_POP,
+ ARM_EXIDX_CMD_WREG_POP,
+ ARM_EXIDX_CMD_WCGR_POP,
+ ARM_EXIDX_CMD_RESERVED,
+ ARM_EXIDX_CMD_REFUSED,
+} arm_exbuf_cmd_t;
+
+struct arm_exbuf_data
+{
+ arm_exbuf_cmd_t cmd;
+ uint32_t data;
+};
+
+#define arm_exidx_extract UNW_OBJ(arm_exidx_extract)
+#define arm_exidx_decode UNW_OBJ(arm_exidx_decode)
+#define arm_exidx_apply_cmd UNW_OBJ(arm_exidx_apply_cmd)
+
+int arm_exidx_extract (struct dwarf_cursor *c, uint8_t *buf);
+int arm_exidx_decode (const uint8_t *buf, uint8_t len, struct dwarf_cursor *c);
+int arm_exidx_apply_cmd (struct arm_exbuf_data *edata, struct dwarf_cursor *c);
+
+#endif // ARM_EX_TABLES_H
diff --git a/src/pal/src/libunwind/include/tdep-arm/jmpbuf.h b/src/pal/src/libunwind/include/tdep-arm/jmpbuf.h
new file mode 100644
index 0000000000..008e77f796
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-arm/jmpbuf.h
@@ -0,0 +1,32 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
+
+/* FIXME for ARM! */
+
+#define JB_SP 4
+#define JB_RP 5
+#define JB_MASK_SAVED 6
+#define JB_MASK 7
diff --git a/src/pal/src/libunwind/include/tdep-arm/libunwind_i.h b/src/pal/src/libunwind/include/tdep-arm/libunwind_i.h
new file mode 100644
index 0000000000..2602f41c4f
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-arm/libunwind_i.h
@@ -0,0 +1,326 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef ARM_LIBUNWIND_I_H
+#define ARM_LIBUNWIND_I_H
+
+/* Target-dependent definitions that are internal to libunwind but need
+ to be shared with target-independent code. */
+
+#include <stdlib.h>
+#include <libunwind.h>
+
+#include "elf32.h"
+#include "mempool.h"
+#include "dwarf.h"
+#include "ex_tables.h"
+
+typedef enum
+ {
+ UNW_ARM_FRAME_SYSCALL = -3, /* r7 saved in r12, sp offset zero */
+ UNW_ARM_FRAME_STANDARD = -2, /* regular r7, sp +/- offset */
+ UNW_ARM_FRAME_SIGRETURN = -1, /* special sigreturn frame */
+ UNW_ARM_FRAME_OTHER = 0, /* not cacheable (special or unrecognised) */
+ UNW_ARM_FRAME_GUESSED = 1 /* guessed it was regular, but not known */
+ }
+unw_tdep_frame_type_t;
+
+typedef struct
+ {
+ uint32_t virtual_address;
+ int32_t frame_type : 3; /* unw_tdep_frame_type_t classification */
+ int32_t last_frame : 1; /* non-zero if last frame in chain */
+ int32_t cfa_reg_sp : 1; /* cfa dwarf base register is sp vs. r7 */
+ int32_t cfa_reg_offset : 30; /* cfa is at this offset from base register value */
+ int32_t r7_cfa_offset : 30; /* r7 saved at this offset from cfa (-1 = not saved) */
+ int32_t lr_cfa_offset : 30; /* lr saved at this offset from cfa (-1 = not saved) */
+ int32_t sp_cfa_offset : 30; /* sp saved at this offset from cfa (-1 = not saved) */
+ }
+unw_tdep_frame_t;
+
+struct unw_addr_space
+ {
+ struct unw_accessors acc;
+ int big_endian;
+ unw_caching_policy_t caching_policy;
+#ifdef HAVE_ATOMIC_OPS_H
+ AO_t cache_generation;
+#else
+ uint32_t cache_generation;
+#endif
+ unw_word_t dyn_generation; /* see dyn-common.h */
+ unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
+ struct dwarf_rs_cache global_cache;
+ struct unw_debug_frame_list *debug_frames;
+ };
+
+struct cursor
+ {
+ struct dwarf_cursor dwarf; /* must be first */
+
+ unw_tdep_frame_t frame_info; /* quick tracing assist info */
+
+ enum
+ {
+ ARM_SCF_NONE, /* no signal frame */
+ ARM_SCF_LINUX_SIGFRAME, /* non-RT signal frame, kernel >=2.6.18 */
+ ARM_SCF_LINUX_RT_SIGFRAME, /* RT signal frame, kernel >=2.6.18 */
+ ARM_SCF_LINUX_OLD_SIGFRAME, /* non-RT signal frame, kernel < 2.6.18 */
+ ARM_SCF_LINUX_OLD_RT_SIGFRAME, /* RT signal frame, kernel < 2.6.18 */
+ ARM_SCF_FREEBSD_SIGFRAME, /* FreeBSD sigframe */
+ ARM_SCF_FREEBSD_SYSCALL, /* FreeBSD syscall stub */
+ }
+ sigcontext_format;
+ unw_word_t sigcontext_addr;
+ unw_word_t sigcontext_sp;
+ unw_word_t sigcontext_pc;
+ int validate;
+ };
+
+#define DWARF_GET_LOC(l) ((l).val)
+
+#ifdef UNW_LOCAL_ONLY
+# define DWARF_NULL_LOC DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
+# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
+# define DWARF_IS_REG_LOC(l) 0
+# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
+ tdep_uc_addr((c)->as_arg, (r)), 0))
+# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
+# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
+ tdep_uc_addr((c)->as_arg, (r)), 0))
+
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
+ return 0;
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *(unw_fpreg_t *) DWARF_GET_LOC (loc) = val;
+ return 0;
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *val = *(unw_word_t *) DWARF_GET_LOC (loc);
+ return 0;
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *(unw_word_t *) DWARF_GET_LOC (loc) = val;
+ return 0;
+}
+
+#else /* !UNW_LOCAL_ONLY */
+# define DWARF_LOC_TYPE_FP (1 << 0)
+# define DWARF_LOC_TYPE_REG (1 << 1)
+# define DWARF_NULL_LOC DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l) \
+ ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
+# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
+# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
+# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
+# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
+# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
+# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
+ | DWARF_LOC_TYPE_FP))
+
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+ char *valp = (char *) &val;
+ unw_word_t addr;
+ int ret;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ val, 0, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+ if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
+ 0, c->as_arg)) < 0)
+ return ret;
+
+ return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
+ c->as_arg);
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ char *valp = (char *) &val;
+ unw_word_t addr;
+ int ret;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ &val, 1, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+ if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
+ 1, c->as_arg)) < 0)
+ return ret;
+
+ return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
+ 1, c->as_arg);
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ /* If a code-generator were to save a value of type unw_word_t in a
+ floating-point register, we would have to support this case. I
+ suppose it could happen with MMX registers, but does it really
+ happen? */
+ assert (!DWARF_IS_FP_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ /* If a code-generator were to save a value of type unw_word_t in a
+ floating-point register, we would have to support this case. I
+ suppose it could happen with MMX registers, but does it really
+ happen? */
+ assert (!DWARF_IS_FP_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+}
+
+#endif /* !UNW_LOCAL_ONLY */
+
+#define tdep_getcontext_trace unw_getcontext
+#define tdep_init_done UNW_OBJ(init_done)
+#define tdep_init UNW_OBJ(init)
+#define arm_find_proc_info UNW_OBJ(find_proc_info)
+#define arm_put_unwind_info UNW_OBJ(put_unwind_info)
+/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
+ tdep_search_unwind_table. */
+#define tdep_search_unwind_table UNW_OBJ(search_unwind_table)
+#define tdep_find_unwind_table dwarf_find_unwind_table
+#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
+#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
+#define tdep_access_reg UNW_OBJ(access_reg)
+#define tdep_access_fpreg UNW_OBJ(access_fpreg)
+#define tdep_fetch_frame(c,ip,n) do {} while(0)
+#define tdep_cache_frame(c) 0
+#define tdep_reuse_frame(c,frame) do {} while(0)
+#define tdep_stash_frame UNW_OBJ(tdep_stash_frame)
+#define tdep_trace UNW_OBJ(tdep_trace)
+
+#ifdef UNW_LOCAL_ONLY
+# define tdep_find_proc_info(c,ip,n) \
+ arm_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define tdep_put_unwind_info(as,pi,arg) \
+ arm_put_unwind_info((as), (pi), (arg))
+#else
+# define tdep_find_proc_info(c,ip,n) \
+ (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define tdep_put_unwind_info(as,pi,arg) \
+ (*(as)->acc.put_unwind_info)((as), (pi), (arg))
+#endif
+
+#define tdep_get_as(c) ((c)->dwarf.as)
+#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
+#define tdep_get_ip(c) ((c)->dwarf.ip)
+#define tdep_big_endian(as) ((as)->big_endian)
+
+extern int tdep_init_done;
+
+extern void tdep_init (void);
+extern int arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
+ unw_proc_info_t *pi, int need_unwind_info,
+ void *arg);
+extern void arm_put_unwind_info (unw_addr_space_t as,
+ unw_proc_info_t *pi, void *arg);
+extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
+ unw_dyn_info_t *di, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg);
+extern void *tdep_uc_addr (unw_tdep_context_t *uc, int reg);
+extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
+ unsigned long *segbase, unsigned long *mapoff,
+ char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
+extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
+ unw_word_t *valp, int write);
+extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
+ unw_fpreg_t *valp, int write);
+extern int tdep_trace (unw_cursor_t *cursor, void **addresses, int *n);
+extern void tdep_stash_frame (struct dwarf_cursor *c,
+ struct dwarf_reg_state *rs);
+
+/* unwinding method selection support */
+#define UNW_ARM_METHOD_ALL 0xFF
+#define UNW_ARM_METHOD_DWARF 0x01
+#define UNW_ARM_METHOD_FRAME 0x02
+#define UNW_ARM_METHOD_EXIDX 0x04
+
+#define unwi_unwind_method UNW_OBJ(unwind_method)
+extern int unwi_unwind_method;
+
+#define UNW_TRY_METHOD(x) (unwi_unwind_method & x)
+
+#endif /* ARM_LIBUNWIND_I_H */
diff --git a/src/pal/src/libunwind/include/tdep-hppa/dwarf-config.h b/src/pal/src/libunwind/include/tdep-hppa/dwarf-config.h
new file mode 100644
index 0000000000..fb963c7d30
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-hppa/dwarf-config.h
@@ -0,0 +1,54 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2004 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef dwarf_config_h
+#define dwarf_config_h
+
+/* See DWARF_FRAME_REGNUM() macro in gcc/config/pa/pa32-regs.h: */
+#define dwarf_to_unw_regnum(reg) \
+ (((reg) < DWARF_NUM_PRESERVED_REGS) ? (reg) : 0)
+
+/* This matches the value used by GCC (see
+ gcc/config/pa/pa32-regs.h:FIRST_PSEUDO_REGISTER), which leaves
+ plenty of room for expansion. */
+#define DWARF_NUM_PRESERVED_REGS 89
+
+/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
+#define dwarf_is_big_endian(addr_space) 1
+
+/* Convert a pointer to a dwarf_cursor structure to a pointer to
+ unw_cursor_t. */
+#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
+
+typedef struct dwarf_loc
+ {
+ unw_word_t val;
+#ifndef UNW_LOCAL_ONLY
+ unw_word_t type; /* see X86_LOC_TYPE_* macros. */
+#endif
+ }
+dwarf_loc_t;
+
+#endif /* dwarf_config_h */
diff --git a/src/pal/src/libunwind/include/tdep-hppa/jmpbuf.h b/src/pal/src/libunwind/include/tdep-hppa/jmpbuf.h
new file mode 100644
index 0000000000..91f062ff7d
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-hppa/jmpbuf.h
@@ -0,0 +1,33 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
+
+#ifndef JB_SP
+# define JB_SP 19
+#endif
+#define JB_RP 20
+#define JB_MASK_SAVED 21
+#define JB_MASK 22
diff --git a/src/pal/src/libunwind/include/tdep-hppa/libunwind_i.h b/src/pal/src/libunwind/include/tdep-hppa/libunwind_i.h
new file mode 100644
index 0000000000..72649aa3ec
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-hppa/libunwind_i.h
@@ -0,0 +1,279 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef HPPA_LIBUNWIND_I_H
+#define HPPA_LIBUNWIND_I_H
+
+/* Target-dependent definitions that are internal to libunwind but need
+ to be shared with target-independent code. */
+
+#include <stdlib.h>
+#include <libunwind.h>
+
+#include "elf32.h"
+#include "mempool.h"
+#include "dwarf.h"
+
+typedef struct
+ {
+ /* no hppa-specific fast trace */
+ }
+unw_tdep_frame_t;
+
+struct unw_addr_space
+ {
+ struct unw_accessors acc;
+ unw_caching_policy_t caching_policy;
+#ifdef HAVE_ATOMIC_OPS_H
+ AO_t cache_generation;
+#else
+ uint32_t cache_generation;
+#endif
+ unw_word_t dyn_generation; /* see dyn-common.h */
+ unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
+ struct dwarf_rs_cache global_cache;
+ struct unw_debug_frame_list *debug_frames;
+ };
+
+struct cursor
+ {
+ struct dwarf_cursor dwarf; /* must be first */
+
+ /* Format of sigcontext structure and address at which it is
+ stored: */
+ enum
+ {
+ HPPA_SCF_NONE, /* no signal frame encountered */
+ HPPA_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */
+ }
+ sigcontext_format;
+ unw_word_t sigcontext_addr;
+ };
+
+#define DWARF_GET_LOC(l) ((l).val)
+
+#ifdef UNW_LOCAL_ONLY
+# define DWARF_NULL_LOC DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
+# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
+# define DWARF_IS_REG_LOC(l) 0
+# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
+ tdep_uc_addr((c)->as_arg, (r)), 0))
+# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
+# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
+ tdep_uc_addr((c)->as_arg, (r)), 0))
+
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
+ return 0;
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *(unw_fpreg_t *) DWARF_GET_LOC (loc) = val;
+ return 0;
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *val = *(unw_word_t *) DWARF_GET_LOC (loc);
+ return 0;
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *(unw_word_t *) DWARF_GET_LOC (loc) = val;
+ return 0;
+}
+
+#else /* !UNW_LOCAL_ONLY */
+# define DWARF_LOC_TYPE_FP (1 << 0)
+# define DWARF_LOC_TYPE_REG (1 << 1)
+# define DWARF_NULL_LOC DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l) \
+ ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
+# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
+# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
+# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
+# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
+# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
+# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
+ | DWARF_LOC_TYPE_FP))
+
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+ char *valp = (char *) &val;
+ unw_word_t addr;
+ int ret;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ val, 0, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+ if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
+ 0, c->as_arg)) < 0)
+ return ret;
+
+ return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
+ c->as_arg);
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ char *valp = (char *) &val;
+ unw_word_t addr;
+ int ret;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ &val, 1, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+ if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
+ 1, c->as_arg)) < 0)
+ return ret;
+
+ return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
+ 1, c->as_arg);
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ /* If a code-generator were to save a value of type unw_word_t in a
+ floating-point register, we would have to support this case. I
+ suppose it could happen with MMX registers, but does it really
+ happen? */
+ assert (!DWARF_IS_FP_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ /* If a code-generator were to save a value of type unw_word_t in a
+ floating-point register, we would have to support this case. I
+ suppose it could happen with MMX registers, but does it really
+ happen? */
+ assert (!DWARF_IS_FP_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+}
+
+#endif /* !UNW_LOCAL_ONLY */
+
+#define tdep_getcontext_trace unw_getcontext
+#define tdep_init_done UNW_OBJ(init_done)
+#define tdep_init UNW_OBJ(init)
+/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
+ tdep_search_unwind_table. */
+#define tdep_search_unwind_table dwarf_search_unwind_table
+#define tdep_find_unwind_table dwarf_find_unwind_table
+#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
+#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
+#define tdep_access_reg UNW_OBJ(access_reg)
+#define tdep_access_fpreg UNW_OBJ(access_fpreg)
+#define tdep_fetch_frame(c,ip,n) do {} while(0)
+#define tdep_cache_frame(c) 0
+#define tdep_reuse_frame(c,frame) do {} while(0)
+#define tdep_stash_frame(c,rs) do {} while(0)
+#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
+
+#ifdef UNW_LOCAL_ONLY
+# define tdep_find_proc_info(c,ip,n) \
+ dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define tdep_put_unwind_info(as,pi,arg) \
+ dwarf_put_unwind_info((as), (pi), (arg))
+#else
+# define tdep_find_proc_info(c,ip,n) \
+ (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define tdep_put_unwind_info(as,pi,arg) \
+ (*(as)->acc.put_unwind_info)((as), (pi), (arg))
+#endif
+
+#define tdep_get_as(c) ((c)->dwarf.as)
+#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
+#define tdep_get_ip(c) ((c)->dwarf.ip)
+#define tdep_big_endian(as) 1
+
+extern int tdep_init_done;
+
+extern void tdep_init (void);
+extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
+ unw_dyn_info_t *di, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg);
+extern void *tdep_uc_addr (ucontext_t *uc, int reg);
+extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
+ unsigned long *segbase, unsigned long *mapoff,
+ char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
+extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
+ unw_word_t *valp, int write);
+extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
+ unw_fpreg_t *valp, int write);
+
+#endif /* HPPA_LIBUNWIND_I_H */
diff --git a/src/pal/src/libunwind/include/tdep-ia64/jmpbuf.h b/src/pal/src/libunwind/include/tdep-ia64/jmpbuf.h
new file mode 100644
index 0000000000..d642af2075
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-ia64/jmpbuf.h
@@ -0,0 +1,32 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Use glibc's jump-buffer indices; NPTL peeks at SP and BSP: */
+
+#define JB_SP 0
+#define JB_RP 8
+#define JB_BSP 17
+#define JB_MASK_SAVED 70
+#define JB_MASK 71
diff --git a/src/pal/src/libunwind/include/tdep-ia64/libunwind_i.h b/src/pal/src/libunwind/include/tdep-ia64/libunwind_i.h
new file mode 100644
index 0000000000..1d9770bab8
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-ia64/libunwind_i.h
@@ -0,0 +1,281 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef IA64_LIBUNWIND_I_H
+#define IA64_LIBUNWIND_I_H
+
+/* Target-dependent definitions that are internal to libunwind but need
+ to be shared with target-independent code. */
+
+#include "elf64.h"
+#include "mempool.h"
+
+typedef struct
+ {
+ /* no ia64-specific fast trace */
+ }
+unw_tdep_frame_t;
+
+enum ia64_pregnum
+ {
+ /* primary unat: */
+ IA64_REG_PRI_UNAT_GR,
+ IA64_REG_PRI_UNAT_MEM,
+
+ /* memory stack (order matters: see build_script() */
+ IA64_REG_PSP, /* previous memory stack pointer */
+ /* register stack */
+ IA64_REG_BSP, /* register stack pointer */
+ IA64_REG_BSPSTORE,
+ IA64_REG_PFS, /* previous function state */
+ IA64_REG_RNAT,
+ /* instruction pointer: */
+ IA64_REG_IP,
+
+ /* preserved registers: */
+ IA64_REG_R4, IA64_REG_R5, IA64_REG_R6, IA64_REG_R7,
+ IA64_REG_NAT4, IA64_REG_NAT5, IA64_REG_NAT6, IA64_REG_NAT7,
+ IA64_REG_UNAT, IA64_REG_PR, IA64_REG_LC, IA64_REG_FPSR,
+ IA64_REG_B1, IA64_REG_B2, IA64_REG_B3, IA64_REG_B4, IA64_REG_B5,
+ IA64_REG_F2, IA64_REG_F3, IA64_REG_F4, IA64_REG_F5,
+ IA64_REG_F16, IA64_REG_F17, IA64_REG_F18, IA64_REG_F19,
+ IA64_REG_F20, IA64_REG_F21, IA64_REG_F22, IA64_REG_F23,
+ IA64_REG_F24, IA64_REG_F25, IA64_REG_F26, IA64_REG_F27,
+ IA64_REG_F28, IA64_REG_F29, IA64_REG_F30, IA64_REG_F31,
+ IA64_NUM_PREGS
+ };
+
+#ifdef UNW_LOCAL_ONLY
+
+typedef unw_word_t ia64_loc_t;
+
+#else /* !UNW_LOCAL_ONLY */
+
+typedef struct ia64_loc
+ {
+ unw_word_t w0, w1;
+ }
+ia64_loc_t;
+
+#endif /* !UNW_LOCAL_ONLY */
+
+#include "script.h"
+
+#define ABI_UNKNOWN 0
+#define ABI_LINUX 1
+#define ABI_HPUX 2
+#define ABI_FREEBSD 3
+#define ABI_OPENVMS 4
+#define ABI_NSK 5 /* Tandem/HP Non-Stop Kernel */
+#define ABI_WINDOWS 6
+
+struct unw_addr_space
+ {
+ struct unw_accessors acc;
+ int big_endian;
+ int abi; /* abi < 0 => unknown, 0 => SysV, 1 => HP-UX, 2 => Windows */
+ unw_caching_policy_t caching_policy;
+#ifdef HAVE_ATOMIC_OPS_H
+ AO_t cache_generation;
+#else
+ uint32_t cache_generation;
+#endif
+ unw_word_t dyn_generation;
+ unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
+#ifndef UNW_REMOTE_ONLY
+ unsigned long long shared_object_removals;
+#endif
+
+ struct ia64_script_cache global_cache;
+ };
+
+/* Note: The ABI numbers in the ABI-markers (.unwabi directive) are
+ not the same as the above ABI numbers. */
+#define ABI_MARKER_OLD_LINUX_SIGTRAMP ((0 << 8) | 's')
+#define ABI_MARKER_OLD_LINUX_INTERRUPT ((0 << 8) | 'i')
+#define ABI_MARKER_HP_UX_SIGTRAMP ((1 << 8) | 1)
+#define ABI_MARKER_LINUX_SIGTRAMP ((3 << 8) | 's')
+#define ABI_MARKER_LINUX_INTERRUPT ((3 << 8) | 'i')
+
+struct cursor
+ {
+ void *as_arg; /* argument to address-space callbacks */
+ unw_addr_space_t as; /* reference to per-address-space info */
+
+ /* IP, CFM, and predicate cache (these are always equal to the
+ values stored in ip_loc, cfm_loc, and pr_loc,
+ respectively). */
+ unw_word_t ip; /* instruction pointer value */
+ unw_word_t cfm; /* current frame mask */
+ unw_word_t pr; /* current predicate values */
+
+ /* current frame info: */
+ unw_word_t bsp; /* backing store pointer value */
+ unw_word_t sp; /* stack pointer value */
+ unw_word_t psp; /* previous sp value */
+ ia64_loc_t cfm_loc; /* cfm save location (or NULL) */
+ ia64_loc_t ec_loc; /* ar.ec save location (usually cfm_loc) */
+ ia64_loc_t loc[IA64_NUM_PREGS];
+
+ unw_word_t eh_args[4]; /* exception handler arguments */
+ unw_word_t sigcontext_addr; /* address of sigcontext or 0 */
+ unw_word_t sigcontext_off; /* sigcontext-offset relative to signal sp */
+
+ short hint;
+ short prev_script;
+
+ uint8_t nat_bitnr[4]; /* NaT bit numbers for r4-r7 */
+ uint16_t abi_marker; /* abi_marker for current frame (if any) */
+ uint16_t last_abi_marker; /* last abi_marker encountered so far */
+ uint8_t eh_valid_mask;
+
+ unsigned int pi_valid :1; /* is proc_info valid? */
+ unsigned int pi_is_dynamic :1; /* proc_info found via dynamic proc info? */
+ unw_proc_info_t pi; /* info about current procedure */
+
+ /* In case of stack-discontiguities, such as those introduced by
+ signal-delivery on an alternate signal-stack (see
+ sigaltstack(2)), we use the following data-structure to keep
+ track of the register-backing-store areas across on which the
+ current frame may be backed up. Since there are at most 96
+ stacked registers and since we only have to track the current
+ frame and only areas that are not empty, this puts an upper
+ limit on the # of backing-store areas we have to track.
+
+ Note that the rbs-area indexed by rbs_curr identifies the
+ rbs-area that was in effect at the time AR.BSP had the value
+ c->bsp. However, this rbs area may not actually contain the
+ value in the register that c->bsp corresponds to because that
+ register may not have gotten spilled until much later, when a
+ possibly different rbs-area might have been in effect
+ already. */
+ uint8_t rbs_curr; /* index of curr. rbs-area (contains c->bsp) */
+ uint8_t rbs_left_edge; /* index of inner-most valid rbs-area */
+ struct rbs_area
+ {
+ unw_word_t end;
+ unw_word_t size;
+ ia64_loc_t rnat_loc;
+ }
+ rbs_area[96 + 2]; /* 96 stacked regs + 1 extra stack on each side... */
+};
+
+struct ia64_global_unwind_state
+ {
+ pthread_mutex_t lock; /* global data lock */
+
+ volatile char init_done;
+
+ /* Table of registers that prologues can save (and order in which
+ they're saved). */
+ const unsigned char save_order[8];
+
+ /*
+ * uc_addr() may return pointers to these variables. We need to
+ * make sure they don't get written via ia64_put() or
+ * ia64_putfp(). To make it possible to test for these variables
+ * quickly, we collect them in a single sub-structure.
+ */
+ struct
+ {
+ unw_word_t r0; /* r0 is byte-order neutral */
+ unw_fpreg_t f0; /* f0 is byte-order neutral */
+ unw_fpreg_t f1_le, f1_be; /* f1 is byte-order dependent */
+ }
+ read_only;
+ unw_fpreg_t nat_val_le, nat_val_be;
+ unw_fpreg_t int_val_le, int_val_be;
+
+ struct mempool reg_state_pool;
+ struct mempool labeled_state_pool;
+
+# if UNW_DEBUG
+ const char *preg_name[IA64_NUM_PREGS];
+# endif
+ };
+
+#define tdep_getcontext_trace unw_getcontext
+#define tdep_init_done unw.init_done
+#define tdep_init UNW_OBJ(init)
+/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
+ tdep_search_unwind_table. */
+#define tdep_search_unwind_table unw_search_ia64_unwind_table
+#define tdep_find_unwind_table ia64_find_unwind_table
+#define tdep_find_proc_info UNW_OBJ(find_proc_info)
+#define tdep_uc_addr UNW_OBJ(uc_addr)
+#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
+#define tdep_access_reg UNW_OBJ(access_reg)
+#define tdep_access_fpreg UNW_OBJ(access_fpreg)
+#define tdep_fetch_frame(c,ip,n) do {} while(0)
+#define tdep_cache_frame(c) 0
+#define tdep_reuse_frame(c,frame) do {} while(0)
+#define tdep_stash_frame(c,rs) do {} while(0)
+#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
+#define tdep_get_as(c) ((c)->as)
+#define tdep_get_as_arg(c) ((c)->as_arg)
+#define tdep_get_ip(c) ((c)->ip)
+#define tdep_big_endian(as) ((c)->as->big_endian != 0)
+
+#ifndef UNW_LOCAL_ONLY
+# define tdep_put_unwind_info UNW_OBJ(put_unwind_info)
+#endif
+
+/* This can't be an UNW_ARCH_OBJ() because we need separate
+ unw.initialized flags for the local-only and generic versions of
+ the library. Also, if we wanted to have a single, shared global
+ data structure, we couldn't declare "unw" as HIDDEN. */
+#define unw UNW_OBJ(data)
+
+extern void tdep_init (void);
+extern int tdep_find_unwind_table (struct elf_dyn_info *edi,
+ unw_addr_space_t as, char *path,
+ unw_word_t segbase, unw_word_t mapoff,
+ unw_word_t ip);
+extern int tdep_find_proc_info (unw_addr_space_t as, unw_word_t ip,
+ unw_proc_info_t *pi, int need_unwind_info,
+ void *arg);
+extern void tdep_put_unwind_info (unw_addr_space_t as,
+ unw_proc_info_t *pi, void *arg);
+extern void *tdep_uc_addr (ucontext_t *uc, unw_regnum_t regnum,
+ uint8_t *nat_bitnr);
+extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
+ unsigned long *segbase, unsigned long *mapoff,
+ char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
+extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
+ unw_word_t *valp, int write);
+extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
+ unw_fpreg_t *valp, int write);
+
+extern struct ia64_global_unwind_state unw;
+
+/* In user-level, we have no reasonable way of determining the base of
+ an arbitrary backing-store. We default to half the
+ address-space. */
+#define rbs_get_base(c,bspstore,rbs_basep) \
+ (*(rbs_basep) = (bspstore) - (((unw_word_t) 1) << 63), 0)
+
+#endif /* IA64_LIBUNWIND_I_H */
diff --git a/src/pal/src/libunwind/include/tdep-ia64/rse.h b/src/pal/src/libunwind/include/tdep-ia64/rse.h
new file mode 100644
index 0000000000..ee521a5917
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-ia64/rse.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 1998, 1999, 2002, 2003, 2005 Hewlett-Packard Co
+ * David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * Register stack engine related helper functions. This file may be
+ * used in applications, so be careful about the name-space and give
+ * some consideration to non-GNU C compilers (though __inline__ is
+ * fine).
+ */
+#ifndef RSE_H
+#define RSE_H
+
+#include <libunwind.h>
+
+static inline uint64_t
+rse_slot_num (uint64_t addr)
+{
+ return (addr >> 3) & 0x3f;
+}
+
+/*
+ * Return TRUE if ADDR is the address of an RNAT slot.
+ */
+static inline uint64_t
+rse_is_rnat_slot (uint64_t addr)
+{
+ return rse_slot_num (addr) == 0x3f;
+}
+
+/*
+ * Returns the address of the RNAT slot that covers the slot at
+ * address SLOT_ADDR.
+ */
+static inline uint64_t
+rse_rnat_addr (uint64_t slot_addr)
+{
+ return slot_addr | (0x3f << 3);
+}
+
+/*
+ * Calculate the number of registers in the dirty partition starting at
+ * BSPSTORE and ending at BSP. This isn't simply (BSP-BSPSTORE)/8
+ * because every 64th slot stores ar.rnat.
+ */
+static inline uint64_t
+rse_num_regs (uint64_t bspstore, uint64_t bsp)
+{
+ uint64_t slots = (bsp - bspstore) >> 3;
+
+ return slots - (rse_slot_num(bspstore) + slots)/0x40;
+}
+
+/*
+ * The inverse of the above: given bspstore and the number of
+ * registers, calculate ar.bsp.
+ */
+static inline uint64_t
+rse_skip_regs (uint64_t addr, long num_regs)
+{
+ long delta = rse_slot_num(addr) + num_regs;
+
+ if (num_regs < 0)
+ delta -= 0x3e;
+ return addr + ((num_regs + delta/0x3f) << 3);
+}
+
+#endif /* RSE_H */
diff --git a/src/pal/src/libunwind/include/tdep-ia64/script.h b/src/pal/src/libunwind/include/tdep-ia64/script.h
new file mode 100644
index 0000000000..fe3360bf58
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-ia64/script.h
@@ -0,0 +1,85 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2002 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#define IA64_LOG_UNW_CACHE_SIZE 7
+#define IA64_UNW_CACHE_SIZE (1 << IA64_LOG_UNW_CACHE_SIZE)
+
+#define IA64_LOG_UNW_HASH_SIZE (IA64_LOG_UNW_CACHE_SIZE + 1)
+#define IA64_UNW_HASH_SIZE (1 << IA64_LOG_UNW_HASH_SIZE)
+
+typedef unsigned char unw_hash_index_t;
+
+struct ia64_script_insn
+ {
+ unsigned int opc; /* see enum ia64_script_insn_opcode */
+ unsigned int dst;
+ unw_word_t val;
+ };
+
+/* Updating each preserved register may result in one script
+ instruction each. At the end of the script, psp gets popped,
+ accounting for one more instruction. */
+#define IA64_MAX_SCRIPT_LEN (IA64_NUM_PREGS + 1)
+
+struct ia64_script
+ {
+ unw_word_t ip; /* ip this script is for */
+ unw_word_t pr_mask; /* mask of predicates script depends on */
+ unw_word_t pr_val; /* predicate values this script is for */
+ unw_proc_info_t pi; /* info about underlying procedure */
+ unsigned short lru_chain; /* used for least-recently-used chain */
+ unsigned short coll_chain; /* used for hash collisions */
+ unsigned short hint; /* hint for next script to try (or -1) */
+ unsigned short count; /* number of instructions in script */
+ unsigned short abi_marker;
+ struct ia64_script_insn insn[IA64_MAX_SCRIPT_LEN];
+ };
+
+struct ia64_script_cache
+ {
+#ifdef HAVE_ATOMIC_OPS_H
+ AO_TS_t busy; /* is the script-cache busy? */
+#else
+ pthread_mutex_t lock;
+#endif
+ unsigned short lru_head; /* index of lead-recently used script */
+ unsigned short lru_tail; /* index of most-recently used script */
+
+ /* hash table that maps instruction pointer to script index: */
+ unsigned short hash[IA64_UNW_HASH_SIZE];
+
+ uint32_t generation; /* generation number */
+
+ /* script cache: */
+ struct ia64_script buckets[IA64_UNW_CACHE_SIZE];
+ };
+
+#define ia64_cache_proc_info UNW_OBJ(cache_proc_info)
+#define ia64_get_cached_proc_info UNW_OBJ(get_cached_proc_info)
+
+struct cursor; /* forward declaration */
+
+extern int ia64_cache_proc_info (struct cursor *c);
+extern int ia64_get_cached_proc_info (struct cursor *c);
diff --git a/src/pal/src/libunwind/include/tdep-mips/dwarf-config.h b/src/pal/src/libunwind/include/tdep-mips/dwarf-config.h
new file mode 100644
index 0000000000..8006d0b8dd
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-mips/dwarf-config.h
@@ -0,0 +1,54 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef dwarf_config_h
+#define dwarf_config_h
+
+/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not
+ explicitly defined. */
+#define DWARF_NUM_PRESERVED_REGS 188
+
+#define dwarf_to_unw_regnum(reg) (((reg) < 32) ? (reg) : 0)
+
+/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
+#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian)
+
+/* Return the size of an address, for DWARF purposes. */
+#define dwarf_addr_size(addr_space) ((addr_space)->addr_size)
+
+/* Convert a pointer to a dwarf_cursor structure to a pointer to
+ unw_cursor_t. */
+#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
+
+typedef struct dwarf_loc
+ {
+ unw_word_t val;
+#ifndef UNW_LOCAL_ONLY
+ unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */
+#endif
+ }
+dwarf_loc_t;
+
+#endif /* dwarf_config_h */
diff --git a/src/pal/src/libunwind/include/tdep-mips/jmpbuf.h b/src/pal/src/libunwind/include/tdep-mips/jmpbuf.h
new file mode 100644
index 0000000000..c099f9267e
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-mips/jmpbuf.h
@@ -0,0 +1,32 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
+
+/* FIXME for MIPS! */
+
+#define JB_SP 4
+#define JB_RP 5
+#define JB_MASK_SAVED 6
+#define JB_MASK 7
diff --git a/src/pal/src/libunwind/include/tdep-mips/libunwind_i.h b/src/pal/src/libunwind/include/tdep-mips/libunwind_i.h
new file mode 100644
index 0000000000..3fe40c0c05
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-mips/libunwind_i.h
@@ -0,0 +1,331 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef MIPS_LIBUNWIND_I_H
+#define MIPS_LIBUNWIND_I_H
+
+/* Target-dependent definitions that are internal to libunwind but need
+ to be shared with target-independent code. */
+
+#include <stdlib.h>
+#include <libunwind.h>
+
+#if !defined(UNW_REMOTE_ONLY) && _MIPS_SIM == _ABI64
+# include "elf64.h"
+#else
+# include "elf32.h"
+#endif
+#include "mempool.h"
+#include "dwarf.h"
+
+typedef struct
+ {
+ /* no mips-specific fast trace */
+ }
+unw_tdep_frame_t;
+
+struct unw_addr_space
+ {
+ struct unw_accessors acc;
+
+ int big_endian;
+ mips_abi_t abi;
+ unsigned int addr_size;
+
+ unw_caching_policy_t caching_policy;
+#ifdef HAVE_ATOMIC_OPS_H
+ AO_t cache_generation;
+#else
+ uint32_t cache_generation;
+#endif
+ unw_word_t dyn_generation; /* see dyn-common.h */
+ unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
+ struct dwarf_rs_cache global_cache;
+ struct unw_debug_frame_list *debug_frames;
+};
+
+#define tdep_big_endian(as) ((as)->big_endian)
+
+struct cursor
+ {
+ struct dwarf_cursor dwarf; /* must be first */
+ unw_word_t sigcontext_addr;
+ };
+
+#define DWARF_GET_LOC(l) ((l).val)
+
+#ifndef UNW_REMOTE_ONLY
+# if _MIPS_SIM == _ABIN32
+typedef long long mips_reg_t;
+# else
+typedef long mips_reg_t;
+# endif
+#endif
+
+#ifdef UNW_LOCAL_ONLY
+# define DWARF_NULL_LOC DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
+# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
+# define DWARF_IS_REG_LOC(l) 0
+# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \
+ tdep_uc_addr((c)->as_arg, (r)), 0))
+# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
+# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \
+ tdep_uc_addr((c)->as_arg, (r)), 0))
+
+/* FIXME: Implement these for the MIPS FPU. */
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *val = *(unw_fpreg_t *) (intptr_t) DWARF_GET_LOC (loc);
+ return 0;
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *(unw_fpreg_t *) (intptr_t) DWARF_GET_LOC (loc) = val;
+ return 0;
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *val = *(mips_reg_t *) (intptr_t) DWARF_GET_LOC (loc);
+ return 0;
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *(mips_reg_t *) (intptr_t) DWARF_GET_LOC (loc) = val;
+ return 0;
+}
+
+#else /* !UNW_LOCAL_ONLY */
+# define DWARF_LOC_TYPE_FP (1 << 0)
+# define DWARF_LOC_TYPE_REG (1 << 1)
+# define DWARF_NULL_LOC DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l) \
+ ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
+# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
+# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
+# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
+# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
+# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
+# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
+ | DWARF_LOC_TYPE_FP))
+
+static inline int
+read_s32 (struct dwarf_cursor *c, unw_word_t addr, unw_word_t *val)
+{
+ int offset = addr & 4;
+ int ret;
+ unw_word_t memval;
+
+ ret = (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 0, c->as_arg);
+ if (ret < 0)
+ return ret;
+
+ if ((offset != 0) == tdep_big_endian (c->as))
+ *val = (int32_t) memval;
+ else
+ *val = (int32_t) (memval >> 32);
+
+ return 0;
+}
+
+static inline int
+write_s32 (struct dwarf_cursor *c, unw_word_t addr, const unw_word_t *val)
+{
+ int offset = addr & 4;
+ int ret;
+ unw_word_t memval;
+
+ ret = (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 0, c->as_arg);
+ if (ret < 0)
+ return ret;
+
+ if ((offset != 0) == tdep_big_endian (c->as))
+ memval = (memval & ~0xffffffffLL) | (uint32_t) *val;
+ else
+ memval = (memval & 0xffffffffLL) | (uint32_t) (*val << 32);
+
+ return (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 1, c->as_arg);
+}
+
+/* FIXME: Implement these for the MIPS FPU. */
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+ char *valp = (char *) &val;
+ unw_word_t addr;
+ int ret;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ val, 0, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+ if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
+ 0, c->as_arg)) < 0)
+ return ret;
+
+ return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
+ c->as_arg);
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ char *valp = (char *) &val;
+ unw_word_t addr;
+ int ret;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ &val, 1, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+ if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
+ 1, c->as_arg)) < 0)
+ return ret;
+
+ return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
+ 1, c->as_arg);
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ /* If a code-generator were to save a value of type unw_word_t in a
+ floating-point register, we would have to support this case. I
+ suppose it could happen with MMX registers, but does it really
+ happen? */
+ assert (!DWARF_IS_FP_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+ else if (c->as->abi == UNW_MIPS_ABI_O32)
+ return read_s32 (c, DWARF_GET_LOC (loc), val);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ /* If a code-generator were to save a value of type unw_word_t in a
+ floating-point register, we would have to support this case. I
+ suppose it could happen with MMX registers, but does it really
+ happen? */
+ assert (!DWARF_IS_FP_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+ else if (c->as->abi == UNW_MIPS_ABI_O32)
+ return write_s32 (c, DWARF_GET_LOC (loc), &val);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+}
+
+#endif /* !UNW_LOCAL_ONLY */
+
+#define tdep_getcontext_trace unw_getcontext
+#define tdep_init_done UNW_OBJ(init_done)
+#define tdep_init UNW_OBJ(init)
+/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
+ tdep_search_unwind_table. */
+#define tdep_search_unwind_table dwarf_search_unwind_table
+#define tdep_find_unwind_table dwarf_find_unwind_table
+#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
+#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
+#define tdep_access_reg UNW_OBJ(access_reg)
+#define tdep_access_fpreg UNW_OBJ(access_fpreg)
+#define tdep_fetch_frame(c,ip,n) do {} while(0)
+#define tdep_cache_frame(c) 0
+#define tdep_reuse_frame(c,frame) do {} while(0)
+#define tdep_stash_frame(c,rs) do {} while(0)
+#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
+
+#ifdef UNW_LOCAL_ONLY
+# define tdep_find_proc_info(c,ip,n) \
+ dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define tdep_put_unwind_info(as,pi,arg) \
+ dwarf_put_unwind_info((as), (pi), (arg))
+#else
+# define tdep_find_proc_info(c,ip,n) \
+ (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define tdep_put_unwind_info(as,pi,arg) \
+ (*(as)->acc.put_unwind_info)((as), (pi), (arg))
+#endif
+
+#define tdep_get_as(c) ((c)->dwarf.as)
+#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
+#define tdep_get_ip(c) ((c)->dwarf.ip)
+
+extern int tdep_init_done;
+
+extern void tdep_init (void);
+extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
+ unw_dyn_info_t *di, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg);
+extern void *tdep_uc_addr (ucontext_t *uc, int reg);
+extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
+ unsigned long *segbase, unsigned long *mapoff,
+ char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
+extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
+ unw_word_t *valp, int write);
+extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
+ unw_fpreg_t *valp, int write);
+
+#endif /* MIPS_LIBUNWIND_I_H */
diff --git a/src/pal/src/libunwind/include/tdep-ppc32/dwarf-config.h b/src/pal/src/libunwind/include/tdep-ppc32/dwarf-config.h
new file mode 100644
index 0000000000..bf6886b066
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-ppc32/dwarf-config.h
@@ -0,0 +1,56 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+ Copied from libunwind-x86_64.h, modified slightly for building
+ frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
+ Will be replaced when libunwind is ready on ppc64 platform.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef dwarf_config_h
+#define dwarf_config_h
+
+/* For PPC64, 48 GPRs + 33 FPRs + 33 AltiVec + 1 SPE */
+#define DWARF_NUM_PRESERVED_REGS 115
+
+#define DWARF_REGNUM_MAP_LENGTH 115
+
+/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
+#define dwarf_is_big_endian(addr_space) 1
+
+/* Convert a pointer to a dwarf_cursor structure to a pointer to
+ unw_cursor_t. */
+#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
+
+typedef struct dwarf_loc
+ {
+ unw_word_t val;
+#ifndef UNW_LOCAL_ONLY
+ unw_word_t type; /* see X86_LOC_TYPE_* macros. */
+#endif
+ }
+dwarf_loc_t;
+
+#endif /* dwarf_config_h */
diff --git a/src/pal/src/libunwind/include/tdep-ppc32/jmpbuf.h b/src/pal/src/libunwind/include/tdep-ppc32/jmpbuf.h
new file mode 100644
index 0000000000..861e94d971
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-ppc32/jmpbuf.h
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+ Copied from libunwind-x86_64.h, modified slightly for building
+ frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
+ Will be replaced when libunwind is ready on ppc64 platform.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
+
+#define JB_SP 6
+#define JB_RP 7
+#define JB_MASK_SAVED 8
+#define JB_MASK 9
diff --git a/src/pal/src/libunwind/include/tdep-ppc32/libunwind_i.h b/src/pal/src/libunwind/include/tdep-ppc32/libunwind_i.h
new file mode 100644
index 0000000000..4cf6d135f6
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-ppc32/libunwind_i.h
@@ -0,0 +1,314 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+ Copied from libunwind-x86_64.h, modified slightly for building
+ frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
+ Will be replaced when libunwind is ready on ppc64 platform.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef PPC32_LIBUNWIND_I_H
+#define PPC32_LIBUNWIND_I_H
+
+/* Target-dependent definitions that are internal to libunwind but need
+ to be shared with target-independent code. */
+
+#include <stdlib.h>
+#include <libunwind.h>
+
+#include "elf32.h"
+#include "mempool.h"
+#include "dwarf.h"
+
+typedef struct
+ {
+ /* no ppc32-specific fast trace */
+ }
+unw_tdep_frame_t;
+
+struct unw_addr_space
+{
+ struct unw_accessors acc;
+ unw_caching_policy_t caching_policy;
+#ifdef HAVE_ATOMIC_OPS_H
+ AO_t cache_generation;
+#else
+ uint32_t cache_generation;
+#endif
+ unw_word_t dyn_generation; /* see dyn-common.h */
+ unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
+ struct dwarf_rs_cache global_cache;
+ struct unw_debug_frame_list *debug_frames;
+ int validate;
+};
+
+struct cursor
+{
+ struct dwarf_cursor dwarf; /* must be first */
+
+ /* Format of sigcontext structure and address at which it is
+ stored: */
+ enum
+ {
+ PPC_SCF_NONE, /* no signal frame encountered */
+ PPC_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */
+ }
+ sigcontext_format;
+ unw_word_t sigcontext_addr;
+};
+
+#define DWARF_GET_LOC(l) ((l).val)
+
+#ifdef UNW_LOCAL_ONLY
+# define DWARF_NULL_LOC DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
+# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
+# define DWARF_IS_REG_LOC(l) 0
+# define DWARF_IS_FP_LOC(l) 0
+# define DWARF_IS_V_LOC(l) 0
+# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
+# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
+ tdep_uc_addr((c)->as_arg, (r)), 0))
+# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
+ tdep_uc_addr((c)->as_arg, (r)), 0))
+# define DWARF_VREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
+ tdep_uc_addr((c)->as_arg, (r)), 0))
+#else /* !UNW_LOCAL_ONLY */
+
+# define DWARF_LOC_TYPE_FP (1 << 0)
+# define DWARF_LOC_TYPE_REG (1 << 1)
+# define DWARF_LOC_TYPE_V (1 << 2)
+# define DWARF_NULL_LOC DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l) \
+ ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
+# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
+# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
+# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
+# define DWARF_IS_V_LOC(l) (((l).type & DWARF_LOC_TYPE_V) != 0)
+# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
+# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
+# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
+ | DWARF_LOC_TYPE_FP))
+# define DWARF_VREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
+ | DWARF_LOC_TYPE_V))
+
+#endif /* !UNW_LOCAL_ONLY */
+
+static inline int
+dwarf_getvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val)
+{
+ unw_word_t *valp = (unw_word_t *) val;
+ unw_word_t addr;
+ int ret;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ assert (DWARF_IS_V_LOC (loc));
+ assert (!DWARF_IS_FP_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ val, 0, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+
+ if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp,
+ 0, c->as_arg)) < 0)
+ return ret;
+
+ return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 0, c->as_arg);
+}
+
+static inline int
+dwarf_putvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ unw_word_t *valp = (unw_word_t *) & val;
+ unw_word_t addr;
+ int ret;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ assert (DWARF_IS_V_LOC (loc));
+ assert (!DWARF_IS_FP_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ &val, 1, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+ if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp,
+ 1, c->as_arg)) < 0)
+ return ret;
+
+ return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 1, c->as_arg);
+}
+
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val)
+{
+ unw_word_t *valp = (unw_word_t *) val;
+ unw_word_t addr;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ assert (DWARF_IS_FP_LOC (loc));
+ assert (!DWARF_IS_V_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ val, 0, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+ return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 0, c->as_arg);
+
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ unw_word_t *valp = (unw_word_t *) & val;
+ unw_word_t addr;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ assert (DWARF_IS_FP_LOC (loc));
+ assert (!DWARF_IS_V_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ &val, 1, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+
+ return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 1, c->as_arg);
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t * val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ /* If a code-generator were to save a value of type unw_word_t in a
+ floating-point register, we would have to support this case. I
+ suppose it could happen with MMX registers, but does it really
+ happen? */
+ assert (!DWARF_IS_FP_LOC (loc));
+ assert (!DWARF_IS_V_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ /* If a code-generator were to save a value of type unw_word_t in a
+ floating-point register, we would have to support this case. I
+ suppose it could happen with MMX registers, but does it really
+ happen? */
+ assert (!DWARF_IS_FP_LOC (loc));
+ assert (!DWARF_IS_V_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+}
+
+#define tdep_getcontext_trace unw_getcontext
+#define tdep_init_done UNW_OBJ(init_done)
+#define tdep_init UNW_OBJ(init)
+/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
+ tdep_search_unwind_table. */
+#define tdep_search_unwind_table dwarf_search_unwind_table
+#define tdep_find_unwind_table dwarf_find_unwind_table
+#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
+#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
+#define tdep_access_reg UNW_OBJ(access_reg)
+#define tdep_access_fpreg UNW_OBJ(access_fpreg)
+#define tdep_fetch_frame(c,ip,n) do {} while(0)
+#define tdep_cache_frame(c) 0
+#define tdep_reuse_frame(c,frame) do {} while(0)
+#define tdep_stash_frame(c,rs) do {} while(0)
+#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
+#define tdep_get_func_addr UNW_OBJ(get_func_addr)
+
+#ifdef UNW_LOCAL_ONLY
+# define tdep_find_proc_info(c,ip,n) \
+ dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define tdep_put_unwind_info(as,pi,arg) \
+ dwarf_put_unwind_info((as), (pi), (arg))
+#else
+# define tdep_find_proc_info(c,ip,n) \
+ (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define tdep_put_unwind_info(as,pi,arg) \
+ (*(as)->acc.put_unwind_info)((as), (pi), (arg))
+#endif
+
+extern int tdep_fetch_proc_info_post (struct dwarf_cursor *c, unw_word_t ip,
+ int need_unwind_info);
+
+#define tdep_get_as(c) ((c)->dwarf.as)
+#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
+#define tdep_get_ip(c) ((c)->dwarf.ip)
+#define tdep_big_endian(as) 1
+
+extern int tdep_init_done;
+
+extern void tdep_init (void);
+extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
+ unw_dyn_info_t * di,
+ unw_proc_info_t * pi,
+ int need_unwind_info, void *arg);
+extern void *tdep_uc_addr (ucontext_t * uc, int reg);
+extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
+ unsigned long *segbase, unsigned long *mapoff,
+ char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
+extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
+ unw_word_t * valp, int write);
+extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
+ unw_fpreg_t * valp, int write);
+extern int tdep_get_func_addr (unw_addr_space_t as, unw_word_t addr,
+ unw_word_t *entry_point);
+
+#endif /* PPC64_LIBUNWIND_I_H */
diff --git a/src/pal/src/libunwind/include/tdep-ppc64/dwarf-config.h b/src/pal/src/libunwind/include/tdep-ppc64/dwarf-config.h
new file mode 100644
index 0000000000..6d8ef0a940
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-ppc64/dwarf-config.h
@@ -0,0 +1,56 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+ Copied from libunwind-x86_64.h, modified slightly for building
+ frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
+ Will be replaced when libunwind is ready on ppc64 platform.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef dwarf_config_h
+#define dwarf_config_h
+
+/* For PPC64, 48 GPRs + 33 FPRs + 33 AltiVec + 1 SPE */
+#define DWARF_NUM_PRESERVED_REGS 115
+
+#define DWARF_REGNUM_MAP_LENGTH 115
+
+/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
+#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian)
+
+/* Convert a pointer to a dwarf_cursor structure to a pointer to
+ unw_cursor_t. */
+#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
+
+typedef struct dwarf_loc
+ {
+ unw_word_t val;
+#ifndef UNW_LOCAL_ONLY
+ unw_word_t type; /* see X86_LOC_TYPE_* macros. */
+#endif
+ }
+dwarf_loc_t;
+
+#endif /* dwarf_config_h */
diff --git a/src/pal/src/libunwind/include/tdep-ppc64/jmpbuf.h b/src/pal/src/libunwind/include/tdep-ppc64/jmpbuf.h
new file mode 100644
index 0000000000..861e94d971
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-ppc64/jmpbuf.h
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+ Copied from libunwind-x86_64.h, modified slightly for building
+ frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
+ Will be replaced when libunwind is ready on ppc64 platform.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
+
+#define JB_SP 6
+#define JB_RP 7
+#define JB_MASK_SAVED 8
+#define JB_MASK 9
diff --git a/src/pal/src/libunwind/include/tdep-ppc64/libunwind_i.h b/src/pal/src/libunwind/include/tdep-ppc64/libunwind_i.h
new file mode 100644
index 0000000000..975f3bb366
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-ppc64/libunwind_i.h
@@ -0,0 +1,369 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+ Copied from libunwind-x86_64.h, modified slightly for building
+ frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
+ Will be replaced when libunwind is ready on ppc64 platform.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef PPC64_LIBUNWIND_I_H
+#define PPC64_LIBUNWIND_I_H
+
+/* Target-dependent definitions that are internal to libunwind but need
+ to be shared with target-independent code. */
+
+#include <stdlib.h>
+#include <libunwind.h>
+
+#include "elf64.h"
+#include "mempool.h"
+#include "dwarf.h"
+
+typedef struct
+ {
+ /* no ppc64-specific fast trace */
+ }
+unw_tdep_frame_t;
+
+struct unw_addr_space
+{
+ struct unw_accessors acc;
+ int big_endian;
+ ppc64_abi_t abi;
+ unw_caching_policy_t caching_policy;
+#ifdef HAVE_ATOMIC_OPS_H
+ AO_t cache_generation;
+#else
+ uint32_t cache_generation;
+#endif
+ unw_word_t dyn_generation; /* see dyn-common.h */
+ unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
+ struct dwarf_rs_cache global_cache;
+ struct unw_debug_frame_list *debug_frames;
+ int validate;
+};
+
+struct cursor
+{
+ struct dwarf_cursor dwarf; /* must be first */
+
+ /* Format of sigcontext structure and address at which it is
+ stored: */
+ enum
+ {
+ PPC_SCF_NONE, /* no signal frame encountered */
+ PPC_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */
+ }
+ sigcontext_format;
+ unw_word_t sigcontext_addr;
+};
+
+#define DWARF_GET_LOC(l) ((l).val)
+
+#ifdef UNW_LOCAL_ONLY
+# define DWARF_NULL_LOC DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
+# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
+# define DWARF_IS_REG_LOC(l) 0
+# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
+ tdep_uc_addr((c)->as_arg, (r)), 0))
+# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
+# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
+ tdep_uc_addr((c)->as_arg, (r)), 0))
+# define DWARF_VREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
+ tdep_uc_addr((c)->as_arg, (r)), 0))
+
+static inline int
+dwarf_getvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
+ return 0;
+}
+
+static inline int
+dwarf_putvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *(unw_fpreg_t *) DWARF_GET_LOC (loc) = val;
+ return 0;
+}
+
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
+ return 0;
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *(unw_fpreg_t *) DWARF_GET_LOC (loc) = val;
+ return 0;
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *val = *(unw_word_t *) DWARF_GET_LOC (loc);
+ return 0;
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *(unw_word_t *) DWARF_GET_LOC (loc) = val;
+ return 0;
+}
+
+#else /* !UNW_LOCAL_ONLY */
+
+# define DWARF_LOC_TYPE_FP (1 << 0)
+# define DWARF_LOC_TYPE_REG (1 << 1)
+# define DWARF_LOC_TYPE_V (1 << 2)
+# define DWARF_NULL_LOC DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l) \
+ ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
+# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
+# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
+# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
+# define DWARF_IS_V_LOC(l) (((l).type & DWARF_LOC_TYPE_V) != 0)
+# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
+# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
+# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
+ | DWARF_LOC_TYPE_FP))
+# define DWARF_VREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
+ | DWARF_LOC_TYPE_V))
+
+static inline int
+dwarf_getvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val)
+{
+ unw_word_t *valp = (unw_word_t *) val;
+ unw_word_t addr;
+ int ret;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ assert (DWARF_IS_V_LOC (loc));
+ assert (!DWARF_IS_FP_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ val, 0, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+
+ if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp,
+ 0, c->as_arg)) < 0)
+ return ret;
+
+ return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 0, c->as_arg);
+}
+
+static inline int
+dwarf_putvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ unw_word_t *valp = (unw_word_t *) & val;
+ unw_word_t addr;
+ int ret;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ assert (DWARF_IS_V_LOC (loc));
+ assert (!DWARF_IS_FP_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ &val, 1, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+ if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp,
+ 1, c->as_arg)) < 0)
+ return ret;
+
+ return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 1, c->as_arg);
+}
+
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val)
+{
+ unw_word_t *valp = (unw_word_t *) val;
+ unw_word_t addr;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ assert (DWARF_IS_FP_LOC (loc));
+ assert (!DWARF_IS_V_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ val, 0, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+ return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 0, c->as_arg);
+
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ unw_word_t *valp = (unw_word_t *) & val;
+ unw_word_t addr;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ assert (DWARF_IS_FP_LOC (loc));
+ assert (!DWARF_IS_V_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ &val, 1, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+
+ return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 1, c->as_arg);
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t * val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ /* If a code-generator were to save a value of type unw_word_t in a
+ floating-point register, we would have to support this case. I
+ suppose it could happen with MMX registers, but does it really
+ happen? */
+ assert (!DWARF_IS_FP_LOC (loc));
+ assert (!DWARF_IS_V_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ /* If a code-generator were to save a value of type unw_word_t in a
+ floating-point register, we would have to support this case. I
+ suppose it could happen with MMX registers, but does it really
+ happen? */
+ assert (!DWARF_IS_FP_LOC (loc));
+ assert (!DWARF_IS_V_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+}
+
+#endif /* !UNW_LOCAL_ONLY */
+
+#define tdep_getcontext_trace unw_getcontext
+#define tdep_init_done UNW_OBJ(init_done)
+#define tdep_init UNW_OBJ(init)
+/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
+ tdep_search_unwind_table. */
+#define tdep_search_unwind_table dwarf_search_unwind_table
+#define tdep_find_unwind_table dwarf_find_unwind_table
+#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
+#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
+#define tdep_access_reg UNW_OBJ(access_reg)
+#define tdep_access_fpreg UNW_OBJ(access_fpreg)
+#define tdep_fetch_frame(c,ip,n) do {} while(0)
+#define tdep_cache_frame(c) 0
+#define tdep_reuse_frame(c,frame) do {} while(0)
+#define tdep_stash_frame(c,rs) do {} while(0)
+#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
+#define tdep_get_func_addr UNW_OBJ(get_func_addr)
+
+#ifdef UNW_LOCAL_ONLY
+# define tdep_find_proc_info(c,ip,n) \
+ dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define tdep_put_unwind_info(as,pi,arg) \
+ dwarf_put_unwind_info((as), (pi), (arg))
+#else
+# define tdep_find_proc_info(c,ip,n) \
+ (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define tdep_put_unwind_info(as,pi,arg) \
+ (*(as)->acc.put_unwind_info)((as), (pi), (arg))
+#endif
+
+extern int tdep_fetch_proc_info_post (struct dwarf_cursor *c, unw_word_t ip,
+ int need_unwind_info);
+
+#define tdep_get_as(c) ((c)->dwarf.as)
+#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
+#define tdep_get_ip(c) ((c)->dwarf.ip)
+#define tdep_big_endian(as) ((as)->big_endian)
+
+extern int tdep_init_done;
+
+extern void tdep_init (void);
+extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
+ unw_dyn_info_t * di,
+ unw_proc_info_t * pi,
+ int need_unwind_info, void *arg);
+extern void *tdep_uc_addr (ucontext_t * uc, int reg);
+extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
+ unsigned long *segbase, unsigned long *mapoff,
+ char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
+extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
+ unw_word_t * valp, int write);
+extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
+ unw_fpreg_t * valp, int write);
+extern int tdep_get_func_addr (unw_addr_space_t as, unw_word_t addr,
+ unw_word_t *entry_point);
+
+#endif /* PPC64_LIBUNWIND_I_H */
diff --git a/src/pal/src/libunwind/include/tdep-sh/dwarf-config.h b/src/pal/src/libunwind/include/tdep-sh/dwarf-config.h
new file mode 100644
index 0000000000..2f76f5be7f
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-sh/dwarf-config.h
@@ -0,0 +1,49 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef dwarf_config_h
+#define dwarf_config_h
+
+#define DWARF_NUM_PRESERVED_REGS 18
+
+#define dwarf_to_unw_regnum(reg) (((reg) <= UNW_SH_PR) ? (reg) : 0)
+
+/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
+#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian)
+
+/* Convert a pointer to a dwarf_cursor structure to a pointer to
+ unw_cursor_t. */
+#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
+
+typedef struct dwarf_loc
+ {
+ unw_word_t val;
+#ifndef UNW_LOCAL_ONLY
+ unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */
+#endif
+ }
+dwarf_loc_t;
+
+#endif /* dwarf_config_h */
diff --git a/src/pal/src/libunwind/include/tdep-sh/jmpbuf.h b/src/pal/src/libunwind/include/tdep-sh/jmpbuf.h
new file mode 100644
index 0000000000..8b44b5b219
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-sh/jmpbuf.h
@@ -0,0 +1,48 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
+
+/* SH4 glibc jump buffer contents:
+ * 0. r8
+ * 1. r9
+ * 2. r10
+ * 3. r11
+ * 4. r12
+ * 5. r13
+ * 6. r14
+ * 7. r15
+ * 8. pr/pc
+ * 9. gbr
+ * 10. fpscr
+ * 11. fr12
+ * 12. fr13
+ * 13. fr14
+ * 14. fr15
+ */
+
+#define JB_SP 7
+#define JB_RP 8
+#define JB_MASK_SAVED 15
+#define JB_MASK 16
diff --git a/src/pal/src/libunwind/include/tdep-sh/libunwind_i.h b/src/pal/src/libunwind/include/tdep-sh/libunwind_i.h
new file mode 100644
index 0000000000..8ced49104b
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-sh/libunwind_i.h
@@ -0,0 +1,280 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef SH_LIBUNWIND_I_H
+#define SH_LIBUNWIND_I_H
+
+/* Target-dependent definitions that are internal to libunwind but need
+ to be shared with target-independent code. */
+
+#include <stdlib.h>
+#include <libunwind.h>
+
+#include "elf32.h"
+#include "mempool.h"
+#include "dwarf.h"
+
+typedef struct
+ {
+ /* no sh-specific fast trace */
+ }
+unw_tdep_frame_t;
+
+struct unw_addr_space
+ {
+ struct unw_accessors acc;
+ int big_endian;
+ unw_caching_policy_t caching_policy;
+#ifdef HAVE_ATOMIC_OPS_H
+ AO_t cache_generation;
+#else
+ uint32_t cache_generation;
+#endif
+ unw_word_t dyn_generation; /* see dyn-common.h */
+ unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
+ struct dwarf_rs_cache global_cache;
+ struct unw_debug_frame_list *debug_frames;
+ };
+
+struct cursor
+ {
+ struct dwarf_cursor dwarf; /* must be first */
+ enum
+ {
+ SH_SCF_NONE, /* no signal frame */
+ SH_SCF_LINUX_SIGFRAME, /* non-RT signal frame */
+ SH_SCF_LINUX_RT_SIGFRAME, /* RT signal frame */
+ }
+ sigcontext_format;
+ unw_word_t sigcontext_addr;
+ unw_word_t sigcontext_sp;
+ unw_word_t sigcontext_pc;
+ };
+
+#define DWARF_GET_LOC(l) ((l).val)
+
+#ifdef UNW_LOCAL_ONLY
+# define DWARF_NULL_LOC DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
+# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
+# define DWARF_IS_REG_LOC(l) 0
+# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
+ tdep_uc_addr((c)->as_arg, (r)), 0))
+# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
+# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
+ tdep_uc_addr((c)->as_arg, (r)), 0))
+
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
+ return 0;
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *(unw_fpreg_t *) DWARF_GET_LOC (loc) = val;
+ return 0;
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *val = *(unw_word_t *) DWARF_GET_LOC (loc);
+ return 0;
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *(unw_word_t *) DWARF_GET_LOC (loc) = val;
+ return 0;
+}
+
+#else /* !UNW_LOCAL_ONLY */
+# define DWARF_LOC_TYPE_FP (1 << 0)
+# define DWARF_LOC_TYPE_REG (1 << 1)
+# define DWARF_NULL_LOC DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l) \
+ ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
+# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
+# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
+# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
+# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
+# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
+# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
+ | DWARF_LOC_TYPE_FP))
+
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+ char *valp = (char *) &val;
+ unw_word_t addr;
+ int ret;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ val, 0, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+ if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
+ 0, c->as_arg)) < 0)
+ return ret;
+
+ return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
+ c->as_arg);
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ char *valp = (char *) &val;
+ unw_word_t addr;
+ int ret;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ &val, 1, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+ if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
+ 1, c->as_arg)) < 0)
+ return ret;
+
+ return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
+ 1, c->as_arg);
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ /* If a code-generator were to save a value of type unw_word_t in a
+ floating-point register, we would have to support this case. I
+ suppose it could happen with MMX registers, but does it really
+ happen? */
+ assert (!DWARF_IS_FP_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ /* If a code-generator were to save a value of type unw_word_t in a
+ floating-point register, we would have to support this case. I
+ suppose it could happen with MMX registers, but does it really
+ happen? */
+ assert (!DWARF_IS_FP_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+}
+
+#endif /* !UNW_LOCAL_ONLY */
+
+#define tdep_getcontext_trace unw_getcontext
+#define tdep_init_done UNW_OBJ(init_done)
+#define tdep_init UNW_OBJ(init)
+/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
+ tdep_search_unwind_table. */
+#define tdep_search_unwind_table dwarf_search_unwind_table
+#define tdep_find_unwind_table dwarf_find_unwind_table
+#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
+#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
+#define tdep_access_reg UNW_OBJ(access_reg)
+#define tdep_access_fpreg UNW_OBJ(access_fpreg)
+#define tdep_fetch_frame(c,ip,n) do {} while(0)
+#define tdep_cache_frame(c) 0
+#define tdep_reuse_frame(c,frame) do {} while(0)
+#define tdep_stash_frame(c,rs) do {} while(0)
+#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
+
+#ifdef UNW_LOCAL_ONLY
+# define tdep_find_proc_info(c,ip,n) \
+ dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define tdep_put_unwind_info(as,pi,arg) \
+ dwarf_put_unwind_info((as), (pi), (arg))
+#else
+# define tdep_find_proc_info(c,ip,n) \
+ (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define tdep_put_unwind_info(as,pi,arg) \
+ (*(as)->acc.put_unwind_info)((as), (pi), (arg))
+#endif
+
+#define tdep_get_as(c) ((c)->dwarf.as)
+#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
+#define tdep_get_ip(c) ((c)->dwarf.ip)
+#define tdep_big_endian(as) ((as)->big_endian)
+
+extern int tdep_init_done;
+
+extern void tdep_init (void);
+extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
+ unw_dyn_info_t *di, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg);
+extern void *tdep_uc_addr (unw_tdep_context_t *uc, int reg);
+extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
+ unsigned long *segbase, unsigned long *mapoff,
+ char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
+extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
+ unw_word_t *valp, int write);
+extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
+ unw_fpreg_t *valp, int write);
+
+#endif /* SH_LIBUNWIND_I_H */
diff --git a/src/pal/src/libunwind/include/tdep-tilegx/dwarf-config.h b/src/pal/src/libunwind/include/tdep-tilegx/dwarf-config.h
new file mode 100644
index 0000000000..93bc6aaecc
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-tilegx/dwarf-config.h
@@ -0,0 +1,50 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2014 Tilera Corp.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef dwarf_config_h
+#define dwarf_config_h
+
+/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not
+ explicitly defined. */
+#define DWARF_NUM_PRESERVED_REGS 188
+
+#define DWARF_REGNUM_MAP_LENGTH (56 + 2)
+
+/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
+#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian)
+
+/* Convert a pointer to a dwarf_cursor structure to a pointer to
+ unw_cursor_t. */
+#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
+
+typedef struct dwarf_loc
+{
+ unw_word_t val;
+#ifndef UNW_LOCAL_ONLY
+ unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */
+#endif
+} dwarf_loc_t;
+
+#endif /* dwarf_config_h */
diff --git a/src/pal/src/libunwind/include/tdep-tilegx/jmpbuf.h b/src/pal/src/libunwind/include/tdep-tilegx/jmpbuf.h
new file mode 100644
index 0000000000..3afe9e46cc
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-tilegx/jmpbuf.h
@@ -0,0 +1,33 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2014 Tilera Corp.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
+
+/* FIXME for Tilegx! */
+
+#define JB_SP 4
+#define JB_RP 5
+#define JB_MASK_SAVED 6
+#define JB_MASK 7
diff --git a/src/pal/src/libunwind/include/tdep-tilegx/libunwind_i.h b/src/pal/src/libunwind/include/tdep-tilegx/libunwind_i.h
new file mode 100644
index 0000000000..2cfed456a7
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-tilegx/libunwind_i.h
@@ -0,0 +1,263 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2014 Tilera Corp.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef TILEGX_LIBUNWIND_I_H
+#define TILEGX_LIBUNWIND_I_H
+
+/* Target-dependent definitions that are internal to libunwind but need
+ to be shared with target-independent code. */
+
+#include <stdlib.h>
+#include <libunwind.h>
+
+# include "elf64.h"
+#include "mempool.h"
+#include "dwarf.h"
+
+typedef struct
+{
+ /* no Tilegx-specific fast trace */
+} unw_tdep_frame_t;
+
+struct unw_addr_space
+{
+ struct unw_accessors acc;
+
+ int big_endian;
+ tilegx_abi_t abi;
+ unsigned int addr_size;
+
+ unw_caching_policy_t caching_policy;
+#ifdef HAVE_ATOMIC_OPS_H
+ AO_t cache_generation;
+#else
+ uint32_t cache_generation;
+#endif
+ unw_word_t dyn_generation; /* see dyn-common.h */
+ unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
+ struct dwarf_rs_cache global_cache;
+ struct unw_debug_frame_list *debug_frames;
+};
+
+#define tdep_big_endian(as) ((as)->big_endian)
+
+struct cursor
+{
+ struct dwarf_cursor dwarf; /* must be first */
+ unw_word_t sigcontext_addr;
+ unw_word_t sigcontext_sp;
+ unw_word_t sigcontext_pc;
+};
+
+#define DWARF_GET_LOC(l) ((l).val)
+
+#ifndef UNW_REMOTE_ONLY
+typedef long tilegx_reg_t;
+#endif
+
+#ifdef UNW_LOCAL_ONLY
+#define DWARF_NULL_LOC DWARF_LOC (0, 0)
+#define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
+#define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
+#define DWARF_IS_REG_LOC(l) 0
+#define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \
+ tdep_uc_addr((c)->as_arg, (r)), 0))
+#define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
+#define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \
+ tdep_uc_addr((c)->as_arg, (r)), 0))
+
+/* Tilegx has no FP. */
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+ Debug (1, "Tielgx has no fp!\n");
+ abort();
+ return 0;
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ Debug (1, "Tielgx has no fp!\n");
+ abort();
+ return 0;
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+
+ *val = *(tilegx_reg_t *) (intptr_t) DWARF_GET_LOC (loc);
+ return 0;
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+
+ *(tilegx_reg_t *) (intptr_t) DWARF_GET_LOC (loc) = val;
+ return 0;
+}
+
+#else /* !UNW_LOCAL_ONLY */
+#define DWARF_LOC_TYPE_FP (1 << 0)
+#define DWARF_LOC_TYPE_REG (1 << 1)
+#define DWARF_NULL_LOC DWARF_LOC (0, 0)
+#define DWARF_IS_NULL_LOC(l) \
+ ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
+#define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
+#define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
+#define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
+#define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
+#define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
+#define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
+ | DWARF_LOC_TYPE_FP))
+
+/* TILEGX has no fp. */
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+ Debug (1, "Tielgx has no fp!\n");
+ abort();
+ return 0;
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ Debug (1, "Tielgx has no fp!\n");
+ abort();
+ return 0;
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ /* If a code-generator were to save a value of type unw_word_t in a
+ floating-point register, we would have to support this case. I
+ suppose it could happen with MMX registers, but does it really
+ happen? */
+ assert (!DWARF_IS_FP_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ /* If a code-generator were to save a value of type unw_word_t in a
+ floating-point register, we would have to support this case. I
+ suppose it could happen with MMX registers, but does it really
+ happen? */
+ assert (!DWARF_IS_FP_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+}
+
+#endif /* !UNW_LOCAL_ONLY */
+
+#define tdep_getcontext_trace unw_getcontext
+#define tdep_init_done UNW_OBJ(init_done)
+#define tdep_needs_initialization UNW_OBJ(needs_initialization)
+#define tdep_init UNW_OBJ(init)
+/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
+ tdep_search_unwind_table. */
+#define tdep_search_unwind_table dwarf_search_unwind_table
+#define tdep_find_unwind_table dwarf_find_unwind_table
+#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
+#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
+#define tdep_access_reg UNW_OBJ(access_reg)
+#define tdep_access_fpreg UNW_OBJ(access_fpreg)
+#define tdep_fetch_frame(c,ip,n) do {} while(0)
+#define tdep_cache_frame(c) 0
+#define tdep_reuse_frame(c,frame) do {} while(0)
+#define tdep_stash_frame(c,rs) do {} while(0)
+#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
+
+#ifdef UNW_LOCAL_ONLY
+#define tdep_find_proc_info(c,ip,n) \
+ dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+#define tdep_put_unwind_info(as,pi,arg) \
+ dwarf_put_unwind_info((as), (pi), (arg))
+#else
+#define tdep_find_proc_info(c,ip,n) \
+ (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+#define tdep_put_unwind_info(as,pi,arg) \
+ (*(as)->acc.put_unwind_info)((as), (pi), (arg))
+#endif
+
+#define tdep_get_as(c) ((c)->dwarf.as)
+#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
+#define tdep_get_ip(c) ((c)->dwarf.ip)
+
+extern int tdep_init_done;
+
+extern void tdep_init (void);
+extern int tdep_search_unwind_table (unw_addr_space_t as,
+ unw_word_t ip,
+ unw_dyn_info_t *di,
+ unw_proc_info_t *pi,
+ int need_unwind_info,
+ void *arg);
+extern void *tdep_uc_addr (ucontext_t *uc, int reg);
+extern int tdep_get_elf_image (struct elf_image *ei,
+ pid_t pid, unw_word_t ip,
+ unsigned long *segbase,
+ unsigned long *mapoff,
+ char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
+extern int tdep_access_reg (struct cursor *c,
+ unw_regnum_t reg,
+ unw_word_t *valp,
+ int write);
+extern int tdep_access_fpreg (struct cursor *c,
+ unw_regnum_t reg,
+ unw_fpreg_t *valp,
+ int write);
+
+#endif /* TILEGX_LIBUNWIND_I_H */
diff --git a/src/pal/src/libunwind/include/tdep-x86/dwarf-config.h b/src/pal/src/libunwind/include/tdep-x86/dwarf-config.h
new file mode 100644
index 0000000000..f76f9c1c4e
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-x86/dwarf-config.h
@@ -0,0 +1,52 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef dwarf_config_h
+#define dwarf_config_h
+
+/* This matches the value used by GCC (see
+ gcc/config/i386.h:DWARF_FRAME_REGISTERS), which leaves plenty of
+ room for expansion. */
+#define DWARF_NUM_PRESERVED_REGS 17
+
+#define DWARF_REGNUM_MAP_LENGTH 19
+
+/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
+#define dwarf_is_big_endian(addr_space) 0
+
+/* Convert a pointer to a dwarf_cursor structure to a pointer to
+ unw_cursor_t. */
+#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
+
+typedef struct dwarf_loc
+ {
+ unw_word_t val;
+#ifndef UNW_LOCAL_ONLY
+ unw_word_t type; /* see X86_LOC_TYPE_* macros. */
+#endif
+ }
+dwarf_loc_t;
+
+#endif /* dwarf_config_h */
diff --git a/src/pal/src/libunwind/include/tdep-x86/jmpbuf.h b/src/pal/src/libunwind/include/tdep-x86/jmpbuf.h
new file mode 100644
index 0000000000..521dfa6992
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-x86/jmpbuf.h
@@ -0,0 +1,42 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
+
+#if defined __linux__
+
+#define JB_SP 4
+#define JB_RP 5
+#define JB_MASK_SAVED 6
+#define JB_MASK 7
+
+#elif defined __FreeBSD__
+
+#define JB_SP 2
+#define JB_RP 0
+#define JB_MASK_SAVED 11
+#define JB_MASK 7
+
+#endif
diff --git a/src/pal/src/libunwind/include/tdep-x86/libunwind_i.h b/src/pal/src/libunwind/include/tdep-x86/libunwind_i.h
new file mode 100644
index 0000000000..5231189a49
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-x86/libunwind_i.h
@@ -0,0 +1,293 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef X86_LIBUNWIND_I_H
+#define X86_LIBUNWIND_I_H
+
+/* Target-dependent definitions that are internal to libunwind but need
+ to be shared with target-independent code. */
+
+#include <stdlib.h>
+#include <libunwind.h>
+
+#include "elf32.h"
+#include "mempool.h"
+#include "dwarf.h"
+
+typedef struct
+ {
+ /* no x86-specific fast trace */
+ }
+unw_tdep_frame_t;
+
+struct unw_addr_space
+ {
+ struct unw_accessors acc;
+ unw_caching_policy_t caching_policy;
+#ifdef HAVE_ATOMIC_OPS_H
+ AO_t cache_generation;
+#else
+ uint32_t cache_generation;
+#endif
+ unw_word_t dyn_generation; /* see dyn-common.h */
+ unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
+ struct dwarf_rs_cache global_cache;
+ struct unw_debug_frame_list *debug_frames;
+ };
+
+struct cursor
+ {
+ struct dwarf_cursor dwarf; /* must be first */
+
+ /* Format of sigcontext structure and address at which it is
+ stored: */
+ enum
+ {
+ X86_SCF_NONE, /* no signal frame encountered */
+ X86_SCF_LINUX_SIGFRAME, /* Linux x86 sigcontext */
+ X86_SCF_LINUX_RT_SIGFRAME, /* POSIX ucontext_t */
+ X86_SCF_FREEBSD_SIGFRAME, /* FreeBSD x86 sigcontext */
+ X86_SCF_FREEBSD_SIGFRAME4, /* FreeBSD 4.x x86 sigcontext */
+ X86_SCF_FREEBSD_OSIGFRAME, /* FreeBSD pre-4.x x86 sigcontext */
+ X86_SCF_FREEBSD_SYSCALL, /* FreeBSD x86 syscall */
+ }
+ sigcontext_format;
+ unw_word_t sigcontext_addr;
+ int validate;
+ ucontext_t *uc;
+ };
+
+static inline ucontext_t *
+dwarf_get_uc(const struct dwarf_cursor *cursor)
+{
+ const struct cursor *c = (struct cursor *) cursor->as_arg;
+ return c->uc;
+}
+
+#define DWARF_GET_LOC(l) ((l).val)
+
+#ifdef UNW_LOCAL_ONLY
+# define DWARF_NULL_LOC DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
+# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
+# define DWARF_IS_REG_LOC(l) 0
+# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
+ tdep_uc_addr(dwarf_get_uc(c), (r)), 0))
+# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
+# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
+ tdep_uc_addr(dwarf_get_uc(c), (r)), 0))
+
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
+ return 0;
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ *(unw_fpreg_t *) DWARF_GET_LOC (loc) = val;
+ return 0;
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+ if (!DWARF_GET_LOC (loc))
+ return -1;
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+}
+
+#else /* !UNW_LOCAL_ONLY */
+# define DWARF_LOC_TYPE_FP (1 << 0)
+# define DWARF_LOC_TYPE_REG (1 << 1)
+# define DWARF_NULL_LOC DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l) \
+ ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
+# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
+# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
+# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
+# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
+# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
+# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
+ | DWARF_LOC_TYPE_FP))
+
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+ char *valp = (char *) &val;
+ unw_word_t addr;
+ int ret;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ val, 0, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+ if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
+ 0, c->as_arg)) < 0)
+ return ret;
+
+ return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
+ c->as_arg);
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ char *valp = (char *) &val;
+ unw_word_t addr;
+ int ret;
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+ &val, 1, c->as_arg);
+
+ addr = DWARF_GET_LOC (loc);
+ if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
+ 1, c->as_arg)) < 0)
+ return ret;
+
+ return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
+ 1, c->as_arg);
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ /* If a code-generator were to save a value of type unw_word_t in a
+ floating-point register, we would have to support this case. I
+ suppose it could happen with MMX registers, but does it really
+ happen? */
+ assert (!DWARF_IS_FP_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ /* If a code-generator were to save a value of type unw_word_t in a
+ floating-point register, we would have to support this case. I
+ suppose it could happen with MMX registers, but does it really
+ happen? */
+ assert (!DWARF_IS_FP_LOC (loc));
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+}
+
+#endif /* !UNW_LOCAL_ONLY */
+
+#define tdep_getcontext_trace unw_getcontext
+#define tdep_init_done UNW_OBJ(init_done)
+#define tdep_init UNW_OBJ(init)
+/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
+ tdep_search_unwind_table. */
+#define tdep_search_unwind_table dwarf_search_unwind_table
+#define tdep_find_unwind_table dwarf_find_unwind_table
+#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
+#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
+#define tdep_access_reg UNW_OBJ(access_reg)
+#define tdep_access_fpreg UNW_OBJ(access_fpreg)
+#define tdep_fetch_frame(c,ip,n) do {} while(0)
+#define tdep_cache_frame(c) 0
+#define tdep_reuse_frame(c,frame) do {} while(0)
+#define tdep_stash_frame(c,rs) do {} while(0)
+#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
+
+#ifdef UNW_LOCAL_ONLY
+# define tdep_find_proc_info(c,ip,n) \
+ dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define tdep_put_unwind_info(as,pi,arg) \
+ dwarf_put_unwind_info((as), (pi), (arg))
+#else
+# define tdep_find_proc_info(c,ip,n) \
+ (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define tdep_put_unwind_info(as,pi,arg) \
+ (*(as)->acc.put_unwind_info)((as), (pi), (arg))
+#endif
+
+#define tdep_get_as(c) ((c)->dwarf.as)
+#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
+#define tdep_get_ip(c) ((c)->dwarf.ip)
+#define tdep_big_endian(as) 0
+
+extern int tdep_init_done;
+
+extern void tdep_init (void);
+extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
+ unw_dyn_info_t *di, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg);
+extern void *tdep_uc_addr (ucontext_t *uc, int reg);
+extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
+ unsigned long *segbase, unsigned long *mapoff,
+ char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
+extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
+ unw_word_t *valp, int write);
+extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
+ unw_fpreg_t *valp, int write);
+
+#endif /* X86_LIBUNWIND_I_H */
diff --git a/src/pal/src/libunwind/include/tdep-x86_64/dwarf-config.h b/src/pal/src/libunwind/include/tdep-x86_64/dwarf-config.h
new file mode 100644
index 0000000000..ff77808e06
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-x86_64/dwarf-config.h
@@ -0,0 +1,57 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* copy of include/tdep-x86/dwarf-config.h, modified slightly for x86-64
+ some consolidation is possible here */
+
+#ifndef dwarf_config_h
+#define dwarf_config_h
+
+/* XXX need to verify if this value is correct */
+#ifdef CONFIG_MSABI_SUPPORT
+#define DWARF_NUM_PRESERVED_REGS 33
+#else
+#define DWARF_NUM_PRESERVED_REGS 17
+#endif
+
+#define DWARF_REGNUM_MAP_LENGTH DWARF_NUM_PRESERVED_REGS
+
+/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
+#define dwarf_is_big_endian(addr_space) 0
+
+/* Convert a pointer to a dwarf_cursor structure to a pointer to
+ unw_cursor_t. */
+#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
+
+typedef struct dwarf_loc
+ {
+ unw_word_t val;
+ unw_word_t type; /* see X86_LOC_TYPE_* macros. */
+ }
+dwarf_loc_t;
+
+#endif /* dwarf_config_h */
diff --git a/src/pal/src/libunwind/include/tdep-x86_64/jmpbuf.h b/src/pal/src/libunwind/include/tdep-x86_64/jmpbuf.h
new file mode 100644
index 0000000000..d57196676d
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-x86_64/jmpbuf.h
@@ -0,0 +1,43 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#if defined __linux__
+
+/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
+
+#define JB_SP 6
+#define JB_RP 7
+#define JB_MASK_SAVED 8
+#define JB_MASK 9
+
+#elif defined __FreeBSD__
+
+#define JB_SP 2
+#define JB_RP 0
+/* Pretend the ip cannot be 0 and mask is always saved */
+#define JB_MASK_SAVED 0
+#define JB_MASK 9
+
+#endif
diff --git a/src/pal/src/libunwind/include/tdep-x86_64/libunwind_i.h b/src/pal/src/libunwind/include/tdep-x86_64/libunwind_i.h
new file mode 100644
index 0000000000..283525c16a
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep-x86_64/libunwind_i.h
@@ -0,0 +1,264 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef X86_64_LIBUNWIND_I_H
+#define X86_64_LIBUNWIND_I_H
+
+/* Target-dependent definitions that are internal to libunwind but need
+ to be shared with target-independent code. */
+
+#include <stdlib.h>
+#include <libunwind.h>
+
+#include "elf64.h"
+#include "mempool.h"
+#include "dwarf.h"
+
+typedef enum
+ {
+ UNW_X86_64_FRAME_ALIGNED = -3, /* frame stack pointer aligned */
+ UNW_X86_64_FRAME_STANDARD = -2, /* regular rbp, rsp +/- offset */
+ UNW_X86_64_FRAME_SIGRETURN = -1, /* special sigreturn frame */
+ UNW_X86_64_FRAME_OTHER = 0, /* not cacheable (special or unrecognised) */
+ UNW_X86_64_FRAME_GUESSED = 1 /* guessed it was regular, but not known */
+ }
+unw_tdep_frame_type_t;
+
+typedef struct
+ {
+ uint64_t virtual_address;
+ int64_t frame_type : 3; /* unw_tdep_frame_type_t classification */
+ int64_t last_frame : 1; /* non-zero if last frame in chain */
+ int64_t cfa_reg_rsp : 1; /* cfa dwarf base register is rsp vs. rbp */
+ int64_t cfa_reg_offset : 29; /* cfa is at this offset from base register value */
+ int64_t rbp_cfa_offset : 15; /* rbp saved at this offset from cfa (-1 = not saved) */
+ int64_t rsp_cfa_offset : 15; /* rsp saved at this offset from cfa (-1 = not saved) */
+ }
+unw_tdep_frame_t;
+
+struct unw_addr_space
+ {
+ struct unw_accessors acc;
+ unw_caching_policy_t caching_policy;
+#ifdef HAVE_ATOMIC_OPS_H
+ AO_t cache_generation;
+#else
+ uint32_t cache_generation;
+#endif
+ unw_word_t dyn_generation; /* see dyn-common.h */
+ unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
+ struct dwarf_rs_cache global_cache;
+ struct unw_debug_frame_list *debug_frames;
+ };
+
+struct cursor
+ {
+ struct dwarf_cursor dwarf; /* must be first */
+
+ unw_tdep_frame_t frame_info; /* quick tracing assist info */
+
+ /* Format of sigcontext structure and address at which it is
+ stored: */
+ enum
+ {
+ X86_64_SCF_NONE, /* no signal frame encountered */
+ X86_64_SCF_LINUX_RT_SIGFRAME, /* Linux ucontext_t */
+ X86_64_SCF_FREEBSD_SIGFRAME, /* FreeBSD signal frame */
+ X86_64_SCF_FREEBSD_SYSCALL, /* FreeBSD syscall */
+ }
+ sigcontext_format;
+ unw_word_t sigcontext_addr;
+ int validate;
+ ucontext_t *uc;
+ };
+
+static inline ucontext_t *
+dwarf_get_uc(const struct dwarf_cursor *cursor)
+{
+ const struct cursor *c = (struct cursor *) cursor->as_arg;
+ return c->uc;
+}
+
+#define DWARF_GET_LOC(l) ((l).val)
+# define DWARF_LOC_TYPE_MEM (0 << 0)
+# define DWARF_LOC_TYPE_FP (1 << 0)
+# define DWARF_LOC_TYPE_REG (1 << 1)
+# define DWARF_LOC_TYPE_VAL (1 << 2)
+
+# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
+# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
+# define DWARF_IS_MEM_LOC(l) ((l).type == DWARF_LOC_TYPE_MEM)
+# define DWARF_IS_VAL_LOC(l) (((l).type & DWARF_LOC_TYPE_VAL) != 0)
+
+# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
+# define DWARF_VAL_LOC(c,v) DWARF_LOC ((v), DWARF_LOC_TYPE_VAL)
+# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), DWARF_LOC_TYPE_MEM)
+
+#ifdef UNW_LOCAL_ONLY
+# define DWARF_NULL_LOC DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
+# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
+ x86_64_r_uc_addr(dwarf_get_uc(c), (r)), 0))
+# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
+ x86_64_r_uc_addr(dwarf_get_uc(c), (r)), 0))
+
+#else /* !UNW_LOCAL_ONLY */
+
+# define DWARF_NULL_LOC DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l) \
+ ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
+# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
+# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
+ | DWARF_LOC_TYPE_FP))
+
+#endif /* !UNW_LOCAL_ONLY */
+
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ abort ();
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ abort ();
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+ if (DWARF_IS_MEM_LOC (loc))
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+ assert(DWARF_IS_VAL_LOC (loc));
+ *val = DWARF_GET_LOC (loc);
+ return 0;
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+ assert(!DWARF_IS_VAL_LOC (loc));
+
+ if (DWARF_IS_NULL_LOC (loc))
+ return -UNW_EBADREG;
+
+ if (DWARF_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
+ 1, c->as_arg);
+}
+
+#define tdep_getcontext_trace UNW_ARCH_OBJ(getcontext_trace)
+#define tdep_init_done UNW_OBJ(init_done)
+#define tdep_init_mem_validate UNW_OBJ(init_mem_validate)
+#define tdep_init UNW_OBJ(init)
+/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
+ tdep_search_unwind_table. */
+#define tdep_search_unwind_table dwarf_search_unwind_table
+#define tdep_find_unwind_table dwarf_find_unwind_table
+#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
+#define tdep_access_reg UNW_OBJ(access_reg)
+#define tdep_access_fpreg UNW_OBJ(access_fpreg)
+#if __linux__
+# define tdep_fetch_frame UNW_OBJ(fetch_frame)
+# define tdep_cache_frame UNW_OBJ(cache_frame)
+# define tdep_reuse_frame UNW_OBJ(reuse_frame)
+#else
+# define tdep_fetch_frame(c,ip,n) do {} while(0)
+# define tdep_cache_frame(c) 0
+# define tdep_reuse_frame(c,frame) do {} while(0)
+#endif
+#define tdep_stash_frame UNW_OBJ(stash_frame)
+#define tdep_trace UNW_OBJ(tdep_trace)
+#define x86_64_r_uc_addr UNW_OBJ(r_uc_addr)
+
+#ifdef UNW_LOCAL_ONLY
+# define tdep_find_proc_info(c,ip,n) \
+ dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define tdep_put_unwind_info(as,pi,arg) \
+ dwarf_put_unwind_info((as), (pi), (arg))
+#else
+# define tdep_find_proc_info(c,ip,n) \
+ (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define tdep_put_unwind_info(as,pi,arg) \
+ (*(as)->acc.put_unwind_info)((as), (pi), (arg))
+#endif
+
+#define tdep_get_as(c) ((c)->dwarf.as)
+#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
+#define tdep_get_ip(c) ((c)->dwarf.ip)
+#define tdep_big_endian(as) 0
+
+extern int tdep_init_done;
+
+extern void tdep_init (void);
+extern void tdep_init_mem_validate (void);
+extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
+ unw_dyn_info_t *di, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg);
+extern void *x86_64_r_uc_addr (ucontext_t *uc, int reg);
+extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
+ unsigned long *segbase, unsigned long *mapoff,
+ char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
+extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
+ unw_word_t *valp, int write);
+extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
+ unw_fpreg_t *valp, int write);
+#if __linux__
+extern void tdep_fetch_frame (struct dwarf_cursor *c, unw_word_t ip,
+ int need_unwind_info);
+extern int tdep_cache_frame (struct dwarf_cursor *c);
+extern void tdep_reuse_frame (struct dwarf_cursor *c,
+ int frame);
+extern void tdep_stash_frame (struct dwarf_cursor *c,
+ struct dwarf_reg_state *rs);
+#endif
+
+extern int tdep_getcontext_trace (unw_tdep_context_t *);
+extern int tdep_trace (unw_cursor_t *cursor, void **addresses, int *n);
+
+#endif /* X86_64_LIBUNWIND_I_H */
diff --git a/src/pal/src/libunwind/include/tdep/dwarf-config.h b/src/pal/src/libunwind/include/tdep/dwarf-config.h
new file mode 100644
index 0000000000..c759a46c63
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep/dwarf-config.h
@@ -0,0 +1,28 @@
+/* Provide a real file - not a symlink - as it would cause multiarch conflicts
+ when multiple different arch releases are installed simultaneously. */
+
+#if defined __aarch64__
+# include "tdep-aarch64/dwarf-config.h"
+#elif defined __arm__
+# include "tdep-arm/dwarf-config.h"
+#elif defined __hppa__
+# include "tdep-hppa/dwarf-config.h"
+#elif defined __ia64__
+# include "tdep-ia64/dwarf-config.h"
+#elif defined __mips__
+# include "tdep-mips/dwarf-config.h"
+#elif defined __powerpc__ && !defined __powerpc64__
+# include "tdep-ppc32/dwarf-config.h"
+#elif defined __powerpc64__
+# include "tdep-ppc64/dwarf-config.h"
+#elif defined __sh__
+# include "tdep-sh/dwarf-config.h"
+#elif defined __i386__
+# include "tdep-x86/dwarf-config.h"
+#elif defined __x86_64__ || defined __amd64__
+# include "tdep-x86_64/dwarf-config.h"
+#elif defined __tilegx__
+# include "tdep-tilegx/dwarf-config.h"
+#else
+# error "Unsupported arch"
+#endif
diff --git a/src/pal/src/libunwind/include/tdep/jmpbuf.h b/src/pal/src/libunwind/include/tdep/jmpbuf.h
new file mode 100644
index 0000000000..13093a0cdc
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep/jmpbuf.h
@@ -0,0 +1,30 @@
+/* Provide a real file - not a symlink - as it would cause multiarch conflicts
+ when multiple different arch releases are installed simultaneously. */
+
+#ifndef UNW_REMOTE_ONLY
+
+#if defined __aarch64__
+# include "tdep-aarch64/jmpbuf.h"
+#elif defined __arm__
+# include "tdep-arm/jmpbuf.h"
+#elif defined __hppa__
+# include "tdep-hppa/jmpbuf.h"
+#elif defined __ia64__
+# include "tdep-ia64/jmpbuf.h"
+#elif defined __mips__
+# include "tdep-mips/jmpbuf.h"
+#elif defined __powerpc__ && !defined __powerpc64__
+# include "tdep-ppc32/jmpbuf.h"
+#elif defined __powerpc64__
+# include "tdep-ppc64/jmpbuf.h"
+#elif defined __i386__
+# include "tdep-x86/jmpbuf.h"
+#elif defined __x86_64__
+# include "tdep-x86_64/jmpbuf.h"
+#elif defined __tilegx__
+# include "tdep-tilegx/jmpbuf.h"
+#else
+# error "Unsupported arch"
+#endif
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/include/tdep/libunwind_i.h.in b/src/pal/src/libunwind/include/tdep/libunwind_i.h.in
new file mode 100644
index 0000000000..af05a7fba2
--- /dev/null
+++ b/src/pal/src/libunwind/include/tdep/libunwind_i.h.in
@@ -0,0 +1,37 @@
+/* Provide a real file - not a symlink - as it would cause multiarch conflicts
+ when multiple different arch releases are installed simultaneously. */
+
+#ifndef UNW_REMOTE_ONLY
+
+#if defined __aarch64__
+# include "tdep-aarch64/libunwind_i.h"
+#elif defined __arm__
+# include "tdep-arm/libunwind_i.h"
+#elif defined __hppa__
+# include "tdep-hppa/libunwind_i.h"
+#elif defined __ia64__
+# include "tdep-ia64/libunwind_i.h"
+#elif defined __mips__
+# include "tdep-mips/libunwind_i.h"
+#elif defined __powerpc__ && !defined __powerpc64__
+# include "tdep-ppc32/libunwind_i.h"
+#elif defined __powerpc64__
+# include "tdep-ppc64/libunwind_i.h"
+#elif defined __sh__
+# include "tdep-sh/libunwind_i.h"
+#elif defined __i386__
+# include "tdep-x86/libunwind_i.h"
+#elif defined __x86_64__
+# include "tdep-x86_64/libunwind_i.h"
+#elif defined __tilegx__
+# include "tdep-tilegx/libunwind_i.h"
+#else
+# error "Unsupported arch"
+#endif
+
+
+#else /* UNW_REMOTE_ONLY */
+
+# include "tdep-@arch@/libunwind_i.h"
+
+#endif /* UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/include/unwind.h b/src/pal/src/libunwind/include/unwind.h
new file mode 100644
index 0000000000..7cf128deca
--- /dev/null
+++ b/src/pal/src/libunwind/include/unwind.h
@@ -0,0 +1,154 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _UNWIND_H
+#define _UNWIND_H
+
+/* For uint64_t */
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Minimal interface as per C++ ABI draft standard:
+
+ http://www.codesourcery.com/cxx-abi/abi-eh.html */
+
+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 int _Unwind_Action;
+
+#define _UA_SEARCH_PHASE 1
+#define _UA_CLEANUP_PHASE 2
+#define _UA_HANDLER_FRAME 4
+#define _UA_FORCE_UNWIND 8
+
+struct _Unwind_Context; /* opaque data-structure */
+struct _Unwind_Exception; /* forward-declaration */
+
+typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code,
+ struct _Unwind_Exception *);
+
+typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) (int, _Unwind_Action,
+ uint64_t,
+ struct _Unwind_Exception *,
+ struct _Unwind_Context *,
+ void *);
+
+/* The C++ ABI requires exception_class, private_1, and private_2 to
+ be of type uint64 and the entire structure to be
+ double-word-aligned. Please note that exception_class stays 64-bit
+ even on 32-bit machines for gcc compatibility. */
+struct _Unwind_Exception
+ {
+ uint64_t exception_class;
+ _Unwind_Exception_Cleanup_Fn exception_cleanup;
+ unsigned long private_1;
+ unsigned long private_2;
+ } __attribute__((__aligned__));
+
+extern _Unwind_Reason_Code _Unwind_RaiseException (struct _Unwind_Exception *);
+extern _Unwind_Reason_Code _Unwind_ForcedUnwind (struct _Unwind_Exception *,
+ _Unwind_Stop_Fn, void *);
+extern void _Unwind_Resume (struct _Unwind_Exception *);
+extern void _Unwind_DeleteException (struct _Unwind_Exception *);
+extern unsigned long _Unwind_GetGR (struct _Unwind_Context *, int);
+extern void _Unwind_SetGR (struct _Unwind_Context *, int, unsigned long);
+extern unsigned long _Unwind_GetIP (struct _Unwind_Context *);
+extern unsigned long _Unwind_GetIPInfo (struct _Unwind_Context *, int *);
+extern void _Unwind_SetIP (struct _Unwind_Context *, unsigned long);
+extern unsigned long _Unwind_GetLanguageSpecificData (struct _Unwind_Context*);
+extern unsigned long _Unwind_GetRegionStart (struct _Unwind_Context *);
+
+#ifdef _GNU_SOURCE
+
+/* Callback for _Unwind_Backtrace(). The backtrace stops immediately
+ if the callback returns any value other than _URC_NO_REASON. */
+typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (struct _Unwind_Context *,
+ void *);
+
+/* See http://gcc.gnu.org/ml/gcc-patches/2001-09/msg00082.html for why
+ _UA_END_OF_STACK exists. */
+# define _UA_END_OF_STACK 16
+
+/* If the unwind was initiated due to a forced unwind, resume that
+ operation, else re-raise the exception. This is used by
+ __cxa_rethrow(). */
+extern _Unwind_Reason_Code
+ _Unwind_Resume_or_Rethrow (struct _Unwind_Exception *);
+
+/* See http://gcc.gnu.org/ml/gcc-patches/2003-09/msg00154.html for why
+ _Unwind_GetBSP() exists. */
+extern unsigned long _Unwind_GetBSP (struct _Unwind_Context *);
+
+/* Return the "canonical frame address" for the given context.
+ This is used by NPTL... */
+extern unsigned long _Unwind_GetCFA (struct _Unwind_Context *);
+
+/* Return the base-address for data references. */
+extern unsigned long _Unwind_GetDataRelBase (struct _Unwind_Context *);
+
+/* Return the base-address for text references. */
+extern unsigned long _Unwind_GetTextRelBase (struct _Unwind_Context *);
+
+/* Call _Unwind_Trace_Fn once for each stack-frame, without doing any
+ cleanup. The first frame for which the callback is invoked is the
+ one for the caller of _Unwind_Backtrace(). _Unwind_Backtrace()
+ returns _URC_END_OF_STACK when the backtrace stopped due to
+ reaching the end of the call-chain or _URC_FATAL_PHASE1_ERROR if it
+ stops for any other reason. */
+extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *);
+
+/* Find the start-address of the procedure containing the specified IP
+ or NULL if it cannot be found (e.g., because the function has no
+ unwind info). Note: there is not necessarily a one-to-one
+ correspondence between source-level functions and procedures: some
+ functions don't have unwind-info and others are split into multiple
+ procedures. */
+extern void *_Unwind_FindEnclosingFunction (void *);
+
+/* See also Linux Standard Base Spec:
+ http://www.linuxbase.org/spec/refspecs/LSB_1.3.0/gLSB/gLSB/libgcc-s.html */
+
+#endif /* _GNU_SOURCE */
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* _UNWIND_H */
diff --git a/src/pal/src/libunwind/include/x86/jmpbuf.h b/src/pal/src/libunwind/include/x86/jmpbuf.h
new file mode 100644
index 0000000000..94d5984f08
--- /dev/null
+++ b/src/pal/src/libunwind/include/x86/jmpbuf.h
@@ -0,0 +1,31 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
+
+#define JB_SP 4
+#define JB_RP 5
+#define JB_MASK_SAVED 6
+#define JB_MASK 7
diff --git a/src/pal/src/libunwind/scripts/kernel-diff.sh b/src/pal/src/libunwind/scripts/kernel-diff.sh
new file mode 100755
index 0000000000..459194e15a
--- /dev/null
+++ b/src/pal/src/libunwind/scripts/kernel-diff.sh
@@ -0,0 +1,10 @@
+kdir=${1:-../kernel}
+scriptdir=$(dirname $0)
+udir=$(dirname $scriptdir)
+cat $scriptdir/kernel-files.txt | \
+(while read l r; do
+ left=$(eval echo $l)
+ right=$(eval echo $r)
+# echo $left $right
+ diff -up $left $right
+done)
diff --git a/src/pal/src/libunwind/scripts/kernel-files.txt b/src/pal/src/libunwind/scripts/kernel-files.txt
new file mode 100644
index 0000000000..d79e453a33
--- /dev/null
+++ b/src/pal/src/libunwind/scripts/kernel-files.txt
@@ -0,0 +1,19 @@
+$udir/include/tdep-ia64/rse.h $kdir/arch/ia64/unwind/rse.h
+$udir/src/ia64/Ginit_local.c $kdir/arch/ia64/unwind/init_local.c
+$udir/src/ia64/Gis_signal_frame.c $kdir/arch/ia64/unwind/is_signal_frame.c
+$udir/src/ia64/Gparser.c $kdir/arch/ia64/unwind/parser.c
+$udir/src/ia64/Grbs.c $kdir/arch/ia64/unwind/rbs.c
+$udir/src/ia64/Gregs.c $kdir/arch/ia64/unwind/regs.c
+$udir/src/ia64/Gscript.c $kdir/arch/ia64/unwind/script.c
+$udir/src/ia64/Gstep.c $kdir/arch/ia64/unwind/step.c
+$udir/src/ia64/init.h $kdir/arch/ia64/unwind/init.h
+$udir/src/ia64/offsets.h $kdir/arch/ia64/unwind/offsets.h
+$udir/src/ia64/regname.c $kdir/arch/ia64/unwind/regname.c
+$udir/src/ia64/regs.h $kdir/arch/ia64/unwind/regs.h
+$udir/src/ia64/unwind_decoder.h $kdir/arch/ia64/unwind/unwind_decoder.h
+$udir/src/mi/Gget_fpreg.c $kdir/unwind/get_fpreg.c
+$udir/src/mi/Gget_reg.c $kdir/unwind/get_reg.c
+$udir/src/mi/Gset_fpreg.c $kdir/unwind/set_fpreg.c
+$udir/src/mi/Gset_reg.c $kdir/unwind/set_reg.c
+$udir/src/mi/flush_cache.c $kdir/unwind/flush_cache.c
+$udir/src/mi/mempool.c $kdir/unwind/mempool.c
diff --git a/src/pal/src/libunwind/scripts/make-L-files b/src/pal/src/libunwind/scripts/make-L-files
new file mode 100755
index 0000000000..8280e3d76a
--- /dev/null
+++ b/src/pal/src/libunwind/scripts/make-L-files
@@ -0,0 +1,30 @@
+#!/bin/sh
+cwd=`pwd`
+dir=`basename ${cwd}`
+#
+# When compiling a file that goes into libunwind, we only
+# need to compile it when we really do support UNW_LOCAL_ONLY.
+# In contrast, libunwind-tests should always get compiled.
+#
+if test $dir = "tests"; then
+ local_only_test=""
+else
+ local_only_test="defined(UNW_LOCAL_ONLY) && "
+fi
+for gname in `ls G*.c G*.cxx G*.S 2>/dev/null`; do
+ lname="L$(expr $gname : '.\(.*\)')"
+ bk edit $lname >/dev/null 2>&1
+ ext=$(expr $gname : '[^.]*[.]\(.*\)')
+ if [ "$ext" = "S" ]; then
+ include=""
+ else
+ include="#include <libunwind.h>"
+ fi
+ echo -e "\
+#define UNW_LOCAL_ONLY\n\
+$include\n\
+#if ${local_only_test}!defined(UNW_REMOTE_ONLY)\n\
+#include \"$gname\"\n\
+#endif" > $lname
+ echo created $lname
+done
diff --git a/src/pal/src/libunwind/src/CMakeLists.txt b/src/pal/src/libunwind/src/CMakeLists.txt
new file mode 100644
index 0000000000..537177716d
--- /dev/null
+++ b/src/pal/src/libunwind/src/CMakeLists.txt
@@ -0,0 +1,337 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+project(unwind)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+
+include(configure.cmake)
+
+# The HAVE___THREAD set to 1 causes creation of thread local variable with tls_model("initial-exec")
+# which is incompatible with usage of the unwind code in a shared library.
+add_definitions(-DHAVE___THREAD=0)
+add_definitions(-DHAVE_CONFIG_H=1)
+
+add_definitions(-DPACKAGE_STRING="")
+add_definitions(-DPACKAGE_BUGREPORT="")
+
+add_definitions(-D_GNU_SOURCE)
+
+add_compile_options(-Wno-header-guard)
+
+if(CLR_CMAKE_PLATFORM_ARCH_ARM)
+ # Disable warning in asm: use of SP or PC in the list is deprecated
+ add_compile_options(-Wno-inline-asm)
+ # Disable warning due to labs function called on unsigned argument
+ add_compile_options(-Wno-absolute-value)
+ # Disable warning due to incorrect format specifier in debugging printf via the Debug macro
+ add_compile_options(-Wno-format)
+ # Disable warning for a bug in the libunwind source src/arm/Gtrace.c:529, but not in code that we exercise
+ add_compile_options(-Wno-implicit-function-declaration)
+ # We compile code with -std=c99 and the asm keyword is not recognized as it is a gnu extension
+ add_definitions(-Dasm=__asm__)
+ # The arm sources include ex_tables.h from include/tdep-arm without going through a redirection
+ # in include/tdep like it works for similar files on other architectures. So we need to add
+ # the include/tdep-arm to include directories
+ include_directories(../include/tdep-arm)
+elseif(CLR_CMAKE_PLATFORM_ARCH_ARM64)
+ # Disable warning due to labs function called on unsigned argument
+ add_compile_options(-Wno-absolute-value)
+ # We compile code with -std=c99 and the asm keyword is not recognized as it is a gnu extension
+ add_definitions(-Dasm=__asm__)
+elseif(CLR_CMAKE_PLATFORM_ARCH_I386)
+ # Disable warning due to incorrect format specifier in debugging printf via the Debug macro
+ add_compile_options(-Wno-format)
+ # Disable warning for a bug in the libunwind source src/x86/Gos-linux.c, but not in code that we exercise
+ add_compile_options(-Wno-incompatible-pointer-types)
+endif()
+
+SET(libunwind_ptrace_la_SOURCES
+ ptrace/_UPT_elf.c
+ ptrace/_UPT_accessors.c ptrace/_UPT_access_fpreg.c
+ ptrace/_UPT_access_mem.c ptrace/_UPT_access_reg.c
+ ptrace/_UPT_create.c ptrace/_UPT_destroy.c
+ ptrace/_UPT_find_proc_info.c ptrace/_UPT_get_dyn_info_list_addr.c
+ ptrace/_UPT_put_unwind_info.c ptrace/_UPT_get_proc_name.c
+ ptrace/_UPT_reg_offset.c ptrace/_UPT_resume.c
+)
+
+SET(libunwind_coredump_la_SOURCES
+ coredump/_UCD_accessors.c
+ coredump/_UCD_create.c
+ coredump/_UCD_destroy.c
+ coredump/_UCD_access_mem.c
+ coredump/_UCD_elf_map_image.c
+ coredump/_UCD_find_proc_info.c
+ coredump/_UCD_get_proc_name.c
+
+ coredump/_UPT_elf.c
+ coredump/_UPT_access_fpreg.c
+ coredump/_UPT_get_dyn_info_list_addr.c
+ coredump/_UPT_put_unwind_info.c
+ coredump/_UPT_resume.c
+)
+
+# List of arch-independent files needed by generic library (libunwind-$ARCH):
+SET(libunwind_la_SOURCES_generic
+ mi/Gdyn-extract.c mi/Gdyn-remote.c mi/Gfind_dynamic_proc_info.c
+ mi/Gget_accessors.c
+ mi/Gget_proc_info_by_ip.c mi/Gget_proc_name.c
+ mi/Gput_dynamic_unwind_info.c mi/Gdestroy_addr_space.c
+ mi/Gget_reg.c mi/Gset_reg.c
+ mi/Gget_fpreg.c mi/Gset_fpreg.c
+ mi/Gset_caching_policy.c
+ mi/Gset_cache_size.c
+)
+
+SET(libunwind_la_SOURCES_os_linux
+ os-linux.c
+)
+
+SET(libunwind_la_SOURCES_os_linux_local
+# Nothing when we don't want to support CXX exceptions
+)
+
+SET(libunwind_la_SOURCES_os_freebsd
+ os-freebsd.c
+)
+
+SET(libunwind_la_SOURCES_os_freebsd_local
+# Nothing
+)
+
+if(CLR_CMAKE_PLATFORM_LINUX)
+ SET(libunwind_la_SOURCES_os ${libunwind_la_SOURCES_os_linux})
+ SET(libunwind_la_SOURCES_os_local ${libunwind_la_SOURCES_os_linux_local})
+ SET(libunwind_la_SOURCES_x86_os x86/Gos-linux.c)
+ SET(libunwind_x86_la_SOURCES_os x86/getcontext-linux.S)
+ SET(libunwind_la_SOURCES_x86_os_local x86/Los-linux.c)
+ SET(libunwind_la_SOURCES_x86_64_os x86_64/Gos-linux.c)
+ SET(libunwind_la_SOURCES_x86_64_os_local x86_64/Los-linux.c)
+ SET(libunwind_la_SOURCES_arm_os arm/Gos-linux.c)
+ SET(libunwind_la_SOURCES_arm_os_local arm/Los-linux.c)
+ list(APPEND libunwind_coredump_la_SOURCES coredump/_UCD_access_reg_linux.c)
+elseif(CLR_CMAKE_PLATFORM_FREEBSD)
+ SET(libunwind_la_SOURCES_os ${libunwind_la_SOURCES_os_freebsd})
+ SET(libunwind_la_SOURCES_os_local ${libunwind_la_SOURCES_os_freebsd_local})
+ SET(libunwind_la_SOURCES_x86_os x86/Gos-freebsd.c)
+ SET(libunwind_x86_la_SOURCES_os x86/getcontext-freebsd.S)
+ SET(libunwind_la_SOURCES_x86_os_local x86/Los-freebsd.c)
+ SET(libunwind_la_SOURCES_x86_64_os x86_64/Gos-freebsd.c)
+ SET(libunwind_la_SOURCES_x86_64_os_local x86_64/Los-freebsd.c)
+ SET(libunwind_la_SOURCES_arm_os arm/Gos-freebsd.c)
+ SET(libunwind_la_SOURCES_arm_os_local arm/Los-freebsd.c)
+ list(APPEND libunwind_coredump_la_SOURCES coredump/_UCD_access_reg_freebsd.c)
+endif()
+
+# List of arch-independent files needed by both local-only and generic
+# libraries:
+SET(libunwind_la_SOURCES_common
+ ${libunwind_la_SOURCES_os}
+ mi/init.c mi/flush_cache.c mi/mempool.c mi/strerror.c
+)
+
+SET(libunwind_la_SOURCES_local_unwind
+# Nothing when we don't want to support CXX exceptions
+)
+
+# List of arch-independent files needed by local-only library (libunwind):
+SET(libunwind_la_SOURCES_local_nounwind
+ ${libunwind_la_SOURCES_os_local}
+ mi/backtrace.c
+ mi/dyn-cancel.c mi/dyn-info-list.c mi/dyn-register.c
+ mi/Ldyn-extract.c mi/Lfind_dynamic_proc_info.c
+ mi/Lget_accessors.c
+ mi/Lget_proc_info_by_ip.c mi/Lget_proc_name.c
+ mi/Lput_dynamic_unwind_info.c mi/Ldestroy_addr_space.c
+ mi/Lget_reg.c mi/Lset_reg.c
+ mi/Lget_fpreg.c mi/Lset_fpreg.c
+ mi/Lset_caching_policy.c
+ mi/Lset_cache_size.c
+)
+
+SET(libunwind_la_SOURCES_local
+ ${libunwind_la_SOURCES_local_nounwind}
+ ${libunwind_la_SOURCES_local_unwind}
+)
+
+SET(libunwind_dwarf_common_la_SOURCES
+ dwarf/global.c
+)
+
+SET(libunwind_dwarf_local_la_SOURCES
+ dwarf/Lexpr.c dwarf/Lfde.c dwarf/Lparser.c dwarf/Lpe.c
+ dwarf/Lfind_proc_info-lsb.c
+ dwarf/Lfind_unwind_table.c
+)
+
+SET(libunwind_dwarf_generic_la_SOURCES
+ dwarf/Gexpr.c dwarf/Gfde.c dwarf/Gparser.c dwarf/Gpe.c
+ dwarf/Gfind_proc_info-lsb.c
+ dwarf/Gfind_unwind_table.c
+)
+
+SET(libunwind_elf32_la_SOURCES
+ elf32.c
+)
+
+SET(libunwind_elf64_la_SOURCES
+ elf64.c
+)
+SET(libunwind_elfxx_la_SOURCES
+ elfxx.c
+)
+
+# The list of files that go into libunwind and libunwind-aarch64:
+SET(libunwind_la_SOURCES_aarch64_common
+ ${libunwind_la_SOURCES_common}
+ aarch64/is_fpreg.c
+ aarch64/regname.c
+)
+
+# The list of files that go into libunwind:
+SET(libunwind_la_SOURCES_aarch64
+ ${libunwind_la_SOURCES_aarch64_common}
+ ${libunwind_la_SOURCES_local}
+ aarch64/Lapply_reg_state.c aarch64/Lreg_states_iterate.c
+ aarch64/Lcreate_addr_space.c aarch64/Lget_proc_info.c
+ aarch64/Lget_save_loc.c aarch64/Lglobal.c aarch64/Linit.c
+ aarch64/Linit_local.c aarch64/Linit_remote.c
+ aarch64/Lis_signal_frame.c aarch64/Lregs.c aarch64/Lresume.c
+ aarch64/Lstash_frame.c aarch64/Lstep.c aarch64/Ltrace.c
+ aarch64/getcontext.S
+)
+
+SET(libunwind_aarch64_la_SOURCES_aarch64
+ ${libunwind_la_SOURCES_aarch64_common}
+ ${libunwind_la_SOURCES_generic}
+ aarch64/Gapply_reg_state.c aarch64/Greg_states_iterate.c
+ aarch64/Gcreate_addr_space.c aarch64/Gget_proc_info.c
+ aarch64/Gget_save_loc.c aarch64/Gglobal.c aarch64/Ginit.c
+ aarch64/Ginit_local.c aarch64/Ginit_remote.c
+ aarch64/Gis_signal_frame.c aarch64/Gregs.c aarch64/Gresume.c
+ aarch64/Gstash_frame.c aarch64/Gstep.c aarch64/Gtrace.c
+)
+
+# The list of files that go into libunwind and libunwind-arm:
+SET(libunwind_la_SOURCES_arm_common
+ ${libunwind_la_SOURCES_common}
+ arm/is_fpreg.c arm/regname.c
+)
+
+# The list of files that go into libunwind:
+SET(libunwind_la_SOURCES_arm
+ ${libunwind_la_SOURCES_arm_common}
+ ${libunwind_la_SOURCES_arm_os_local}
+ ${libunwind_la_SOURCES_local}
+ arm/getcontext.S
+ arm/Lapply_reg_state.c arm/Lreg_states_iterate.c
+ arm/Lcreate_addr_space.c arm/Lget_proc_info.c arm/Lget_save_loc.c
+ arm/Lglobal.c arm/Linit.c arm/Linit_local.c arm/Linit_remote.c
+ arm/Lregs.c arm/Lresume.c arm/Lstep.c
+ arm/Lex_tables.c arm/Lstash_frame.c arm/Ltrace.c
+)
+
+# The list of files that go into libunwind-arm:
+SET(libunwind_arm_la_SOURCES_arm
+ ${libunwind_la_SOURCES_arm_common}
+ ${libunwind_la_SOURCES_arm_os}
+ ${libunwind_la_SOURCES_generic}
+ arm/Gapply_reg_state.c arm/Greg_states_iterate.c
+ arm/Gcreate_addr_space.c arm/Gget_proc_info.c arm/Gget_save_loc.c
+ arm/Gglobal.c arm/Ginit.c arm/Ginit_local.c arm/Ginit_remote.c
+ arm/Gregs.c arm/Gresume.c arm/Gstep.c
+ arm/Gex_tables.c arm/Gstash_frame.c arm/Gtrace.c
+)
+
+# The list of files that go both into libunwind and libunwind-x86:
+SET(libunwind_la_SOURCES_x86_common
+ ${libunwind_la_SOURCES_common}
+ x86/is_fpreg.c x86/regname.c
+)
+
+# The list of files that go into libunwind:
+SET(libunwind_la_SOURCES_x86
+ ${libunwind_la_SOURCES_x86_common}
+ ${libunwind_la_SOURCES_x86_os_local}
+ ${libunwind_la_SOURCES_local}
+ x86/Lapply_reg_state.c x86/Lreg_states_iterate.c
+ x86/Lcreate_addr_space.c x86/Lget_save_loc.c x86/Lglobal.c
+ x86/Linit.c x86/Linit_local.c x86/Linit_remote.c
+ x86/Lget_proc_info.c x86/Lregs.c
+ x86/Lresume.c x86/Lstep.c
+)
+
+# The list of files that go into libunwind-x86:
+SET(libunwind_x86_la_SOURCES_x86
+ ${libunwind_la_SOURCES_x86_common}
+ ${libunwind_la_SOURCES_x86_os}
+ ${libunwind_la_SOURCES_generic}
+ x86/Gapply_reg_state.c x86/Greg_states_iterate.c
+ x86/Gcreate_addr_space.c x86/Gget_save_loc.c x86/Gglobal.c
+ x86/Ginit.c x86/Ginit_local.c x86/Ginit_remote.c
+ x86/Gget_proc_info.c x86/Gregs.c
+ x86/Gresume.c x86/Gstep.c
+)
+
+# The list of files that go both into libunwind and libunwind-x86_64:
+SET(libunwind_la_SOURCES_x86_64_common
+ ${libunwind_la_SOURCES_common}
+ x86_64/is_fpreg.c x86_64/regname.c
+)
+
+# The list of files that go into libunwind:
+SET(libunwind_la_SOURCES_x86_64
+ ${libunwind_la_SOURCES_x86_64_common}
+ ${libunwind_la_SOURCES_x86_64_os_local}
+ ${libunwind_la_SOURCES_local}
+ x86_64/setcontext.S
+ x86_64/Lapply_reg_state.c x86_64/Lreg_states_iterate.c
+ x86_64/Lcreate_addr_space.c x86_64/Lget_save_loc.c x86_64/Lglobal.c
+ x86_64/Linit.c x86_64/Linit_local.c x86_64/Linit_remote.c
+ x86_64/Lget_proc_info.c x86_64/Lregs.c x86_64/Lresume.c
+ x86_64/Lstash_frame.c x86_64/Lstep.c x86_64/Ltrace.c x86_64/getcontext.S
+)
+
+# The list of files that go into libunwind-x86_64:
+SET(libunwind_x86_64_la_SOURCES_x86_64
+ ${libunwind_la_SOURCES_x86_64_common}
+ ${libunwind_la_SOURCES_x86_64_os}
+ ${libunwind_la_SOURCES_generic}
+ x86_64/Gapply_reg_state.c x86_64/Greg_states_iterate.c
+ x86_64/Gcreate_addr_space.c x86_64/Gget_save_loc.c x86_64/Gglobal.c
+ x86_64/Ginit.c x86_64/Ginit_local.c x86_64/Ginit_remote.c
+ x86_64/Gget_proc_info.c x86_64/Gregs.c x86_64/Gresume.c
+ x86_64/Gstash_frame.c x86_64/Gstep.c x86_64/Gtrace.c
+)
+
+if(CLR_CMAKE_PLATFORM_ARCH_ARM64)
+ SET(libunwind_la_SOURCES ${libunwind_la_SOURCES_aarch64})
+ SET(libunwind_aarch64_la_SOURCES ${libunwind_aarch64_la_SOURCES_aarch64})
+ SET(libunwind_elf_la_SOURCES ${libunwind_elf64_la_SOURCES})
+ list(APPEND libunwind_setjmp_la_SOURCES aarch64/siglongjmp.S)
+elseif(CLR_CMAKE_PLATFORM_ARCH_ARM)
+ SET(libunwind_la_SOURCES ${libunwind_la_SOURCES_arm})
+ SET(libunwind_arm_la_SOURCES ${libunwind_arm_la_SOURCES_arm})
+ SET(libunwind_elf_la_SOURCES ${libunwind_elf32_la_SOURCES})
+ list(APPEND libunwind_setjmp_la_SOURCES arm/siglongjmp.S)
+elseif(CLR_CMAKE_PLATFORM_ARCH_I386)
+ SET(libunwind_la_SOURCES ${libunwind_la_SOURCES_x86} ${libunwind_x86_la_SOURCES_os})
+ SET(libunwind_x86_la_SOURCES ${libunwind_x86_la_SOURCES_x86})
+ SET(libunwind_elf_la_SOURCES ${libunwind_elf32_la_SOURCES})
+ list(APPEND libunwind_setjmp_la_SOURCES x86/longjmp.S x86/siglongjmp.S)
+elseif(CLR_CMAKE_PLATFORM_ARCH_AMD64)
+ SET(libunwind_la_SOURCES ${libunwind_la_SOURCES_x86_64})
+ SET(libunwind_x86_64_la_SOURCES ${libunwind_x86_64_la_SOURCES_x86_64})
+ SET(libunwind_elf_la_SOURCES ${libunwind_elf64_la_SOURCES})
+ list(APPEND libunwind_setjmp_la_SOURCES x86_64/longjmp.S x86_64/siglongjmp.SA)
+endif()
+
+add_library(libunwind
+ OBJECT
+ ${libunwind_la_SOURCES}
+ ${libunwind_dwarf_local_la_SOURCES}
+ ${libunwind_dwarf_common_la_SOURCES}
+ ${libunwind_elf_la_SOURCES}
+)
+
diff --git a/src/pal/src/libunwind/src/Makefile.am b/src/pal/src/libunwind/src/Makefile.am
new file mode 100644
index 0000000000..a557d8d1f4
--- /dev/null
+++ b/src/pal/src/libunwind/src/Makefile.am
@@ -0,0 +1,750 @@
+SOVERSION=8:1:0 # See comments at end of file.
+SETJMP_SO_VERSION=0:0:0
+COREDUMP_SO_VERSION=0:0:0
+#
+# Don't link with start-files since we don't use any constructors/destructors:
+#
+COMMON_SO_LDFLAGS = $(LDFLAGS_NOSTARTFILES)
+
+lib_LIBRARIES =
+lib_LTLIBRARIES =
+if !REMOTE_ONLY
+lib_LTLIBRARIES += libunwind.la
+if BUILD_PTRACE
+lib_LTLIBRARIES += libunwind-ptrace.la
+endif
+if BUILD_COREDUMP
+lib_LTLIBRARIES += libunwind-coredump.la
+endif
+endif
+
+noinst_HEADERS =
+noinst_LTLIBRARIES =
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libunwind-generic.pc
+
+if !REMOTE_ONLY
+pkgconfig_DATA += unwind/libunwind.pc
+endif
+
+if BUILD_PTRACE
+pkgconfig_DATA += ptrace/libunwind-ptrace.pc
+endif
+
+if BUILD_SETJMP
+pkgconfig_DATA += setjmp/libunwind-setjmp.pc
+endif
+
+if BUILD_COREDUMP
+pkgconfig_DATA += coredump/libunwind-coredump.pc
+endif
+
+### libunwind-ptrace:
+libunwind_ptrace_la_SOURCES = \
+ ptrace/_UPT_elf.c \
+ ptrace/_UPT_accessors.c ptrace/_UPT_access_fpreg.c \
+ ptrace/_UPT_access_mem.c ptrace/_UPT_access_reg.c \
+ ptrace/_UPT_create.c ptrace/_UPT_destroy.c \
+ ptrace/_UPT_find_proc_info.c ptrace/_UPT_get_dyn_info_list_addr.c \
+ ptrace/_UPT_put_unwind_info.c ptrace/_UPT_get_proc_name.c \
+ ptrace/_UPT_reg_offset.c ptrace/_UPT_resume.c
+noinst_HEADERS += ptrace/_UPT_internal.h
+
+### libunwind-coredump:
+libunwind_coredump_la_SOURCES = \
+ coredump/_UCD_accessors.c \
+ coredump/_UCD_create.c \
+ coredump/_UCD_destroy.c \
+ coredump/_UCD_access_mem.c \
+ coredump/_UCD_elf_map_image.c \
+ coredump/_UCD_find_proc_info.c \
+ coredump/_UCD_get_proc_name.c \
+ \
+ coredump/_UPT_elf.c \
+ coredump/_UPT_access_fpreg.c \
+ coredump/_UPT_get_dyn_info_list_addr.c \
+ coredump/_UPT_put_unwind_info.c \
+ coredump/_UPT_resume.c
+libunwind_coredump_la_LDFLAGS = $(COMMON_SO_LDFLAGS) \
+ -version-info $(COREDUMP_SO_VERSION)
+libunwind_coredump_la_LIBADD = $(LIBLZMA)
+noinst_HEADERS += coredump/_UCD_internal.h coredump/_UCD_lib.h
+
+### libunwind-setjmp:
+libunwind_setjmp_la_LDFLAGS = $(COMMON_SO_LDFLAGS) \
+ -version-info $(SETJMP_SO_VERSION)
+
+if USE_ELF32
+LIBUNWIND_ELF = libunwind-elf32.la
+endif
+if USE_ELF64
+LIBUNWIND_ELF = libunwind-elf64.la
+endif
+if USE_ELFXX
+LIBUNWIND_ELF = libunwind-elfxx.la
+endif
+
+libunwind_setjmp_la_LIBADD = $(LIBUNWIND_ELF) \
+ libunwind-$(arch).la \
+ libunwind.la -lc
+libunwind_setjmp_la_SOURCES = setjmp/longjmp.c \
+ setjmp/siglongjmp.c
+noinst_HEADERS += setjmp/setjmp_i.h
+
+### libunwind:
+libunwind_la_LIBADD =
+
+# List of arch-independent files needed by both local-only and generic
+# libraries:
+libunwind_la_SOURCES_common = \
+ $(libunwind_la_SOURCES_os) \
+ mi/init.c mi/flush_cache.c mi/mempool.c mi/strerror.c
+
+# List of arch-independent files needed by generic library (libunwind-$ARCH):
+libunwind_la_SOURCES_generic = \
+ mi/Gdyn-extract.c mi/Gdyn-remote.c mi/Gfind_dynamic_proc_info.c \
+ mi/Gget_accessors.c \
+ mi/Gget_proc_info_by_ip.c mi/Gget_proc_name.c \
+ mi/Gput_dynamic_unwind_info.c mi/Gdestroy_addr_space.c \
+ mi/Gget_reg.c mi/Gset_reg.c \
+ mi/Gget_fpreg.c mi/Gset_fpreg.c \
+ mi/Gset_caching_policy.c \
+ mi/Gset_cache_size.c
+
+if SUPPORT_CXX_EXCEPTIONS
+libunwind_la_SOURCES_local_unwind = \
+ unwind/Backtrace.c unwind/DeleteException.c \
+ unwind/FindEnclosingFunction.c unwind/ForcedUnwind.c \
+ unwind/GetBSP.c unwind/GetCFA.c unwind/GetDataRelBase.c \
+ unwind/GetGR.c unwind/GetIP.c unwind/GetLanguageSpecificData.c \
+ unwind/GetRegionStart.c unwind/GetTextRelBase.c \
+ unwind/RaiseException.c unwind/Resume.c \
+ unwind/Resume_or_Rethrow.c unwind/SetGR.c unwind/SetIP.c \
+ unwind/GetIPInfo.c
+
+# _ReadULEB()/_ReadSLEB() are needed for Intel C++ 8.0 compatibility
+libunwind_la_SOURCES_os_linux_local = mi/_ReadULEB.c mi/_ReadSLEB.c
+endif
+
+# List of arch-independent files needed by local-only library (libunwind):
+libunwind_la_SOURCES_local_nounwind = \
+ $(libunwind_la_SOURCES_os_local) \
+ mi/backtrace.c \
+ mi/dyn-cancel.c mi/dyn-info-list.c mi/dyn-register.c \
+ mi/Ldyn-extract.c mi/Lfind_dynamic_proc_info.c \
+ mi/Lget_accessors.c \
+ mi/Lget_proc_info_by_ip.c mi/Lget_proc_name.c \
+ mi/Lput_dynamic_unwind_info.c mi/Ldestroy_addr_space.c \
+ mi/Lget_reg.c mi/Lset_reg.c \
+ mi/Lget_fpreg.c mi/Lset_fpreg.c \
+ mi/Lset_caching_policy.c \
+ mi/Lset_cache_size.c
+
+libunwind_la_SOURCES_local = \
+ $(libunwind_la_SOURCES_local_nounwind) \
+ $(libunwind_la_SOURCES_local_unwind)
+
+noinst_HEADERS += os-linux.h
+libunwind_la_SOURCES_os_linux = os-linux.c
+
+libunwind_la_SOURCES_os_hpux = os-hpux.c
+
+libunwind_la_SOURCES_os_freebsd = os-freebsd.c
+
+libunwind_la_SOURCES_os_qnx = os-qnx.c
+
+libunwind_dwarf_common_la_SOURCES = dwarf/global.c
+
+libunwind_dwarf_local_la_SOURCES = \
+ dwarf/Lexpr.c dwarf/Lfde.c dwarf/Lparser.c dwarf/Lpe.c \
+ dwarf/Lfind_proc_info-lsb.c \
+ dwarf/Lfind_unwind_table.c
+libunwind_dwarf_local_la_LIBADD = libunwind-dwarf-common.la
+
+libunwind_dwarf_generic_la_SOURCES = \
+ dwarf/Gexpr.c dwarf/Gfde.c dwarf/Gparser.c dwarf/Gpe.c \
+ dwarf/Gfind_proc_info-lsb.c \
+ dwarf/Gfind_unwind_table.c
+libunwind_dwarf_generic_la_LIBADD = libunwind-dwarf-common.la
+
+if USE_DWARF
+ noinst_LTLIBRARIES += libunwind-dwarf-common.la libunwind-dwarf-generic.la
+if !REMOTE_ONLY
+ noinst_LTLIBRARIES += libunwind-dwarf-local.la
+endif
+ libunwind_la_LIBADD += libunwind-dwarf-local.la
+endif
+
+noinst_HEADERS += elf32.h elf64.h elfxx.h
+
+libunwind_elf32_la_SOURCES = elf32.c
+libunwind_elf64_la_SOURCES = elf64.c
+libunwind_elfxx_la_SOURCES = elfxx.c
+libunwind_elf32_la_LIBADD = $(LIBLZMA)
+libunwind_elf64_la_LIBADD = $(LIBLZMA)
+libunwind_elfxx_la_LIBADD = $(LIBLZMA)
+
+noinst_LTLIBRARIES += $(LIBUNWIND_ELF)
+libunwind_la_LIBADD += $(LIBUNWIND_ELF)
+
+# The list of files that go into libunwind and libunwind-aarch64:
+noinst_HEADERS += aarch64/init.h aarch64/offsets.h aarch64/unwind_i.h
+libunwind_la_SOURCES_aarch64_common = $(libunwind_la_SOURCES_common) \
+ aarch64/is_fpreg.c aarch64/regname.c
+
+# The list of files that go into libunwind:
+libunwind_la_SOURCES_aarch64 = $(libunwind_la_SOURCES_aarch64_common) \
+ $(libunwind_la_SOURCES_local) \
+ aarch64/Lapply_reg_state.c aarch64/Lreg_states_iterate.c \
+ aarch64/Lcreate_addr_space.c aarch64/Lget_proc_info.c \
+ aarch64/Lget_save_loc.c aarch64/Lglobal.c aarch64/Linit.c \
+ aarch64/Linit_local.c aarch64/Linit_remote.c \
+ aarch64/Lis_signal_frame.c aarch64/Lregs.c aarch64/Lresume.c \
+ aarch64/Lstash_frame.c aarch64/Lstep.c aarch64/Ltrace.c \
+ aarch64/getcontext.S
+
+libunwind_aarch64_la_SOURCES_aarch64 = $(libunwind_la_SOURCES_aarch64_common) \
+ $(libunwind_la_SOURCES_generic) \
+ aarch64/Gapply_reg_state.c aarch64/Greg_states_iterate.c \
+ aarch64/Gcreate_addr_space.c aarch64/Gget_proc_info.c \
+ aarch64/Gget_save_loc.c aarch64/Gglobal.c aarch64/Ginit.c \
+ aarch64/Ginit_local.c aarch64/Ginit_remote.c \
+ aarch64/Gis_signal_frame.c aarch64/Gregs.c aarch64/Gresume.c \
+ aarch64/Gstash_frame.c aarch64/Gstep.c aarch64/Gtrace.c
+
+# The list of files that go into libunwind and libunwind-arm:
+noinst_HEADERS += arm/init.h arm/offsets.h arm/unwind_i.h
+libunwind_la_SOURCES_arm_common = $(libunwind_la_SOURCES_common) \
+ arm/is_fpreg.c arm/regname.c
+
+# The list of files that go into libunwind:
+libunwind_la_SOURCES_arm = $(libunwind_la_SOURCES_arm_common) \
+ $(libunwind_la_SOURCES_arm_os_local) \
+ $(libunwind_la_SOURCES_local) \
+ arm/getcontext.S \
+ arm/Lapply_reg_state.c arm/Lreg_states_iterate.c \
+ arm/Lcreate_addr_space.c arm/Lget_proc_info.c arm/Lget_save_loc.c \
+ arm/Lglobal.c arm/Linit.c arm/Linit_local.c arm/Linit_remote.c \
+ arm/Lregs.c arm/Lresume.c arm/Lstep.c \
+ arm/Lex_tables.c arm/Lstash_frame.c arm/Ltrace.c
+
+# The list of files that go into libunwind-arm:
+libunwind_arm_la_SOURCES_arm = $(libunwind_la_SOURCES_arm_common) \
+ $(libunwind_la_SOURCES_arm_os) \
+ $(libunwind_la_SOURCES_generic) \
+ arm/Gapply_reg_state.c arm/Greg_states_iterate.c \
+ arm/Gcreate_addr_space.c arm/Gget_proc_info.c arm/Gget_save_loc.c \
+ arm/Gglobal.c arm/Ginit.c arm/Ginit_local.c arm/Ginit_remote.c \
+ arm/Gregs.c arm/Gresume.c arm/Gstep.c \
+ arm/Gex_tables.c arm/Gstash_frame.c arm/Gtrace.c
+
+# The list of files that go both into libunwind and libunwind-ia64:
+noinst_HEADERS += ia64/init.h ia64/offsets.h ia64/regs.h \
+ ia64/ucontext_i.h ia64/unwind_decoder.h ia64/unwind_i.h
+libunwind_la_SOURCES_ia64_common = $(libunwind_la_SOURCES_common) \
+ ia64/regname.c
+
+# The list of files that go into libunwind:
+libunwind_la_SOURCES_ia64 = $(libunwind_la_SOURCES_ia64_common) \
+ $(libunwind_la_SOURCES_local) \
+ \
+ ia64/dyn_info_list.S ia64/getcontext.S \
+ \
+ ia64/Lapply_reg_state.c ia64/Lreg_states_iterate.c \
+ ia64/Lcreate_addr_space.c ia64/Lget_proc_info.c ia64/Lget_save_loc.c \
+ ia64/Lglobal.c ia64/Linit.c ia64/Linit_local.c ia64/Linit_remote.c \
+ ia64/Linstall_cursor.S ia64/Lis_signal_frame.c ia64/Lparser.c \
+ ia64/Lrbs.c ia64/Lregs.c ia64/Lresume.c ia64/Lscript.c ia64/Lstep.c \
+ ia64/Ltables.c ia64/Lfind_unwind_table.c
+
+# The list of files that go into libunwind-ia64:
+libunwind_ia64_la_SOURCES_ia64 = $(libunwind_la_SOURCES_ia64_common) \
+ $(libunwind_la_SOURCES_generic) \
+ ia64/Gapply_reg_state.c ia64/Greg_states_iterate.c \
+ ia64/Gcreate_addr_space.c ia64/Gget_proc_info.c ia64/Gget_save_loc.c \
+ ia64/Gglobal.c ia64/Ginit.c ia64/Ginit_local.c ia64/Ginit_remote.c \
+ ia64/Ginstall_cursor.S ia64/Gis_signal_frame.c ia64/Gparser.c \
+ ia64/Grbs.c ia64/Gregs.c ia64/Gresume.c ia64/Gscript.c ia64/Gstep.c \
+ ia64/Gtables.c ia64/Gfind_unwind_table.c
+
+# The list of files that go both into libunwind and libunwind-hppa:
+noinst_HEADERS += hppa/init.h hppa/offsets.h hppa/unwind_i.h
+libunwind_la_SOURCES_hppa_common = $(libunwind_la_SOURCES_common) \
+ hppa/regname.c
+
+# The list of files that go into libunwind:
+libunwind_la_SOURCES_hppa = $(libunwind_la_SOURCES_hppa_common) \
+ $(libunwind_la_SOURCES_local) \
+ hppa/getcontext.S hppa/setcontext.S \
+ hppa/Lapply_reg_state.c hppa/Lreg_states_iterate.c \
+ hppa/Lcreate_addr_space.c hppa/Lget_save_loc.c hppa/Lglobal.c \
+ hppa/Linit.c hppa/Linit_local.c hppa/Linit_remote.c \
+ hppa/Lis_signal_frame.c hppa/Lget_proc_info.c hppa/Lregs.c \
+ hppa/Lresume.c hppa/Lstep.c
+
+# The list of files that go into libunwind-hppa:
+libunwind_hppa_la_SOURCES_hppa = $(libunwind_la_SOURCES_hppa_common) \
+ $(libunwind_la_SOURCES_generic) \
+ hppa/Gapply_reg_state.c hppa/Greg_states_iterate.c \
+ hppa/Gcreate_addr_space.c hppa/Gget_save_loc.c hppa/Gglobal.c \
+ hppa/Ginit.c hppa/Ginit_local.c hppa/Ginit_remote.c \
+ hppa/Gis_signal_frame.c hppa/Gget_proc_info.c hppa/Gregs.c \
+ hppa/Gresume.c hppa/Gstep.c
+
+# The list of files that go info libunwind and libunwind-mips:
+noinst_HEADERS += mips/init.h mips/offsets.h mips/unwind_i.h
+libunwind_la_SOURCES_mips_common = $(libunwind_la_SOURCES_common) \
+ mips/is_fpreg.c mips/regname.c
+
+# The list of files that go into libunwind:
+libunwind_la_SOURCES_mips = $(libunwind_la_SOURCES_mips_common) \
+ $(libunwind_la_SOURCES_local) \
+ mips/getcontext.S \
+ mips/Lapply_reg_state.c mips/Lreg_states_iterate.c \
+ mips/Lcreate_addr_space.c mips/Lget_proc_info.c mips/Lget_save_loc.c \
+ mips/Lglobal.c mips/Linit.c mips/Linit_local.c mips/Linit_remote.c \
+ mips/Lis_signal_frame.c mips/Lregs.c mips/Lresume.c mips/Lstep.c
+
+libunwind_mips_la_SOURCES_mips = $(libunwind_la_SOURCES_mips_common) \
+ $(libunwind_la_SOURCES_generic) \
+ mips/Gapply_reg_state.c mips/Greg_states_iterate.c \
+ mips/Gcreate_addr_space.c mips/Gget_proc_info.c mips/Gget_save_loc.c \
+ mips/Gglobal.c mips/Ginit.c mips/Ginit_local.c mips/Ginit_remote.c \
+ mips/Gis_signal_frame.c mips/Gregs.c mips/Gresume.c mips/Gstep.c
+
+# The list of files that go info libunwind and libunwind-tilegx:
+noinst_HEADERS += tilegx/init.h tilegx/offsets.h tilegx/unwind_i.h
+libunwind_la_SOURCES_tilegx_common = $(libunwind_la_SOURCES_common) \
+ tilegx/is_fpreg.c tilegx/regname.c
+
+# The list of files that go into libunwind:
+libunwind_la_SOURCES_tilegx = $(libunwind_la_SOURCES_tilegx_common) \
+ $(libunwind_la_SOURCES_local) \
+ tilegx/getcontext.S \
+ tilegx/Lapply_reg_state.c tilegx/Lreg_states_iterate.c \
+ tilegx/Lcreate_addr_space.c tilegx/Lget_proc_info.c tilegx/Lget_save_loc.c \
+ tilegx/Lglobal.c tilegx/Linit.c tilegx/Linit_local.c tilegx/Linit_remote.c \
+ tilegx/Lis_signal_frame.c tilegx/Lregs.c tilegx/Lresume.c tilegx/Lstep.c
+
+libunwind_tilegx_la_SOURCES_tilegx = $(libunwind_la_SOURCES_tilegx_common) \
+ $(libunwind_la_SOURCES_generic) \
+ tilegx/Gapply_reg_state.c tilegx/Greg_states_iterate.c \
+ tilegx/Gcreate_addr_space.c tilegx/Gget_proc_info.c tilegx/Gget_save_loc.c \
+ tilegx/Gglobal.c tilegx/Ginit.c tilegx/Ginit_local.c tilegx/Ginit_remote.c \
+ tilegx/Gis_signal_frame.c tilegx/Gregs.c tilegx/Gresume.c tilegx/Gstep.c
+
+
+# The list of files that go both into libunwind and libunwind-x86:
+noinst_HEADERS += x86/init.h x86/offsets.h x86/unwind_i.h
+libunwind_la_SOURCES_x86_common = $(libunwind_la_SOURCES_common) \
+ x86/is_fpreg.c x86/regname.c
+
+# The list of files that go into libunwind:
+libunwind_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \
+ $(libunwind_la_SOURCES_x86_os_local) \
+ $(libunwind_la_SOURCES_local) \
+ x86/Lapply_reg_state.c x86/Lreg_states_iterate.c \
+ x86/Lcreate_addr_space.c x86/Lget_save_loc.c x86/Lglobal.c \
+ x86/Linit.c x86/Linit_local.c x86/Linit_remote.c \
+ x86/Lget_proc_info.c x86/Lregs.c \
+ x86/Lresume.c x86/Lstep.c
+
+# The list of files that go into libunwind-x86:
+libunwind_x86_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \
+ $(libunwind_la_SOURCES_x86_os) \
+ $(libunwind_la_SOURCES_generic) \
+ x86/Gapply_reg_state.c x86/Greg_states_iterate.c \
+ x86/Gcreate_addr_space.c x86/Gget_save_loc.c x86/Gglobal.c \
+ x86/Ginit.c x86/Ginit_local.c x86/Ginit_remote.c \
+ x86/Gget_proc_info.c x86/Gregs.c \
+ x86/Gresume.c x86/Gstep.c
+
+# The list of files that go both into libunwind and libunwind-x86_64:
+noinst_HEADERS += x86_64/offsets.h \
+ x86_64/init.h x86_64/unwind_i.h x86_64/ucontext_i.h
+libunwind_la_SOURCES_x86_64_common = $(libunwind_la_SOURCES_common) \
+ x86_64/is_fpreg.c x86_64/regname.c
+
+# The list of files that go into libunwind:
+libunwind_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common) \
+ $(libunwind_la_SOURCES_x86_64_os_local) \
+ $(libunwind_la_SOURCES_local) \
+ x86_64/setcontext.S \
+ x86_64/Lapply_reg_state.c x86_64/Lreg_states_iterate.c \
+ x86_64/Lcreate_addr_space.c x86_64/Lget_save_loc.c x86_64/Lglobal.c \
+ x86_64/Linit.c x86_64/Linit_local.c x86_64/Linit_remote.c \
+ x86_64/Lget_proc_info.c x86_64/Lregs.c x86_64/Lresume.c \
+ x86_64/Lstash_frame.c x86_64/Lstep.c x86_64/Ltrace.c x86_64/getcontext.S
+
+# The list of files that go into libunwind-x86_64:
+libunwind_x86_64_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common) \
+ $(libunwind_la_SOURCES_x86_64_os) \
+ $(libunwind_la_SOURCES_generic) \
+ x86_64/Gapply_reg_state.c x86_64/Greg_states_iterate.c \
+ x86_64/Gcreate_addr_space.c x86_64/Gget_save_loc.c x86_64/Gglobal.c \
+ x86_64/Ginit.c x86_64/Ginit_local.c x86_64/Ginit_remote.c \
+ x86_64/Gget_proc_info.c x86_64/Gregs.c x86_64/Gresume.c \
+ x86_64/Gstash_frame.c x86_64/Gstep.c x86_64/Gtrace.c
+
+# The list of local files that go to Power 64 and 32:
+libunwind_la_SOURCES_ppc = \
+ ppc/Lget_proc_info.c ppc/Lget_save_loc.c ppc/Linit_local.c \
+ ppc/Linit_remote.c ppc/Lis_signal_frame.c
+
+# The list of generic files that go to Power 64 and 32:
+libunwind_ppc_la_SOURCES_ppc_generic = \
+ ppc/Gget_proc_info.c ppc/Gget_save_loc.c ppc/Ginit_local.c \
+ ppc/Ginit_remote.c ppc/Gis_signal_frame.c
+
+# The list of files that go both into libunwind and libunwind-ppc32:
+noinst_HEADERS += ppc32/init.h ppc32/unwind_i.h ppc32/ucontext_i.h
+libunwind_la_SOURCES_ppc32_common = $(libunwind_la_SOURCES_common) \
+ ppc32/is_fpreg.c ppc32/regname.c ppc32/get_func_addr.c
+
+# The list of files that go into libunwind:
+libunwind_la_SOURCES_ppc32 = $(libunwind_la_SOURCES_ppc32_common) \
+ $(libunwind_la_SOURCES_local) \
+ $(libunwind_la_SOURCES_ppc) \
+ ppc32/Lapply_reg_state.c ppc32/Lreg_states_iterate.c \
+ ppc32/Lcreate_addr_space.c \
+ ppc32/Lglobal.c ppc32/Linit.c \
+ ppc32/Lregs.c ppc32/Lresume.c ppc32/Lstep.c
+
+# The list of files that go into libunwind-ppc32:
+libunwind_ppc32_la_SOURCES_ppc32 = $(libunwind_la_SOURCES_ppc32_common) \
+ $(libunwind_la_SOURCES_generic) \
+ $(libunwind_ppc_la_SOURCES_ppc_generic) \
+ ppc32/Gapply_reg_state.c ppc32/Greg_states_iterate.c \
+ ppc32/Gcreate_addr_space.c \
+ ppc32/Gglobal.c ppc32/Ginit.c \
+ ppc32/Gregs.c ppc32/Gresume.c ppc32/Gstep.c
+
+# The list of files that go both into libunwind and libunwind-ppc64:
+noinst_HEADERS += ppc64/init.h ppc64/unwind_i.h ppc64/ucontext_i.h
+libunwind_la_SOURCES_ppc64_common = $(libunwind_la_SOURCES_common) \
+ ppc64/is_fpreg.c ppc64/regname.c ppc64/get_func_addr.c
+
+# The list of files that go into libunwind:
+libunwind_la_SOURCES_ppc64 = $(libunwind_la_SOURCES_ppc64_common) \
+ $(libunwind_la_SOURCES_local) \
+ $(libunwind_la_SOURCES_ppc) \
+ ppc64/Lapply_reg_state.c ppc64/Lreg_states_iterate.c \
+ ppc64/Lcreate_addr_space.c \
+ ppc64/Lglobal.c ppc64/Linit.c \
+ ppc64/Lregs.c ppc64/Lresume.c ppc64/Lstep.c
+
+# The list of files that go into libunwind-ppc64:
+libunwind_ppc64_la_SOURCES_ppc64 = $(libunwind_la_SOURCES_ppc64_common) \
+ $(libunwind_la_SOURCES_generic) \
+ $(libunwind_ppc_la_SOURCES_ppc_generic) \
+ ppc64/Gapply_reg_state.c ppc64/Greg_states_iterate.c \
+ ppc64/Gcreate_addr_space.c \
+ ppc64/Gglobal.c ppc64/Ginit.c \
+ ppc64/Gregs.c ppc64/Gresume.c ppc64/Gstep.c
+
+# The list of files that go into libunwind and libunwind-sh:
+noinst_HEADERS += sh/init.h sh/offsets.h sh/unwind_i.h
+libunwind_la_SOURCES_sh_common = $(libunwind_la_SOURCES_common) \
+ sh/is_fpreg.c sh/regname.c
+
+# The list of files that go into libunwind:
+libunwind_la_SOURCES_sh = $(libunwind_la_SOURCES_sh_common) \
+ $(libunwind_la_SOURCES_local) \
+ sh/Lapply_reg_state.c sh/Lreg_states_iterate.c \
+ sh/Lcreate_addr_space.c sh/Lget_proc_info.c sh/Lget_save_loc.c \
+ sh/Lglobal.c sh/Linit.c sh/Linit_local.c sh/Linit_remote.c \
+ sh/Lis_signal_frame.c sh/Lregs.c sh/Lresume.c sh/Lstep.c
+
+libunwind_sh_la_SOURCES_sh = $(libunwind_la_SOURCES_sh_common) \
+ $(libunwind_la_SOURCES_generic) \
+ sh/Gapply_reg_state.c sh/Greg_states_iterate.c \
+ sh/Gcreate_addr_space.c sh/Gget_proc_info.c sh/Gget_save_loc.c \
+ sh/Gglobal.c sh/Ginit.c sh/Ginit_local.c sh/Ginit_remote.c \
+ sh/Gis_signal_frame.c sh/Gregs.c sh/Gresume.c sh/Gstep.c
+
+if REMOTE_ONLY
+install-exec-hook:
+# Nothing to do here....
+else
+#
+# This is not ideal, but I know of no other way to install an
+# alias for a library. For the shared version, we have to do
+# a file check before creating the link, because it isn't going
+# to be there if the user configured with --disable-shared.
+#
+install-exec-hook:
+ if test -f $(DESTDIR)$(libdir)/libunwind-$(arch).a; then \
+ cd $(DESTDIR)$(libdir) && $(LN_S) -f libunwind-$(arch).a libunwind-generic.a; \
+ fi
+ if test -f $(DESTDIR)$(libdir)/libunwind-$(arch).so; then \
+ cd $(DESTDIR)$(libdir) && $(LN_S) -f libunwind-$(arch).so \
+ libunwind-generic.so; \
+ fi
+endif
+
+if OS_LINUX
+ libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_linux)
+ libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_linux_local)
+ libunwind_la_SOURCES_x86_os = x86/Gos-linux.c
+ libunwind_x86_la_SOURCES_os = x86/getcontext-linux.S
+ libunwind_la_SOURCES_x86_os_local = x86/Los-linux.c
+ libunwind_la_SOURCES_x86_64_os = x86_64/Gos-linux.c
+ libunwind_la_SOURCES_x86_64_os_local = x86_64/Los-linux.c
+ libunwind_la_SOURCES_arm_os = arm/Gos-linux.c
+ libunwind_la_SOURCES_arm_os_local = arm/Los-linux.c
+ libunwind_coredump_la_SOURCES += coredump/_UCD_access_reg_linux.c
+endif
+
+if OS_HPUX
+ libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_hpux)
+ libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_hpux_local)
+endif
+
+if OS_FREEBSD
+ libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_freebsd)
+ libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_freebsd_local)
+ libunwind_la_SOURCES_x86_os = x86/Gos-freebsd.c
+ libunwind_x86_la_SOURCES_os = x86/getcontext-freebsd.S
+ libunwind_la_SOURCES_x86_os_local = x86/Los-freebsd.c
+ libunwind_la_SOURCES_x86_64_os = x86_64/Gos-freebsd.c
+ libunwind_la_SOURCES_x86_64_os_local = x86_64/Los-freebsd.c
+ libunwind_la_SOURCES_arm_os = arm/Gos-freebsd.c
+ libunwind_la_SOURCES_arm_os_local = arm/Los-freebsd.c
+ libunwind_coredump_la_SOURCES += coredump/_UCD_access_reg_freebsd.c
+endif
+
+if OS_QNX
+ libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_qnx)
+ libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_qnx_local)
+ libunwind_la_SOURCES_arm_os = arm/Gos-other.c
+ libunwind_la_SOURCES_arm_os_local = arm/Los-other.c
+endif
+
+if ARCH_AARCH64
+ lib_LTLIBRARIES += libunwind-aarch64.la
+ libunwind_la_SOURCES = $(libunwind_la_SOURCES_aarch64)
+ libunwind_aarch64_la_SOURCES = $(libunwind_aarch64_la_SOURCES_aarch64)
+ libunwind_aarch64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
+ libunwind_aarch64_la_LIBADD = libunwind-dwarf-generic.la
+ libunwind_aarch64_la_LIBADD += libunwind-elf64.la
+if !REMOTE_ONLY
+ libunwind_aarch64_la_LIBADD += libunwind.la -lc
+endif
+ libunwind_setjmp_la_SOURCES += aarch64/siglongjmp.S
+else
+if ARCH_ARM
+ lib_LTLIBRARIES += libunwind-arm.la
+ libunwind_la_SOURCES = $(libunwind_la_SOURCES_arm)
+ libunwind_arm_la_SOURCES = $(libunwind_arm_la_SOURCES_arm)
+ libunwind_arm_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
+ libunwind_arm_la_LIBADD = libunwind-dwarf-generic.la
+ libunwind_arm_la_LIBADD += libunwind-elf32.la
+if !REMOTE_ONLY
+ libunwind_arm_la_LIBADD += libunwind.la -lc
+endif
+ libunwind_setjmp_la_SOURCES += arm/siglongjmp.S
+else
+if ARCH_IA64
+ BUILT_SOURCES = Gcursor_i.h Lcursor_i.h
+mk_Gcursor_i.s: $(srcdir)/ia64/mk_Gcursor_i.c
+ $(COMPILE) -S "$(srcdir)/ia64/mk_Gcursor_i.c" -o mk_Gcursor_i.s
+mk_Lcursor_i.s: $(srcdir)/ia64/mk_Lcursor_i.c
+ $(COMPILE) -S "$(srcdir)/ia64/mk_Lcursor_i.c" -o mk_Lcursor_i.s
+Gcursor_i.h: mk_Gcursor_i.s
+ "$(srcdir)/ia64/mk_cursor_i" mk_Gcursor_i.s > Gcursor_i.h
+Lcursor_i.h: mk_Lcursor_i.s
+ "$(srcdir)/ia64/mk_cursor_i" mk_Lcursor_i.s > Lcursor_i.h
+
+ lib_LTLIBRARIES += libunwind-ia64.la
+ libunwind_la_SOURCES = $(libunwind_la_SOURCES_ia64)
+ libunwind_ia64_la_SOURCES = $(libunwind_ia64_la_SOURCES_ia64)
+ libunwind_ia64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
+ libunwind_ia64_la_LIBADD = libunwind-elf64.la
+if !REMOTE_ONLY
+ libunwind_ia64_la_LIBADD += libunwind.la -lc
+endif
+ libunwind_setjmp_la_SOURCES += ia64/setjmp.S ia64/sigsetjmp.S \
+ ia64/longjmp.S ia64/siglongjmp.S
+else
+if ARCH_HPPA
+ lib_LTLIBRARIES += libunwind-hppa.la
+ libunwind_la_SOURCES = $(libunwind_la_SOURCES_hppa)
+ libunwind_hppa_la_SOURCES = $(libunwind_hppa_la_SOURCES_hppa)
+ libunwind_hppa_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
+ libunwind_hppa_la_LIBADD = libunwind-dwarf-generic.la
+ libunwind_hppa_la_LIBADD += libunwind-elf32.la
+if !REMOTE_ONLY
+ libunwind_hppa_la_LIBADD += libunwind.la -lc
+endif
+ libunwind_setjmp_la_SOURCES += hppa/siglongjmp.S
+else
+if ARCH_MIPS
+ lib_LTLIBRARIES += libunwind-mips.la
+ libunwind_la_SOURCES = $(libunwind_la_SOURCES_mips)
+ libunwind_mips_la_SOURCES = $(libunwind_mips_la_SOURCES_mips)
+ libunwind_mips_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
+ libunwind_mips_la_LIBADD = libunwind-dwarf-generic.la
+ libunwind_mips_la_LIBADD += libunwind-elfxx.la
+if !REMOTE_ONLY
+ libunwind_mips_la_LIBADD += libunwind.la -lc
+endif
+ libunwind_setjmp_la_SOURCES += mips/siglongjmp.S
+else
+if ARCH_TILEGX
+ lib_LTLIBRARIES += libunwind-tilegx.la
+ libunwind_la_SOURCES = $(libunwind_la_SOURCES_tilegx)
+ libunwind_tilegx_la_SOURCES = $(libunwind_tilegx_la_SOURCES_tilegx)
+ libunwind_tilegx_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
+ libunwind_tilegx_la_LIBADD = libunwind-dwarf-generic.la
+ libunwind_tilegx_la_LIBADD += libunwind-elfxx.la
+if !REMOTE_ONLY
+ libunwind_tilegx_la_LIBADD += libunwind.la -lc
+endif
+ libunwind_setjmp_la_SOURCES += tilegx/siglongjmp.S
+else
+if ARCH_X86
+ lib_LTLIBRARIES += libunwind-x86.la
+ libunwind_la_SOURCES = $(libunwind_la_SOURCES_x86) $(libunwind_x86_la_SOURCES_os)
+ libunwind_x86_la_SOURCES = $(libunwind_x86_la_SOURCES_x86)
+ libunwind_x86_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
+ libunwind_x86_la_LIBADD = libunwind-dwarf-generic.la
+ libunwind_x86_la_LIBADD += libunwind-elf32.la
+if !REMOTE_ONLY
+ libunwind_x86_la_LIBADD += libunwind.la -lc
+endif
+ libunwind_setjmp_la_SOURCES += x86/longjmp.S x86/siglongjmp.S
+else
+if ARCH_X86_64
+ lib_LTLIBRARIES += libunwind-x86_64.la
+ libunwind_la_SOURCES = $(libunwind_la_SOURCES_x86_64)
+ libunwind_x86_64_la_SOURCES = $(libunwind_x86_64_la_SOURCES_x86_64)
+ libunwind_x86_64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
+ libunwind_x86_64_la_LIBADD = libunwind-dwarf-generic.la
+ libunwind_x86_64_la_LIBADD += libunwind-elf64.la
+if !REMOTE_ONLY
+ libunwind_x86_64_la_LIBADD += libunwind.la -lc
+endif
+ libunwind_setjmp_la_SOURCES += x86_64/longjmp.S x86_64/siglongjmp.S
+else
+if ARCH_PPC32
+ lib_LTLIBRARIES += libunwind-ppc32.la
+ libunwind_la_SOURCES = $(libunwind_la_SOURCES_ppc32)
+ libunwind_ppc32_la_SOURCES = $(libunwind_ppc32_la_SOURCES_ppc32)
+ libunwind_ppc32_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
+ libunwind_ppc32_la_LIBADD = libunwind-dwarf-generic.la
+ libunwind_ppc32_la_LIBADD += libunwind-elf32.la
+if !REMOTE_ONLY
+ libunwind_ppc32_la_LIBADD += libunwind.la -lc
+endif
+ libunwind_setjmp_la_SOURCES += ppc/longjmp.S ppc/siglongjmp.S
+else
+if ARCH_PPC64
+ lib_LTLIBRARIES += libunwind-ppc64.la
+ libunwind_la_SOURCES = $(libunwind_la_SOURCES_ppc64)
+ libunwind_ppc64_la_SOURCES = $(libunwind_ppc64_la_SOURCES_ppc64)
+ libunwind_ppc64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
+ libunwind_ppc64_la_LIBADD = libunwind-dwarf-generic.la
+ libunwind_ppc64_la_LIBADD += libunwind-elf64.la
+if !REMOTE_ONLY
+ libunwind_ppc64_la_LIBADD += libunwind.la -lc
+endif
+ libunwind_setjmp_la_SOURCES += ppc/longjmp.S ppc/siglongjmp.S
+else
+if ARCH_SH
+ lib_LTLIBRARIES += libunwind-sh.la
+ libunwind_la_SOURCES = $(libunwind_la_SOURCES_sh)
+ libunwind_sh_la_SOURCES = $(libunwind_sh_la_SOURCES_sh)
+ libunwind_sh_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
+ libunwind_sh_la_LIBADD = libunwind-dwarf-generic.la
+ libunwind_sh_la_LIBADD += libunwind-elf32.la
+if !REMOTE_ONLY
+ libunwind_sh_la_LIBADD += libunwind.la -lc
+endif
+ libunwind_setjmp_la_SOURCES += sh/siglongjmp.S
+
+endif # ARCH_SH
+endif # ARCH_PPC64
+endif # ARCH_PPC32
+endif # ARCH_X86_64
+endif # ARCH_X86
+endif # ARCH_TILEGX
+endif # ARCH_MIPS
+endif # ARCH_HPPA
+endif # ARCH_IA64
+endif # ARCH_ARM
+endif # ARCH_AARCH64
+
+# libunwind-setjmp depends on libunwind-$(arch). Therefore must be added
+# at the end.
+if BUILD_SETJMP
+lib_LTLIBRARIES += libunwind-setjmp.la
+endif
+
+#
+# Don't link with standard libraries, because those may mention
+# libunwind already.
+#
+libunwind_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -XCClinker -nostdlib \
+ $(LDFLAGS_STATIC_LIBCXA) -version-info $(SOVERSION)
+libunwind_la_LIBADD += -lc $(LIBCRTS)
+libunwind_la_LIBADD += $(LIBLZMA)
+
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/tdep-$(arch) -I.
+AM_CCASFLAGS = $(AM_CPPFLAGS)
+noinst_HEADERS += unwind/unwind-internal.h
+
+EXTRA_DIST = $(libunwind_la_SOURCES_aarch64) \
+ $(libunwind_la_SOURCES_arm) \
+ $(libunwind_la_SOURCES_hppa) \
+ $(libunwind_la_SOURCES_ia64) \
+ $(libunwind_la_SOURCES_mips) \
+ $(libunwind_la_SOURCES_sh) \
+ $(libunwind_la_SOURCES_x86) \
+ $(libunwind_la_SOURCES_os_freebsd) \
+ $(libunwind_la_SOURCES_os_linux) \
+ $(libunwind_la_SOURCES_os_hpux) \
+ $(libunwind_la_SOURCES_os_qnx) \
+ $(libunwind_la_SOURCES_common) \
+ $(libunwind_la_SOURCES_local) \
+ $(libunwind_la_SOURCES_generic) \
+ $(libunwind_aarch64_la_SOURCES_aarch64) \
+ $(libunwind_arm_la_SOURCES_arm) \
+ $(libunwind_hppa_la_SOURCES_hppa) \
+ $(libunwind_ia64_la_SOURCES_ia64) \
+ $(libunwind_mips_la_SOURCES_mips) \
+ $(libunwind_sh_la_SOURCES_sh) \
+ $(libunwind_x86_la_SOURCES_x86) \
+ $(libunwind_x86_64_la_SOURCES_x86_64)
+
+MAINTAINERCLEANFILES = Makefile.in
+
+# The -version-info flag accepts an argument of the form
+# `current[:revision[:age]]'. So, passing `-version-info 3:12:1' sets
+# current to 3, revision to 12, and age to 1.
+
+# If either revision or age are omitted, they default to 0. Also note
+# that age must be less than or equal to the current interface number.
+
+# Here are a set of rules to help you update your library version
+# information:
+
+# 1. Start with version information of `0:0:0' for each libtool
+# library.
+
+# 2. Update the version information only immediately before a public
+# release of your software. More frequent updates are unnecessary,
+# and only guarantee that the current interface number gets larger
+# faster.
+
+# 3. If the library source code has changed at all since the last
+# update, then increment revision (`c:r:a' becomes `c:r+1:a').
+
+# 4. If any interfaces have been added, removed, or changed since the
+# last update, increment current, and set revision to 0.
+
+# 5. If any interfaces have been added since the last public release,
+# then increment age.
+
+# 6. If any interfaces have been removed since the last public
+# release, then set age to 0.
diff --git a/src/pal/src/libunwind/src/aarch64/Gapply_reg_state.c b/src/pal/src/libunwind/src/aarch64/Gapply_reg_state.c
new file mode 100644
index 0000000000..82f056da67
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Gapply_reg_state.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+ void *reg_states_data)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
diff --git a/src/pal/src/libunwind/src/aarch64/Gcreate_addr_space.c b/src/pal/src/libunwind/src/aarch64/Gcreate_addr_space.c
new file mode 100644
index 0000000000..f217adc745
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Gcreate_addr_space.c
@@ -0,0 +1,60 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+ Copyright (C) 2013 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "unwind_i.h"
+
+unw_addr_space_t
+unw_create_addr_space (unw_accessors_t *a, int byte_order)
+{
+#ifdef UNW_LOCAL_ONLY
+ return NULL;
+#else
+ unw_addr_space_t as;
+
+ /* AArch64 supports little-endian and big-endian. */
+ if (byte_order != 0 && byte_order != __LITTLE_ENDIAN
+ && byte_order != __BIG_ENDIAN)
+ return NULL;
+
+ as = malloc (sizeof (*as));
+ if (!as)
+ return NULL;
+
+ memset (as, 0, sizeof (*as));
+
+ as->acc = *a;
+
+ /* Default to little-endian for AArch64. */
+ if (byte_order == 0 || byte_order == __LITTLE_ENDIAN)
+ as->big_endian = 0;
+ else
+ as->big_endian = 1;
+
+ return as;
+#endif
+}
diff --git a/src/pal/src/libunwind/src/aarch64/Gget_proc_info.c b/src/pal/src/libunwind/src/aarch64/Gget_proc_info.c
new file mode 100644
index 0000000000..c363d2405d
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Gget_proc_info.c
@@ -0,0 +1,39 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ ret = dwarf_make_proc_info (&c->dwarf);
+ if (ret < 0)
+ return ret;
+
+ *pi = c->dwarf.pi;
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/aarch64/Gget_save_loc.c b/src/pal/src/libunwind/src/aarch64/Gget_save_loc.c
new file mode 100644
index 0000000000..86bbbd03d1
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Gget_save_loc.c
@@ -0,0 +1,100 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+ Copyright (C) 2013 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ dwarf_loc_t loc;
+
+ switch (reg)
+ {
+ case UNW_AARCH64_X0:
+ case UNW_AARCH64_X1:
+ case UNW_AARCH64_X2:
+ case UNW_AARCH64_X3:
+ case UNW_AARCH64_X4:
+ case UNW_AARCH64_X5:
+ case UNW_AARCH64_X6:
+ case UNW_AARCH64_X7:
+ case UNW_AARCH64_X8:
+ case UNW_AARCH64_X9:
+ case UNW_AARCH64_X10:
+ case UNW_AARCH64_X11:
+ case UNW_AARCH64_X12:
+ case UNW_AARCH64_X13:
+ case UNW_AARCH64_X14:
+ case UNW_AARCH64_X15:
+ case UNW_AARCH64_X16:
+ case UNW_AARCH64_X17:
+ case UNW_AARCH64_X18:
+ case UNW_AARCH64_X19:
+ case UNW_AARCH64_X20:
+ case UNW_AARCH64_X21:
+ case UNW_AARCH64_X22:
+ case UNW_AARCH64_X23:
+ case UNW_AARCH64_X24:
+ case UNW_AARCH64_X25:
+ case UNW_AARCH64_X26:
+ case UNW_AARCH64_X27:
+ case UNW_AARCH64_X28:
+ case UNW_AARCH64_X29:
+ case UNW_AARCH64_X30:
+ case UNW_AARCH64_SP:
+ case UNW_AARCH64_PC:
+ case UNW_AARCH64_PSTATE:
+ loc = c->dwarf.loc[reg];
+ break;
+
+ default:
+ loc = DWARF_NULL_LOC; /* default to "not saved" */
+ break;
+ }
+
+ memset (sloc, 0, sizeof (*sloc));
+
+ if (DWARF_IS_NULL_LOC (loc))
+ {
+ sloc->type = UNW_SLT_NONE;
+ return 0;
+ }
+
+#if !defined(UNW_LOCAL_ONLY)
+ if (DWARF_IS_REG_LOC (loc))
+ {
+ sloc->type = UNW_SLT_REG;
+ sloc->u.regnum = DWARF_GET_LOC (loc);
+ }
+ else
+#endif
+ {
+ sloc->type = UNW_SLT_MEMORY;
+ sloc->u.addr = DWARF_GET_LOC (loc);
+ }
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/aarch64/Gglobal.c b/src/pal/src/libunwind/src/aarch64/Gglobal.c
new file mode 100644
index 0000000000..72e36b2d4d
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Gglobal.c
@@ -0,0 +1,57 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+ Copyright (C) 2013 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "dwarf_i.h"
+
+HIDDEN define_lock (aarch64_lock);
+HIDDEN int tdep_init_done;
+
+HIDDEN void
+tdep_init (void)
+{
+ intrmask_t saved_mask;
+
+ sigfillset (&unwi_full_mask);
+
+ lock_acquire (&aarch64_lock, saved_mask);
+ {
+ if (tdep_init_done)
+ /* another thread else beat us to it... */
+ goto out;
+
+ mi_init ();
+
+ dwarf_init ();
+
+#ifndef UNW_REMOTE_ONLY
+ aarch64_local_addr_space_init ();
+#endif
+ tdep_init_done = 1; /* signal that we're initialized... */
+ }
+ out:
+ lock_release (&aarch64_lock, saved_mask);
+}
diff --git a/src/pal/src/libunwind/src/aarch64/Ginit.c b/src/pal/src/libunwind/src/aarch64/Ginit.c
new file mode 100644
index 0000000000..9c4eae8298
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Ginit.c
@@ -0,0 +1,190 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+ Copyright (C) 2013 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "unwind_i.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+/* unw_local_addr_space is a NULL pointer in this case. */
+unw_addr_space_t unw_local_addr_space;
+
+#else /* !UNW_REMOTE_ONLY */
+
+static struct unw_addr_space local_addr_space;
+
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
+
+static inline void *
+uc_addr (ucontext_t *uc, int reg)
+{
+ if (reg >= UNW_AARCH64_X0 && reg < UNW_AARCH64_V0)
+ return &uc->uc_mcontext.regs[reg];
+ else if (reg >= UNW_AARCH64_V0 && reg <= UNW_AARCH64_V31)
+ return &GET_FPCTX(uc)->vregs[reg - UNW_AARCH64_V0];
+ else
+ return NULL;
+}
+
+# ifdef UNW_LOCAL_ONLY
+
+HIDDEN void *
+tdep_uc_addr (ucontext_t *uc, int reg)
+{
+ return uc_addr (uc, reg);
+}
+
+# endif /* UNW_LOCAL_ONLY */
+
+HIDDEN unw_dyn_info_list_t _U_dyn_info_list;
+
+/* XXX fix me: there is currently no way to locate the dyn-info list
+ by a remote unwinder. On ia64, this is done via a special
+ unwind-table entry. Perhaps something similar can be done with
+ DWARF2 unwind info. */
+
+static void
+put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
+{
+ /* it's a no-op */
+}
+
+static int
+get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
+ void *arg)
+{
+ *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list;
+ return 0;
+}
+
+static int
+access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
+ void *arg)
+{
+ if (write)
+ {
+ Debug (16, "mem[%lx] <- %lx\n", addr, *val);
+ *(unw_word_t *) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_word_t *) addr;
+ Debug (16, "mem[%lx] -> %lx\n", addr, *val);
+ }
+ return 0;
+}
+
+static int
+access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
+ void *arg)
+{
+ unw_word_t *addr;
+ ucontext_t *uc = arg;
+
+ if (unw_is_fpreg (reg))
+ goto badreg;
+
+ if (!(addr = uc_addr (uc, reg)))
+ goto badreg;
+
+ if (write)
+ {
+ *(unw_word_t *) addr = *val;
+ Debug (12, "%s <- %lx\n", unw_regname (reg), *val);
+ }
+ else
+ {
+ *val = *(unw_word_t *) addr;
+ Debug (12, "%s -> %lx\n", unw_regname (reg), *val);
+ }
+ return 0;
+
+ badreg:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+}
+
+static int
+access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
+ int write, void *arg)
+{
+ ucontext_t *uc = arg;
+ unw_fpreg_t *addr;
+
+ if (!unw_is_fpreg (reg))
+ goto badreg;
+
+ if (!(addr = uc_addr (uc, reg)))
+ goto badreg;
+
+ if (write)
+ {
+ Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg),
+ ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
+ *(unw_fpreg_t *) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_fpreg_t *) addr;
+ Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg),
+ ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
+ }
+ return 0;
+
+ badreg:
+ Debug (1, "bad register number %u\n", reg);
+ /* attempt to access a non-preserved register */
+ return -UNW_EBADREG;
+}
+
+static int
+get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
+ char *buf, size_t buf_len, unw_word_t *offp,
+ void *arg)
+{
+ return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
+}
+
+HIDDEN void
+aarch64_local_addr_space_init (void)
+{
+ memset (&local_addr_space, 0, sizeof (local_addr_space));
+ local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
+ local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
+ local_addr_space.acc.put_unwind_info = put_unwind_info;
+ local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
+ local_addr_space.acc.access_mem = access_mem;
+ local_addr_space.acc.access_reg = access_reg;
+ local_addr_space.acc.access_fpreg = access_fpreg;
+ local_addr_space.acc.resume = aarch64_local_resume;
+ local_addr_space.acc.get_proc_name = get_static_proc_name;
+ local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
+ unw_flush_cache (&local_addr_space, 0, 0);
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/aarch64/Ginit_local.c b/src/pal/src/libunwind/src/aarch64/Ginit_local.c
new file mode 100644
index 0000000000..cd60ca840f
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Ginit_local.c
@@ -0,0 +1,78 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2011-2013 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "init.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+int
+unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
+{
+ return -UNW_EINVAL;
+}
+
+#else /* !UNW_REMOTE_ONLY */
+
+static int
+unw_init_local_common (unw_cursor_t *cursor, unw_context_t *uc, unsigned use_prev_instr)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->dwarf.as = unw_local_addr_space;
+ c->dwarf.as_arg = uc;
+
+ return common_init (c, use_prev_instr);
+}
+
+int
+unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
+{
+ return unw_init_local_common(cursor, uc, 1);
+}
+
+int
+unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
+{
+ if (!flag)
+ {
+ return unw_init_local_common(cursor, uc, 1);
+ }
+ else if (flag == UNW_INIT_SIGNAL_FRAME)
+ {
+ return unw_init_local_common(cursor, uc, 0);
+ }
+ else
+ {
+ return -UNW_EINVAL;
+ }
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/aarch64/Ginit_remote.c b/src/pal/src/libunwind/src/aarch64/Ginit_remote.c
new file mode 100644
index 0000000000..9b8ba5b89d
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Ginit_remote.c
@@ -0,0 +1,45 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "init.h"
+#include "unwind_i.h"
+
+int
+unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
+{
+#ifdef UNW_LOCAL_ONLY
+ return -UNW_EINVAL;
+#else /* !UNW_LOCAL_ONLY */
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->dwarf.as = as;
+ c->dwarf.as_arg = as_arg;
+ return common_init (c, 0);
+#endif /* !UNW_LOCAL_ONLY */
+}
diff --git a/src/pal/src/libunwind/src/aarch64/Gis_signal_frame.c b/src/pal/src/libunwind/src/aarch64/Gis_signal_frame.c
new file mode 100644
index 0000000000..67159d8396
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Gis_signal_frame.c
@@ -0,0 +1,64 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+ Copyright (C) 2013 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+/* The restorer stub will always have the form:
+
+ d2801168 movz x8, #0x8b
+ d4000001 svc #0x0
+*/
+
+int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+#ifdef __linux__
+ struct cursor *c = (struct cursor *) cursor;
+ unw_word_t w0, ip;
+ unw_addr_space_t as;
+ unw_accessors_t *a;
+ void *arg;
+ int ret;
+
+ as = c->dwarf.as;
+ a = unw_get_accessors_int (as);
+ arg = c->dwarf.as_arg;
+
+ ip = c->dwarf.ip;
+
+ ret = (*a->access_mem) (as, ip, &w0, 0, arg);
+ if (ret < 0)
+ return ret;
+
+ /* FIXME: distinguish 32bit insn vs 64bit registers. */
+ if (w0 != 0xd4000001d2801168)
+ return 0;
+
+ return 1;
+
+#else
+ return -UNW_ENOINFO;
+#endif
+}
diff --git a/src/pal/src/libunwind/src/aarch64/Greg_states_iterate.c b/src/pal/src/libunwind/src/aarch64/Greg_states_iterate.c
new file mode 100644
index 0000000000..a17dc1b561
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Greg_states_iterate.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+ unw_reg_states_callback cb, void *token)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
diff --git a/src/pal/src/libunwind/src/aarch64/Gregs.c b/src/pal/src/libunwind/src/aarch64/Gregs.c
new file mode 100644
index 0000000000..a884373445
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Gregs.c
@@ -0,0 +1,118 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+ Copyright (C) 2013 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+HIDDEN int
+tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
+ int write)
+{
+ dwarf_loc_t loc = DWARF_NULL_LOC;
+ unsigned int mask;
+
+ switch (reg)
+ {
+ case UNW_AARCH64_X0:
+ case UNW_AARCH64_X1:
+ case UNW_AARCH64_X2:
+ case UNW_AARCH64_X3:
+ mask = 1 << reg;
+ if (write)
+ {
+ c->dwarf.eh_args[reg] = *valp;
+ c->dwarf.eh_valid_mask |= mask;
+ return 0;
+ }
+ else if ((c->dwarf.eh_valid_mask & mask) != 0)
+ {
+ *valp = c->dwarf.eh_args[reg];
+ return 0;
+ }
+ else
+ loc = c->dwarf.loc[reg];
+ break;
+
+ case UNW_AARCH64_X30:
+ if (write)
+ c->dwarf.ip = *valp; /* update the IP cache */
+ case UNW_AARCH64_X4:
+ case UNW_AARCH64_X5:
+ case UNW_AARCH64_X6:
+ case UNW_AARCH64_X7:
+ case UNW_AARCH64_X8:
+ case UNW_AARCH64_X9:
+ case UNW_AARCH64_X10:
+ case UNW_AARCH64_X11:
+ case UNW_AARCH64_X12:
+ case UNW_AARCH64_X13:
+ case UNW_AARCH64_X14:
+ case UNW_AARCH64_X15:
+ case UNW_AARCH64_X16:
+ case UNW_AARCH64_X17:
+ case UNW_AARCH64_X18:
+ case UNW_AARCH64_X19:
+ case UNW_AARCH64_X20:
+ case UNW_AARCH64_X21:
+ case UNW_AARCH64_X22:
+ case UNW_AARCH64_X23:
+ case UNW_AARCH64_X24:
+ case UNW_AARCH64_X25:
+ case UNW_AARCH64_X26:
+ case UNW_AARCH64_X27:
+ case UNW_AARCH64_X28:
+ case UNW_AARCH64_X29:
+ case UNW_AARCH64_PC:
+ case UNW_AARCH64_PSTATE:
+ loc = c->dwarf.loc[reg];
+ break;
+
+ case UNW_AARCH64_SP:
+ if (write)
+ return -UNW_EREADONLYREG;
+ *valp = c->dwarf.cfa;
+ return 0;
+
+ default:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+ }
+
+ if (write)
+ return dwarf_put (&c->dwarf, loc, *valp);
+ else
+ return dwarf_get (&c->dwarf, loc, valp);
+}
+
+HIDDEN int
+tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
+ int write)
+{
+ dwarf_loc_t loc = c->dwarf.loc[reg];
+ if (write)
+ return dwarf_putfp (&c->dwarf, loc, *valp);
+ else
+ return dwarf_getfp (&c->dwarf, loc, valp);
+}
diff --git a/src/pal/src/libunwind/src/aarch64/Gresume.c b/src/pal/src/libunwind/src/aarch64/Gresume.c
new file mode 100644
index 0000000000..3d82739293
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Gresume.c
@@ -0,0 +1,198 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2011-2013 Linaro Limited
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "offsets.h"
+
+#ifndef UNW_REMOTE_ONLY
+
+HIDDEN inline int
+aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
+{
+#ifdef __linux__
+ struct cursor *c = (struct cursor *) cursor;
+ unw_tdep_context_t *uc = c->dwarf.as_arg;
+
+ if (c->sigcontext_format == AARCH64_SCF_NONE)
+ {
+ /* Since there are no signals involved here we restore EH and non scratch
+ registers only. */
+ unsigned long regs[24];
+ regs[0] = uc->uc_mcontext.regs[0];
+ regs[1] = uc->uc_mcontext.regs[1];
+ regs[2] = uc->uc_mcontext.regs[2];
+ regs[3] = uc->uc_mcontext.regs[3];
+ regs[4] = uc->uc_mcontext.regs[19];
+ regs[5] = uc->uc_mcontext.regs[20];
+ regs[6] = uc->uc_mcontext.regs[21];
+ regs[7] = uc->uc_mcontext.regs[22];
+ regs[8] = uc->uc_mcontext.regs[23];
+ regs[9] = uc->uc_mcontext.regs[24];
+ regs[10] = uc->uc_mcontext.regs[25];
+ regs[11] = uc->uc_mcontext.regs[26];
+ regs[12] = uc->uc_mcontext.regs[27];
+ regs[13] = uc->uc_mcontext.regs[28];
+ regs[14] = uc->uc_mcontext.regs[29]; /* FP */
+ regs[15] = uc->uc_mcontext.regs[30]; /* LR */
+ regs[16] = GET_FPCTX(uc)->vregs[8];
+ regs[17] = GET_FPCTX(uc)->vregs[9];
+ regs[18] = GET_FPCTX(uc)->vregs[10];
+ regs[19] = GET_FPCTX(uc)->vregs[11];
+ regs[20] = GET_FPCTX(uc)->vregs[12];
+ regs[21] = GET_FPCTX(uc)->vregs[13];
+ regs[22] = GET_FPCTX(uc)->vregs[14];
+ regs[23] = GET_FPCTX(uc)->vregs[15];
+ unsigned long sp = uc->uc_mcontext.sp;
+
+ struct regs_overlay {
+ char x[sizeof(regs)];
+ };
+
+ asm volatile (
+ "mov x4, %0\n"
+ "mov x5, %1\n"
+ "ldp x0, x1, [x4]\n"
+ "ldp x2, x3, [x4,16]\n"
+ "ldp x19, x20, [x4,32]\n"
+ "ldp x21, x22, [x4,48]\n"
+ "ldp x23, x24, [x4,64]\n"
+ "ldp x25, x26, [x4,80]\n"
+ "ldp x27, x28, [x4,96]\n"
+ "ldp x29, x30, [x4,112]\n"
+ "ldp d8, d9, [x4,128]\n"
+ "ldp d10, d11, [x4,144]\n"
+ "ldp d12, d13, [x4,160]\n"
+ "ldp d14, d15, [x4,176]\n"
+ "mov sp, x5\n"
+ "ret \n"
+ :
+ : "r" (regs),
+ "r" (sp),
+ "m" (*(struct regs_overlay *)regs)
+ );
+ }
+ else
+ {
+ struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
+
+ if (c->dwarf.eh_valid_mask & 0x1) sc->regs[0] = c->dwarf.eh_args[0];
+ if (c->dwarf.eh_valid_mask & 0x2) sc->regs[1] = c->dwarf.eh_args[1];
+ if (c->dwarf.eh_valid_mask & 0x4) sc->regs[2] = c->dwarf.eh_args[2];
+ if (c->dwarf.eh_valid_mask & 0x8) sc->regs[3] = c->dwarf.eh_args[3];
+
+ sc->regs[4] = uc->uc_mcontext.regs[4];
+ sc->regs[5] = uc->uc_mcontext.regs[5];
+ sc->regs[6] = uc->uc_mcontext.regs[6];
+ sc->regs[7] = uc->uc_mcontext.regs[7];
+ sc->regs[8] = uc->uc_mcontext.regs[8];
+ sc->regs[9] = uc->uc_mcontext.regs[9];
+ sc->regs[10] = uc->uc_mcontext.regs[10];
+ sc->regs[11] = uc->uc_mcontext.regs[11];
+ sc->regs[12] = uc->uc_mcontext.regs[12];
+ sc->regs[13] = uc->uc_mcontext.regs[13];
+ sc->regs[14] = uc->uc_mcontext.regs[14];
+ sc->regs[15] = uc->uc_mcontext.regs[15];
+ sc->regs[16] = uc->uc_mcontext.regs[16];
+ sc->regs[17] = uc->uc_mcontext.regs[17];
+ sc->regs[18] = uc->uc_mcontext.regs[18];
+ sc->regs[19] = uc->uc_mcontext.regs[19];
+ sc->regs[20] = uc->uc_mcontext.regs[20];
+ sc->regs[21] = uc->uc_mcontext.regs[21];
+ sc->regs[22] = uc->uc_mcontext.regs[22];
+ sc->regs[23] = uc->uc_mcontext.regs[23];
+ sc->regs[24] = uc->uc_mcontext.regs[24];
+ sc->regs[25] = uc->uc_mcontext.regs[25];
+ sc->regs[26] = uc->uc_mcontext.regs[26];
+ sc->regs[27] = uc->uc_mcontext.regs[27];
+ sc->regs[28] = uc->uc_mcontext.regs[28];
+ sc->regs[29] = uc->uc_mcontext.regs[29];
+ sc->regs[30] = uc->uc_mcontext.regs[30];
+ sc->sp = uc->uc_mcontext.sp;
+ sc->pc = uc->uc_mcontext.pc;
+ sc->pstate = uc->uc_mcontext.pstate;
+
+ asm volatile (
+ "mov sp, %0\n"
+ "ret %1\n"
+ : : "r" (c->sigcontext_sp), "r" (c->sigcontext_pc)
+ );
+ }
+ unreachable();
+#else
+ printf ("%s: implement me\n", __FUNCTION__);
+#endif
+ return -UNW_EINVAL;
+}
+
+#endif /* !UNW_REMOTE_ONLY */
+
+static inline void
+establish_machine_state (struct cursor *c)
+{
+ unw_addr_space_t as = c->dwarf.as;
+ void *arg = c->dwarf.as_arg;
+ unw_fpreg_t fpval;
+ unw_word_t val;
+ int reg;
+
+ Debug (8, "copying out cursor state\n");
+
+ for (reg = 0; reg <= UNW_AARCH64_V31; ++reg)
+ {
+ Debug (16, "copying %s %d\n", unw_regname (reg), reg);
+ if (unw_is_fpreg (reg))
+ {
+ if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0)
+ as->acc.access_fpreg (as, reg, &fpval, 1, arg);
+ }
+ else
+ {
+ if (tdep_access_reg (c, reg, &val, 0) >= 0)
+ as->acc.access_reg (as, reg, &val, 1, arg);
+ }
+ }
+}
+
+int
+unw_resume (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ if (!c->dwarf.ip)
+ {
+ /* This can happen easily when the frame-chain gets truncated
+ due to bad or missing unwind-info. */
+ Debug (1, "refusing to resume execution at address 0\n");
+ return -UNW_EINVAL;
+ }
+
+ establish_machine_state (c);
+
+ return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c,
+ c->dwarf.as_arg);
+}
diff --git a/src/pal/src/libunwind/src/aarch64/Gstash_frame.c b/src/pal/src/libunwind/src/aarch64/Gstash_frame.c
new file mode 100644
index 0000000000..6689af1a61
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Gstash_frame.c
@@ -0,0 +1,89 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
+ Copyright (C) 2014 CERN and Aalto University
+ Contributed by Filip Nyback
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+HIDDEN void
+tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs)
+{
+ struct cursor *c = (struct cursor *) dwarf_to_cursor (d);
+ unw_tdep_frame_t *f = &c->frame_info;
+
+ Debug (4, "ip=0x%lx cfa=0x%lx type %d cfa [where=%d val=%ld] cfaoff=%ld"
+ " ra=0x%lx fp [where=%d val=%ld @0x%lx] lr [where=%d val=%ld @0x%lx] "
+ "sp [where=%d val=%ld @0x%lx]\n",
+ d->ip, d->cfa, f->frame_type,
+ rs->reg.where[DWARF_CFA_REG_COLUMN],
+ rs->reg.val[DWARF_CFA_REG_COLUMN],
+ rs->reg.val[DWARF_CFA_OFF_COLUMN],
+ DWARF_GET_LOC(d->loc[rs->ret_addr_column]),
+ rs->reg.where[FP], rs->reg.val[FP], DWARF_GET_LOC(d->loc[FP]),
+ rs->reg.where[LR], rs->reg.val[LR], DWARF_GET_LOC(d->loc[LR]),
+ rs->reg.where[SP], rs->reg.val[SP], DWARF_GET_LOC(d->loc[SP]));
+
+ /* A standard frame is defined as:
+ - CFA is register-relative offset off FP or SP;
+ - Return address is saved in LR;
+ - FP is unsaved or saved at CFA+offset, offset != -1;
+ - LR is unsaved or saved at CFA+offset, offset != -1;
+ - SP is unsaved or saved at CFA+offset, offset != -1. */
+ if (f->frame_type == UNW_AARCH64_FRAME_OTHER
+ && (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG)
+ && (rs->reg.val[DWARF_CFA_REG_COLUMN] == FP
+ || rs->reg.val[DWARF_CFA_REG_COLUMN] == SP)
+ && labs(rs->reg.val[DWARF_CFA_OFF_COLUMN]) < (1 << 29)
+ && rs->ret_addr_column == LR
+ && (rs->reg.where[FP] == DWARF_WHERE_UNDEF
+ || rs->reg.where[FP] == DWARF_WHERE_SAME
+ || (rs->reg.where[FP] == DWARF_WHERE_CFAREL
+ && labs(rs->reg.val[FP]) < (1 << 29)
+ && rs->reg.val[FP]+1 != 0))
+ && (rs->reg.where[LR] == DWARF_WHERE_UNDEF
+ || rs->reg.where[LR] == DWARF_WHERE_SAME
+ || (rs->reg.where[LR] == DWARF_WHERE_CFAREL
+ && labs(rs->reg.val[LR]) < (1 << 29)
+ && rs->reg.val[LR]+1 != 0))
+ && (rs->reg.where[SP] == DWARF_WHERE_UNDEF
+ || rs->reg.where[SP] == DWARF_WHERE_SAME
+ || (rs->reg.where[SP] == DWARF_WHERE_CFAREL
+ && labs(rs->reg.val[SP]) < (1 << 29)
+ && rs->reg.val[SP]+1 != 0)))
+ {
+ /* Save information for a standard frame. */
+ f->frame_type = UNW_AARCH64_FRAME_STANDARD;
+ f->cfa_reg_sp = (rs->reg.val[DWARF_CFA_REG_COLUMN] == SP);
+ f->cfa_reg_offset = rs->reg.val[DWARF_CFA_OFF_COLUMN];
+ if (rs->reg.where[FP] == DWARF_WHERE_CFAREL)
+ f->fp_cfa_offset = rs->reg.val[FP];
+ if (rs->reg.where[LR] == DWARF_WHERE_CFAREL)
+ f->lr_cfa_offset = rs->reg.val[LR];
+ if (rs->reg.where[SP] == DWARF_WHERE_CFAREL)
+ f->sp_cfa_offset = rs->reg.val[SP];
+ Debug (4, " standard frame\n");
+ }
+ else
+ Debug (4, " unusual frame\n");
+}
diff --git a/src/pal/src/libunwind/src/aarch64/Gstep.c b/src/pal/src/libunwind/src/aarch64/Gstep.c
new file mode 100644
index 0000000000..fdf64a73f3
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Gstep.c
@@ -0,0 +1,189 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2011-2013 Linaro Limited
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "offsets.h"
+
+/* Recognise PLT entries such as:
+ 40ddf0: b0000570 adrp x16, 4ba000 <_GLOBAL_OFFSET_TABLE_+0x2a8>
+ 40ddf4: f9433611 ldr x17, [x16,#1640]
+ 40ddf8: 9119a210 add x16, x16, #0x668
+ 40ddfc: d61f0220 br x17 */
+static int
+is_plt_entry (struct dwarf_cursor *c)
+{
+ unw_word_t w0, w1;
+ unw_accessors_t *a;
+ int ret;
+
+ a = unw_get_accessors_int (c->as);
+ if ((ret = (*a->access_mem) (c->as, c->ip, &w0, 0, c->as_arg)) < 0
+ || (ret = (*a->access_mem) (c->as, c->ip + 8, &w1, 0, c->as_arg)) < 0)
+ return 0;
+
+ ret = (((w0 & 0xff0000009f000000) == 0xf900000090000000)
+ && ((w1 & 0xffffffffff000000) == 0xd61f022091000000));
+
+ Debug (14, "ip=0x%lx => 0x%016lx 0x%016lx, ret = %d\n", c->ip, w0, w1, ret);
+ return ret;
+}
+
+static int
+aarch64_handle_signal_frame (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+ unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa;
+ struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0);
+
+ if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0)
+ return -UNW_EUNSPEC;
+
+ ret = unw_is_signal_frame (cursor);
+ Debug(1, "unw_is_signal_frame()=%d\n", ret);
+
+ /* Save the SP and PC to be able to return execution at this point
+ later in time (unw_resume). */
+ c->sigcontext_sp = c->dwarf.cfa;
+ c->sigcontext_pc = c->dwarf.ip;
+
+ if (ret)
+ {
+ c->sigcontext_format = AARCH64_SCF_LINUX_RT_SIGFRAME;
+ sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF;
+ }
+ else
+ return -UNW_EUNSPEC;
+
+ c->sigcontext_addr = sc_addr;
+ c->frame_info.frame_type = UNW_AARCH64_FRAME_SIGRETURN;
+ c->frame_info.cfa_reg_offset = sc_addr - sp_addr;
+
+ /* Update the dwarf cursor.
+ Set the location of the registers to the corresponding addresses of the
+ uc_mcontext / sigcontext structure contents. */
+ c->dwarf.loc[UNW_AARCH64_X0] = DWARF_LOC (sc_addr + LINUX_SC_X0_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X1] = DWARF_LOC (sc_addr + LINUX_SC_X1_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X2] = DWARF_LOC (sc_addr + LINUX_SC_X2_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X3] = DWARF_LOC (sc_addr + LINUX_SC_X3_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X4] = DWARF_LOC (sc_addr + LINUX_SC_X4_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X5] = DWARF_LOC (sc_addr + LINUX_SC_X5_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X6] = DWARF_LOC (sc_addr + LINUX_SC_X6_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X7] = DWARF_LOC (sc_addr + LINUX_SC_X7_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X8] = DWARF_LOC (sc_addr + LINUX_SC_X8_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X9] = DWARF_LOC (sc_addr + LINUX_SC_X9_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X10] = DWARF_LOC (sc_addr + LINUX_SC_X10_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X11] = DWARF_LOC (sc_addr + LINUX_SC_X11_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X12] = DWARF_LOC (sc_addr + LINUX_SC_X12_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X13] = DWARF_LOC (sc_addr + LINUX_SC_X13_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X14] = DWARF_LOC (sc_addr + LINUX_SC_X14_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X15] = DWARF_LOC (sc_addr + LINUX_SC_X15_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X16] = DWARF_LOC (sc_addr + LINUX_SC_X16_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X17] = DWARF_LOC (sc_addr + LINUX_SC_X17_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X18] = DWARF_LOC (sc_addr + LINUX_SC_X18_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X19] = DWARF_LOC (sc_addr + LINUX_SC_X19_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X20] = DWARF_LOC (sc_addr + LINUX_SC_X20_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X21] = DWARF_LOC (sc_addr + LINUX_SC_X21_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X22] = DWARF_LOC (sc_addr + LINUX_SC_X22_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X23] = DWARF_LOC (sc_addr + LINUX_SC_X23_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X24] = DWARF_LOC (sc_addr + LINUX_SC_X24_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X25] = DWARF_LOC (sc_addr + LINUX_SC_X25_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X26] = DWARF_LOC (sc_addr + LINUX_SC_X26_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X27] = DWARF_LOC (sc_addr + LINUX_SC_X27_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X28] = DWARF_LOC (sc_addr + LINUX_SC_X28_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X29] = DWARF_LOC (sc_addr + LINUX_SC_X29_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_X30] = DWARF_LOC (sc_addr + LINUX_SC_X30_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_SP] = DWARF_LOC (sc_addr + LINUX_SC_SP_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0);
+ c->dwarf.loc[UNW_AARCH64_PSTATE] = DWARF_LOC (sc_addr + LINUX_SC_PSTATE_OFF, 0);
+
+ /* Set SP/CFA and PC/IP. */
+ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_SP], &c->dwarf.cfa);
+ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip);
+
+ c->dwarf.pi_valid = 0;
+ c->dwarf.use_prev_instr = 0;
+
+ return 1;
+}
+
+int
+unw_step (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx))\n",
+ c, c->dwarf.ip, c->dwarf.cfa);
+
+ /* Check if this is a signal frame. */
+ if (unw_is_signal_frame (cursor) > 0)
+ return aarch64_handle_signal_frame (cursor);
+
+ ret = dwarf_step (&c->dwarf);
+ Debug(1, "dwarf_step()=%d\n", ret);
+
+ if (unlikely (ret == -UNW_ESTOPUNWIND))
+ return ret;
+
+ if (unlikely (ret < 0))
+ {
+ /* DWARF failed. */
+ if (is_plt_entry (&c->dwarf))
+ {
+ Debug (2, "found plt entry\n");
+ c->frame_info.frame_type = UNW_AARCH64_FRAME_STANDARD;
+ }
+ else
+ {
+ Debug (2, "fallback\n");
+ c->frame_info.frame_type = UNW_AARCH64_FRAME_GUESSED;
+ }
+ /* Use link register (X30). */
+ c->frame_info.cfa_reg_offset = 0;
+ c->frame_info.cfa_reg_sp = 0;
+ c->frame_info.fp_cfa_offset = -1;
+ c->frame_info.lr_cfa_offset = -1;
+ c->frame_info.sp_cfa_offset = -1;
+ c->dwarf.loc[UNW_AARCH64_PC] = c->dwarf.loc[UNW_AARCH64_X30];
+ c->dwarf.loc[UNW_AARCH64_X30] = DWARF_NULL_LOC;
+ if (!DWARF_IS_NULL_LOC (c->dwarf.loc[UNW_AARCH64_PC]))
+ {
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip);
+ if (ret < 0)
+ {
+ Debug (2, "failed to get pc from link register: %d\n", ret);
+ return ret;
+ }
+ Debug (2, "link register (x30) = 0x%016lx\n", c->dwarf.ip);
+ ret = 1;
+ }
+ else
+ c->dwarf.ip = 0;
+ }
+
+ return (c->dwarf.ip == 0) ? 0 : 1;
+}
diff --git a/src/pal/src/libunwind/src/aarch64/Gtrace.c b/src/pal/src/libunwind/src/aarch64/Gtrace.c
new file mode 100644
index 0000000000..c67faf0e35
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Gtrace.c
@@ -0,0 +1,548 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
+ Copyright (C) 2014 CERN and Aalto University
+ Contributed by Filip Nyback
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "offsets.h"
+#include <signal.h>
+#include <limits.h>
+
+#pragma weak pthread_once
+#pragma weak pthread_key_create
+#pragma weak pthread_getspecific
+#pragma weak pthread_setspecific
+
+/* Initial hash table size. Table expands by 2 bits (times four). */
+#define HASH_MIN_BITS 14
+
+typedef struct
+{
+ unw_tdep_frame_t *frames;
+ size_t log_size;
+ size_t used;
+ size_t dtor_count; /* Counts how many times our destructor has already
+ been called. */
+} unw_trace_cache_t;
+
+static const unw_tdep_frame_t empty_frame = { 0, UNW_AARCH64_FRAME_OTHER, -1, -1, 0, -1, -1, -1 };
+static define_lock (trace_init_lock);
+static pthread_once_t trace_cache_once = PTHREAD_ONCE_INIT;
+static sig_atomic_t trace_cache_once_happen;
+static pthread_key_t trace_cache_key;
+static struct mempool trace_cache_pool;
+static __thread unw_trace_cache_t *tls_cache;
+static __thread int tls_cache_destroyed;
+
+/* Free memory for a thread's trace cache. */
+static void
+trace_cache_free (void *arg)
+{
+ unw_trace_cache_t *cache = arg;
+ if (++cache->dtor_count < PTHREAD_DESTRUCTOR_ITERATIONS)
+ {
+ /* Not yet our turn to get destroyed. Re-install ourselves into the key. */
+ pthread_setspecific(trace_cache_key, cache);
+ Debug(5, "delayed freeing cache %p (%zx to go)\n", cache,
+ PTHREAD_DESTRUCTOR_ITERATIONS - cache->dtor_count);
+ return;
+ }
+ tls_cache_destroyed = 1;
+ tls_cache = NULL;
+ munmap (cache->frames, (1u << cache->log_size) * sizeof(unw_tdep_frame_t));
+ mempool_free (&trace_cache_pool, cache);
+ Debug(5, "freed cache %p\n", cache);
+}
+
+/* Initialise frame tracing for threaded use. */
+static void
+trace_cache_init_once (void)
+{
+ pthread_key_create (&trace_cache_key, &trace_cache_free);
+ mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0);
+ trace_cache_once_happen = 1;
+}
+
+static unw_tdep_frame_t *
+trace_cache_buckets (size_t n)
+{
+ unw_tdep_frame_t *frames;
+ size_t i;
+
+ GET_MEMORY(frames, n * sizeof (unw_tdep_frame_t));
+ if (likely(frames != NULL))
+ for (i = 0; i < n; ++i)
+ frames[i] = empty_frame;
+
+ return frames;
+}
+
+/* Allocate and initialise hash table for frame cache lookups.
+ Returns the cache initialised with (1u << HASH_LOW_BITS) hash
+ buckets, or NULL if there was a memory allocation problem. */
+static unw_trace_cache_t *
+trace_cache_create (void)
+{
+ unw_trace_cache_t *cache;
+
+ if (tls_cache_destroyed)
+ {
+ /* The current thread is in the process of exiting. Don't recreate
+ cache, as we wouldn't have another chance to free it. */
+ Debug(5, "refusing to reallocate cache: "
+ "thread-locals are being deallocated\n");
+ return NULL;
+ }
+
+ if (! (cache = mempool_alloc(&trace_cache_pool)))
+ {
+ Debug(5, "failed to allocate cache\n");
+ return NULL;
+ }
+
+ if (! (cache->frames = trace_cache_buckets(1u << HASH_MIN_BITS)))
+ {
+ Debug(5, "failed to allocate buckets\n");
+ mempool_free(&trace_cache_pool, cache);
+ return NULL;
+ }
+
+ cache->log_size = HASH_MIN_BITS;
+ cache->used = 0;
+ cache->dtor_count = 0;
+ tls_cache_destroyed = 0; /* Paranoia: should already be 0. */
+ Debug(5, "allocated cache %p\n", cache);
+ return cache;
+}
+
+/* Expand the hash table in the frame cache if possible. This always
+ quadruples the hash size, and clears all previous frame entries. */
+static int
+trace_cache_expand (unw_trace_cache_t *cache)
+{
+ size_t old_size = (1u << cache->log_size);
+ size_t new_log_size = cache->log_size + 2;
+ unw_tdep_frame_t *new_frames = trace_cache_buckets (1u << new_log_size);
+
+ if (unlikely(! new_frames))
+ {
+ Debug(5, "failed to expand cache to 2^%lu buckets\n", new_log_size);
+ return -UNW_ENOMEM;
+ }
+
+ Debug(5, "expanded cache from 2^%lu to 2^%lu buckets\n", cache->log_size, new_log_size);
+ munmap(cache->frames, old_size * sizeof(unw_tdep_frame_t));
+ cache->frames = new_frames;
+ cache->log_size = new_log_size;
+ cache->used = 0;
+ return 0;
+}
+
+static unw_trace_cache_t *
+trace_cache_get_unthreaded (void)
+{
+ unw_trace_cache_t *cache;
+ intrmask_t saved_mask;
+ static unw_trace_cache_t *global_cache = NULL;
+ lock_acquire (&trace_init_lock, saved_mask);
+ if (! global_cache)
+ {
+ mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0);
+ global_cache = trace_cache_create ();
+ }
+ cache = global_cache;
+ lock_release (&trace_init_lock, saved_mask);
+ Debug(5, "using cache %p\n", cache);
+ return cache;
+}
+
+/* Get the frame cache for the current thread. Create it if there is none. */
+static unw_trace_cache_t *
+trace_cache_get (void)
+{
+ unw_trace_cache_t *cache;
+ if (likely (pthread_once != NULL))
+ {
+ pthread_once(&trace_cache_once, &trace_cache_init_once);
+ if (!trace_cache_once_happen)
+ {
+ return trace_cache_get_unthreaded();
+ }
+ if (! (cache = tls_cache))
+ {
+ cache = trace_cache_create();
+ pthread_setspecific(trace_cache_key, cache);
+ tls_cache = cache;
+ }
+ Debug(5, "using cache %p\n", cache);
+ return cache;
+ }
+ else
+ {
+ return trace_cache_get_unthreaded();
+ }
+}
+
+/* Initialise frame properties for address cache slot F at address
+ PC using current CFA, FP and SP values. Modifies CURSOR to
+ that location, performs one unw_step(), and fills F with what
+ was discovered about the location. Returns F.
+
+ FIXME: This probably should tell DWARF handling to never evaluate
+ or use registers other than FP, SP and PC in case there is
+ highly unusual unwind info which uses these creatively. */
+static unw_tdep_frame_t *
+trace_init_addr (unw_tdep_frame_t *f,
+ unw_cursor_t *cursor,
+ unw_word_t cfa,
+ unw_word_t pc,
+ unw_word_t fp,
+ unw_word_t sp)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ struct dwarf_cursor *d = &c->dwarf;
+ int ret = -UNW_EINVAL;
+
+ /* Initialise frame properties: unknown, not last. */
+ f->virtual_address = pc;
+ f->frame_type = UNW_AARCH64_FRAME_OTHER;
+ f->last_frame = 0;
+ f->cfa_reg_sp = -1;
+ f->cfa_reg_offset = 0;
+ f->fp_cfa_offset = -1;
+ f->lr_cfa_offset = -1;
+ f->sp_cfa_offset = -1;
+
+ /* Reinitialise cursor to this instruction - but undo next/prev PC
+ adjustment because unw_step will redo it - and force PC, FP and
+ SP into register locations (=~ ucontext we keep), then set
+ their desired values. Then perform the step. */
+ d->ip = pc + d->use_prev_instr;
+ d->cfa = cfa;
+ d->loc[UNW_AARCH64_X29] = DWARF_REG_LOC (d, UNW_AARCH64_X29);
+ d->loc[UNW_AARCH64_SP] = DWARF_REG_LOC (d, UNW_AARCH64_SP);
+ d->loc[UNW_AARCH64_PC] = DWARF_REG_LOC (d, UNW_AARCH64_PC);
+ c->frame_info = *f;
+
+ if (likely(dwarf_put (d, d->loc[UNW_AARCH64_X29], fp) >= 0)
+ && likely(dwarf_put (d, d->loc[UNW_AARCH64_SP], sp) >= 0)
+ && likely(dwarf_put (d, d->loc[UNW_AARCH64_PC], pc) >= 0)
+ && likely((ret = unw_step (cursor)) >= 0))
+ *f = c->frame_info;
+
+ /* If unw_step() stopped voluntarily, remember that, even if it
+ otherwise could not determine anything useful. This avoids
+ failing trace if we hit frames without unwind info, which is
+ common for the outermost frame (CRT stuff) on many systems.
+ This avoids failing trace in very common circumstances; failing
+ to unw_step() loop wouldn't produce any better result. */
+ if (ret == 0)
+ f->last_frame = -1;
+
+ Debug (3, "frame va %lx type %d last %d cfa %s+%d fp @ cfa%+d lr @ cfa%+d sp @ cfa%+d\n",
+ f->virtual_address, f->frame_type, f->last_frame,
+ f->cfa_reg_sp ? "sp" : "fp", f->cfa_reg_offset,
+ f->fp_cfa_offset, f->lr_cfa_offset, f->sp_cfa_offset);
+
+ return f;
+}
+
+/* Look up and if necessary fill in frame attributes for address PC
+ in CACHE using current CFA, FP and SP values. Uses CURSOR to
+ perform any unwind steps necessary to fill the cache. Returns the
+ frame cache slot which describes RIP. */
+static unw_tdep_frame_t *
+trace_lookup (unw_cursor_t *cursor,
+ unw_trace_cache_t *cache,
+ unw_word_t cfa,
+ unw_word_t pc,
+ unw_word_t fp,
+ unw_word_t sp)
+{
+ /* First look up for previously cached information using cache as
+ linear probing hash table with probe step of 1. Majority of
+ lookups should be completed within few steps, but it is very
+ important the hash table does not fill up, or performance falls
+ off the cliff. */
+ uint64_t i, addr;
+ uint64_t cache_size = 1u << cache->log_size;
+ uint64_t slot = ((pc * 0x9e3779b97f4a7c16) >> 43) & (cache_size-1);
+ unw_tdep_frame_t *frame;
+
+ for (i = 0; i < 16; ++i)
+ {
+ frame = &cache->frames[slot];
+ addr = frame->virtual_address;
+
+ /* Return if we found the address. */
+ if (likely(addr == pc))
+ {
+ Debug (4, "found address after %ld steps\n", i);
+ return frame;
+ }
+
+ /* If slot is empty, reuse it. */
+ if (likely(! addr))
+ break;
+
+ /* Linear probe to next slot candidate, step = 1. */
+ if (++slot >= cache_size)
+ slot -= cache_size;
+ }
+
+ /* If we collided after 16 steps, or if the hash is more than half
+ full, force the hash to expand. Fill the selected slot, whether
+ it's free or collides. Note that hash expansion drops previous
+ contents; further lookups will refill the hash. */
+ Debug (4, "updating slot %lu after %ld steps, replacing 0x%lx\n", slot, i, addr);
+ if (unlikely(addr || cache->used >= cache_size / 2))
+ {
+ if (unlikely(trace_cache_expand (cache) < 0))
+ return NULL;
+
+ cache_size = 1u << cache->log_size;
+ slot = ((pc * 0x9e3779b97f4a7c16) >> 43) & (cache_size-1);
+ frame = &cache->frames[slot];
+ addr = frame->virtual_address;
+ }
+
+ if (! addr)
+ ++cache->used;
+
+ return trace_init_addr (frame, cursor, cfa, pc, fp, sp);
+}
+
+/* Fast stack backtrace for AArch64.
+
+ This is used by backtrace() implementation to accelerate frequent
+ queries for current stack, without any desire to unwind. It fills
+ BUFFER with the call tree from CURSOR upwards for at most SIZE
+ stack levels. The first frame, backtrace itself, is omitted. When
+ called, SIZE should give the maximum number of entries that can be
+ stored into BUFFER. Uses an internal thread-specific cache to
+ accelerate queries.
+
+ The caller should fall back to a unw_step() loop if this function
+ fails by returning -UNW_ESTOPUNWIND, meaning the routine hit a
+ stack frame that is too complex to be traced in the fast path.
+
+ This function is tuned for clients which only need to walk the
+ stack to get the call tree as fast as possible but without any
+ other details, for example profilers sampling the stack thousands
+ to millions of times per second. The routine handles the most
+ common AArch64 ABI stack layouts: CFA is FP or SP plus/minus
+ constant offset, return address is in LR, and FP, LR and SP are
+ either unchanged or saved on stack at constant offset from the CFA;
+ the signal return frame; and frames without unwind info provided
+ they are at the outermost (final) frame or can conservatively be
+ assumed to be frame-pointer based.
+
+ Any other stack layout will cause the routine to give up. There
+ are only a handful of relatively rarely used functions which do
+ not have a stack in the standard form: vfork, longjmp, setcontext
+ and _dl_runtime_profile on common linux systems for example.
+
+ On success BUFFER and *SIZE reflect the trace progress up to *SIZE
+ stack levels or the outermost frame, which ever is less. It may
+ stop short of outermost frame if unw_step() loop would also do so,
+ e.g. if there is no more unwind information; this is not reported
+ as an error.
+
+ The function returns a negative value for errors, -UNW_ESTOPUNWIND
+ if tracing stopped because of an unusual frame unwind info. The
+ BUFFER and *SIZE reflect tracing progress up to the error frame.
+
+ Callers of this function would normally look like this:
+
+ unw_cursor_t cur;
+ unw_context_t ctx;
+ void addrs[128];
+ int depth = 128;
+ int ret;
+
+ unw_getcontext(&ctx);
+ unw_init_local(&cur, &ctx);
+ if ((ret = unw_tdep_trace(&cur, addrs, &depth)) < 0)
+ {
+ depth = 0;
+ unw_getcontext(&ctx);
+ unw_init_local(&cur, &ctx);
+ while ((ret = unw_step(&cur)) > 0 && depth < 128)
+ {
+ unw_word_t ip;
+ unw_get_reg(&cur, UNW_REG_IP, &ip);
+ addresses[depth++] = (void *) ip;
+ }
+ }
+*/
+HIDDEN int
+tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ struct dwarf_cursor *d = &c->dwarf;
+ unw_trace_cache_t *cache;
+ unw_word_t fp, sp, pc, cfa, lr;
+ int maxdepth = 0;
+ int depth = 0;
+ int ret;
+
+ /* Check input parametres. */
+ if (unlikely(! cursor || ! buffer || ! size || (maxdepth = *size) <= 0))
+ return -UNW_EINVAL;
+
+ Debug (1, "begin ip 0x%lx cfa 0x%lx\n", d->ip, d->cfa);
+
+ /* Tell core dwarf routines to call back to us. */
+ d->stash_frames = 1;
+
+ /* Determine initial register values. These are direct access safe
+ because we know they come from the initial machine context. */
+ pc = d->ip;
+ sp = cfa = d->cfa;
+ ACCESS_MEM_FAST(ret, 0, d, DWARF_GET_LOC(d->loc[UNW_AARCH64_X29]), fp);
+ assert(ret == 0);
+ lr = 0;
+
+ /* Get frame cache. */
+ if (unlikely(! (cache = trace_cache_get())))
+ {
+ Debug (1, "returning %d, cannot get trace cache\n", -UNW_ENOMEM);
+ *size = 0;
+ d->stash_frames = 0;
+ return -UNW_ENOMEM;
+ }
+
+ /* Trace the stack upwards, starting from current RIP. Adjust
+ the RIP address for previous/next instruction as the main
+ unwinding logic would also do. We undo this before calling
+ back into unw_step(). */
+ while (depth < maxdepth)
+ {
+ pc -= d->use_prev_instr;
+ Debug (2, "depth %d cfa 0x%lx pc 0x%lx sp 0x%lx fp 0x%lx\n",
+ depth, cfa, pc, sp, fp);
+
+ /* See if we have this address cached. If not, evaluate enough of
+ the dwarf unwind information to fill the cache line data, or to
+ decide this frame cannot be handled in fast trace mode. We
+ cache negative results too to prevent unnecessary dwarf parsing
+ for common failures. */
+ unw_tdep_frame_t *f = trace_lookup (cursor, cache, cfa, pc, fp, sp);
+
+ /* If we don't have information for this frame, give up. */
+ if (unlikely(! f))
+ {
+ ret = -UNW_ENOINFO;
+ break;
+ }
+
+ Debug (3, "frame va %lx type %d last %d cfa %s+%d fp @ cfa%+d lr @ cfa%+d sp @ cfa%+d\n",
+ f->virtual_address, f->frame_type, f->last_frame,
+ f->cfa_reg_sp ? "sp" : "fp", f->cfa_reg_offset,
+ f->fp_cfa_offset, f->lr_cfa_offset, f->sp_cfa_offset);
+
+ assert (f->virtual_address == pc);
+
+ /* Stop if this was the last frame. In particular don't evaluate
+ new register values as it may not be safe - we don't normally
+ run with full validation on, and do not want to - and there's
+ enough bad unwind info floating around that we need to trust
+ what unw_step() previously said, in potentially bogus frames. */
+ if (f->last_frame)
+ break;
+
+ /* Evaluate CFA and registers for the next frame. */
+ switch (f->frame_type)
+ {
+ case UNW_AARCH64_FRAME_GUESSED:
+ /* Fall thru to standard processing after forcing validation. */
+ c->validate = 1;
+
+ case UNW_AARCH64_FRAME_STANDARD:
+ /* Advance standard traceable frame. */
+ cfa = (f->cfa_reg_sp ? sp : fp) + f->cfa_reg_offset;
+ if (likely(f->lr_cfa_offset != -1))
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->lr_cfa_offset, pc);
+ else if (lr != 0)
+ {
+ /* Use the saved link register as the new pc. */
+ pc = lr;
+ lr = 0;
+ }
+ if (likely(ret >= 0) && likely(f->fp_cfa_offset != -1))
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->fp_cfa_offset, fp);
+
+ /* Don't bother reading SP from DWARF, CFA becomes new SP. */
+ sp = cfa;
+
+ /* Next frame needs to back up for unwind info lookup. */
+ d->use_prev_instr = 1;
+ break;
+
+ case UNW_AARCH64_FRAME_SIGRETURN:
+ cfa = cfa + f->cfa_reg_offset; /* cfa now points to ucontext_t. */
+
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_PC_OFF, pc);
+ if (likely(ret >= 0))
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_X29_OFF, fp);
+ if (likely(ret >= 0))
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_SP_OFF, sp);
+ /* Save the link register here in case we end up in a function that
+ doesn't save the link register in the prologue, e.g. kill. */
+ if (likely(ret >= 0))
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_X30_OFF, lr);
+
+ /* Resume stack at signal restoration point. The stack is not
+ necessarily continuous here, especially with sigaltstack(). */
+ cfa = sp;
+
+ /* Next frame should not back up. */
+ d->use_prev_instr = 0;
+ break;
+
+ default:
+ /* We cannot trace through this frame, give up and tell the
+ caller we had to stop. Data collected so far may still be
+ useful to the caller, so let it know how far we got. */
+ ret = -UNW_ESTOPUNWIND;
+ break;
+ }
+
+ Debug (4, "new cfa 0x%lx pc 0x%lx sp 0x%lx fp 0x%lx\n",
+ cfa, pc, sp, fp);
+
+ /* If we failed or ended up somewhere bogus, stop. */
+ if (unlikely(ret < 0 || pc < 0x4000))
+ break;
+
+ /* Record this address in stack trace. We skipped the first address. */
+ buffer[depth++] = (void *) (pc - d->use_prev_instr);
+ }
+
+#if UNW_DEBUG
+ Debug (1, "returning %d, depth %d\n", ret, depth);
+#endif
+ *size = depth;
+ return ret;
+}
diff --git a/src/pal/src/libunwind/src/aarch64/Lapply_reg_state.c b/src/pal/src/libunwind/src/aarch64/Lapply_reg_state.c
new file mode 100644
index 0000000000..7ebada480e
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Lapply_reg_state.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/pal/src/libunwind/src/aarch64/Lcreate_addr_space.c b/src/pal/src/libunwind/src/aarch64/Lcreate_addr_space.c
new file mode 100644
index 0000000000..0f2dc6be90
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Lcreate_addr_space.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gcreate_addr_space.c"
+#endif
diff --git a/src/pal/src/libunwind/src/aarch64/Lget_proc_info.c b/src/pal/src/libunwind/src/aarch64/Lget_proc_info.c
new file mode 100644
index 0000000000..69028b019f
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Lget_proc_info.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_proc_info.c"
+#endif
diff --git a/src/pal/src/libunwind/src/aarch64/Lget_save_loc.c b/src/pal/src/libunwind/src/aarch64/Lget_save_loc.c
new file mode 100644
index 0000000000..9ea048a907
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Lget_save_loc.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_save_loc.c"
+#endif
diff --git a/src/pal/src/libunwind/src/aarch64/Lglobal.c b/src/pal/src/libunwind/src/aarch64/Lglobal.c
new file mode 100644
index 0000000000..6d7b489e14
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Lglobal.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gglobal.c"
+#endif
diff --git a/src/pal/src/libunwind/src/aarch64/Linit.c b/src/pal/src/libunwind/src/aarch64/Linit.c
new file mode 100644
index 0000000000..e9abfdd46a
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Linit.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit.c"
+#endif
diff --git a/src/pal/src/libunwind/src/aarch64/Linit_local.c b/src/pal/src/libunwind/src/aarch64/Linit_local.c
new file mode 100644
index 0000000000..68a1687e85
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Linit_local.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_local.c"
+#endif
diff --git a/src/pal/src/libunwind/src/aarch64/Linit_remote.c b/src/pal/src/libunwind/src/aarch64/Linit_remote.c
new file mode 100644
index 0000000000..58cb04ab7c
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Linit_remote.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_remote.c"
+#endif
diff --git a/src/pal/src/libunwind/src/aarch64/Lis_signal_frame.c b/src/pal/src/libunwind/src/aarch64/Lis_signal_frame.c
new file mode 100644
index 0000000000..b9a7c4f51a
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Lis_signal_frame.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gis_signal_frame.c"
+#endif
diff --git a/src/pal/src/libunwind/src/aarch64/Lreg_states_iterate.c b/src/pal/src/libunwind/src/aarch64/Lreg_states_iterate.c
new file mode 100644
index 0000000000..f1eb1e79dc
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Lreg_states_iterate.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
diff --git a/src/pal/src/libunwind/src/aarch64/Lregs.c b/src/pal/src/libunwind/src/aarch64/Lregs.c
new file mode 100644
index 0000000000..2c9c75cd7d
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Lregs.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gregs.c"
+#endif
diff --git a/src/pal/src/libunwind/src/aarch64/Lresume.c b/src/pal/src/libunwind/src/aarch64/Lresume.c
new file mode 100644
index 0000000000..41a8cf003d
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Lresume.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gresume.c"
+#endif
diff --git a/src/pal/src/libunwind/src/aarch64/Lstash_frame.c b/src/pal/src/libunwind/src/aarch64/Lstash_frame.c
new file mode 100644
index 0000000000..77587803d0
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Lstash_frame.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gstash_frame.c"
+#endif
diff --git a/src/pal/src/libunwind/src/aarch64/Lstep.c b/src/pal/src/libunwind/src/aarch64/Lstep.c
new file mode 100644
index 0000000000..c1ac3c7547
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Lstep.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gstep.c"
+#endif
diff --git a/src/pal/src/libunwind/src/aarch64/Ltrace.c b/src/pal/src/libunwind/src/aarch64/Ltrace.c
new file mode 100644
index 0000000000..fcd3f239c9
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/Ltrace.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gtrace.c"
+#endif
diff --git a/src/pal/src/libunwind/src/aarch64/gen-offsets.c b/src/pal/src/libunwind/src/aarch64/gen-offsets.c
new file mode 100644
index 0000000000..eadc2377d8
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/gen-offsets.c
@@ -0,0 +1,68 @@
+#include <stdio.h>
+#include <stddef.h>
+#include <ucontext.h>
+#include <asm/sigcontext.h>
+
+#define UC(N,X) \
+ printf ("#define LINUX_UC_" N "_OFF\t0x%X\n", offsetof (ucontext_t, X))
+
+#define SC(N,X) \
+ printf ("#define LINUX_SC_" N "_OFF\t0x%X\n", offsetof (struct sigcontext, X))
+
+int
+main (void)
+{
+ printf (
+"/* Linux-specific definitions: */\n\n"
+
+"/* Define various structure offsets to simplify cross-compilation. */\n\n"
+
+"/* Offsets for AArch64 Linux \"ucontext_t\": */\n\n");
+
+ UC ("FLAGS", uc_flags);
+ UC ("LINK", uc_link);
+ UC ("STACK", uc_stack);
+ UC ("MCONTEXT", uc_mcontext);
+ UC ("SIGMASK", uc_sigmask);
+
+ printf ("\n/* Offsets for AArch64 Linux \"struct sigcontext\": */\n\n");
+
+ SC ("R0", regs[0]);
+ SC ("R1", regs[1]);
+ SC ("R2", regs[2]);
+ SC ("R3", regs[3]);
+ SC ("R4", regs[4]);
+ SC ("R5", regs[5]);
+ SC ("R6", regs[6]);
+ SC ("R7", regs[7]);
+ SC ("R8", regs[8]);
+ SC ("R9", regs[9]);
+ SC ("R10", regs[10]);
+ SC ("R11", regs[11]);
+ SC ("R12", regs[12]);
+ SC ("R13", regs[13]);
+ SC ("R14", regs[14]);
+ SC ("R15", regs[15]);
+ SC ("R16", regs[16]);
+ SC ("R17", regs[17]);
+ SC ("R18", regs[18]);
+ SC ("R19", regs[19]);
+ SC ("R20", regs[20]);
+ SC ("R21", regs[21]);
+ SC ("R22", regs[22]);
+ SC ("R23", regs[23]);
+ SC ("R24", regs[24]);
+ SC ("R25", regs[25]);
+ SC ("R26", regs[26]);
+ SC ("R27", regs[27]);
+ SC ("R28", regs[28]);
+ SC ("R29", regs[29]);
+ SC ("R30", regs[30]);
+ SC ("R31", regs[31]);
+
+ SC ("PC", pc);
+ SC ("SP", sp);
+ SC ("Fault", fault_address);
+ SC ("state", pstate);
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/aarch64/getcontext.S b/src/pal/src/libunwind/src/aarch64/getcontext.S
new file mode 100644
index 0000000000..25ed5b66be
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/getcontext.S
@@ -0,0 +1,52 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 Google, Inc
+ Contributed by Paul Pluzhnikov <ppluzhnikov@google.com>
+ Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "offsets.h"
+
+/* int _Uaarch64_getcontext_trace (unw_tdep_context_t *ucp)
+
+ Saves limited machine context in UCP necessary for fast trace. If fast trace
+ fails, caller will have to get the full context.
+*/
+
+ .global _Uaarch64_getcontext_trace
+ .hidden _Uaarch64_getcontext_trace
+ .type _Uaarch64_getcontext_trace, @function
+_Uaarch64_getcontext_trace:
+ .cfi_startproc
+
+ /* Save only FP, SP, PC - exclude this call. */
+ str x29, [x0, #(LINUX_UC_MCONTEXT_OFF + LINUX_SC_X29_OFF)]
+ mov x9, sp
+ str x9, [x0, #(LINUX_UC_MCONTEXT_OFF + LINUX_SC_SP_OFF)]
+ str x30, [x0, #(LINUX_UC_MCONTEXT_OFF + LINUX_SC_PC_OFF)]
+
+ ret
+ .cfi_endproc
+ .size _Uaarch64_getcontext_trace, . - _Uaarch64_getcontext_trace
+
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
diff --git a/src/pal/src/libunwind/src/aarch64/init.h b/src/pal/src/libunwind/src/aarch64/init.h
new file mode 100644
index 0000000000..5dab60bb64
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/init.h
@@ -0,0 +1,126 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+ Copyright (C) 2013 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+static inline int
+common_init (struct cursor *c, unsigned use_prev_instr)
+{
+ int ret, i;
+
+ c->dwarf.loc[UNW_AARCH64_X0] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X0);
+ c->dwarf.loc[UNW_AARCH64_X1] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X1);
+ c->dwarf.loc[UNW_AARCH64_X2] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X2);
+ c->dwarf.loc[UNW_AARCH64_X3] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X3);
+ c->dwarf.loc[UNW_AARCH64_X4] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X4);
+ c->dwarf.loc[UNW_AARCH64_X5] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X5);
+ c->dwarf.loc[UNW_AARCH64_X6] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X6);
+ c->dwarf.loc[UNW_AARCH64_X7] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X7);
+ c->dwarf.loc[UNW_AARCH64_X8] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X8);
+ c->dwarf.loc[UNW_AARCH64_X9] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X9);
+ c->dwarf.loc[UNW_AARCH64_X10] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X10);
+ c->dwarf.loc[UNW_AARCH64_X11] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X11);
+ c->dwarf.loc[UNW_AARCH64_X12] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X12);
+ c->dwarf.loc[UNW_AARCH64_X13] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X13);
+ c->dwarf.loc[UNW_AARCH64_X14] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X14);
+ c->dwarf.loc[UNW_AARCH64_X15] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X15);
+ c->dwarf.loc[UNW_AARCH64_X16] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X16);
+ c->dwarf.loc[UNW_AARCH64_X17] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X17);
+ c->dwarf.loc[UNW_AARCH64_X18] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X18);
+ c->dwarf.loc[UNW_AARCH64_X19] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X19);
+ c->dwarf.loc[UNW_AARCH64_X20] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X20);
+ c->dwarf.loc[UNW_AARCH64_X21] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X21);
+ c->dwarf.loc[UNW_AARCH64_X22] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X22);
+ c->dwarf.loc[UNW_AARCH64_X23] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X23);
+ c->dwarf.loc[UNW_AARCH64_X24] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X24);
+ c->dwarf.loc[UNW_AARCH64_X25] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X25);
+ c->dwarf.loc[UNW_AARCH64_X26] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X26);
+ c->dwarf.loc[UNW_AARCH64_X27] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X27);
+ c->dwarf.loc[UNW_AARCH64_X28] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X28);
+ c->dwarf.loc[UNW_AARCH64_X29] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X29);
+ c->dwarf.loc[UNW_AARCH64_X30] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X30);
+ c->dwarf.loc[UNW_AARCH64_SP] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_SP);
+ c->dwarf.loc[UNW_AARCH64_PC] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_PC);
+ c->dwarf.loc[UNW_AARCH64_PSTATE] = DWARF_REG_LOC (&c->dwarf,
+ UNW_AARCH64_PSTATE);
+ c->dwarf.loc[UNW_AARCH64_V0] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V0);
+ c->dwarf.loc[UNW_AARCH64_V1] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V1);
+ c->dwarf.loc[UNW_AARCH64_V2] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V2);
+ c->dwarf.loc[UNW_AARCH64_V3] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V3);
+ c->dwarf.loc[UNW_AARCH64_V4] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V4);
+ c->dwarf.loc[UNW_AARCH64_V5] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V5);
+ c->dwarf.loc[UNW_AARCH64_V6] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V6);
+ c->dwarf.loc[UNW_AARCH64_V7] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V7);
+ c->dwarf.loc[UNW_AARCH64_V8] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V8);
+ c->dwarf.loc[UNW_AARCH64_V9] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V9);
+ c->dwarf.loc[UNW_AARCH64_V10] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V10);
+ c->dwarf.loc[UNW_AARCH64_V11] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V11);
+ c->dwarf.loc[UNW_AARCH64_V12] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V12);
+ c->dwarf.loc[UNW_AARCH64_V13] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V13);
+ c->dwarf.loc[UNW_AARCH64_V14] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V14);
+ c->dwarf.loc[UNW_AARCH64_V15] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V15);
+ c->dwarf.loc[UNW_AARCH64_V16] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V16);
+ c->dwarf.loc[UNW_AARCH64_V17] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V17);
+ c->dwarf.loc[UNW_AARCH64_V18] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V18);
+ c->dwarf.loc[UNW_AARCH64_V19] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V19);
+ c->dwarf.loc[UNW_AARCH64_V20] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V20);
+ c->dwarf.loc[UNW_AARCH64_V21] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V21);
+ c->dwarf.loc[UNW_AARCH64_V22] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V22);
+ c->dwarf.loc[UNW_AARCH64_V23] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V23);
+ c->dwarf.loc[UNW_AARCH64_V24] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V24);
+ c->dwarf.loc[UNW_AARCH64_V25] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V25);
+ c->dwarf.loc[UNW_AARCH64_V26] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V26);
+ c->dwarf.loc[UNW_AARCH64_V27] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V27);
+ c->dwarf.loc[UNW_AARCH64_V28] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V28);
+ c->dwarf.loc[UNW_AARCH64_V29] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V29);
+ c->dwarf.loc[UNW_AARCH64_V30] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V30);
+ c->dwarf.loc[UNW_AARCH64_V31] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V31);
+
+ for (i = UNW_AARCH64_PSTATE + 1; i < UNW_AARCH64_V0; ++i)
+ c->dwarf.loc[i] = DWARF_NULL_LOC;
+
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip);
+ if (ret < 0)
+ return ret;
+
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_SP], &c->dwarf.cfa);
+ if (ret < 0)
+ return ret;
+
+ c->sigcontext_format = AARCH64_SCF_NONE;
+ c->sigcontext_addr = 0;
+ c->sigcontext_sp = 0;
+ c->sigcontext_pc = 0;
+
+ c->dwarf.args_size = 0;
+ c->dwarf.stash_frames = 0;
+ c->dwarf.use_prev_instr = use_prev_instr;
+ c->dwarf.pi_valid = 0;
+ c->dwarf.pi_is_dynamic = 0;
+ c->dwarf.hint = 0;
+ c->dwarf.prev_rs = 0;
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/aarch64/is_fpreg.c b/src/pal/src/libunwind/src/aarch64/is_fpreg.c
new file mode 100644
index 0000000000..2981d27520
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/is_fpreg.c
@@ -0,0 +1,32 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2013 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+int
+unw_is_fpreg (int regnum)
+{
+ return (regnum >= UNW_AARCH64_V0 && regnum <= UNW_AARCH64_V31);
+}
diff --git a/src/pal/src/libunwind/src/aarch64/offsets.h b/src/pal/src/libunwind/src/aarch64/offsets.h
new file mode 100644
index 0000000000..e78251d0a8
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/offsets.h
@@ -0,0 +1,49 @@
+/* Linux-specific definitions: */
+
+/* Define various structure offsets to simplify cross-compilation. */
+
+/* Offsets for AArch64 Linux "ucontext_t": */
+
+#define LINUX_UC_FLAGS_OFF 0x0
+#define LINUX_UC_LINK_OFF 0x8
+#define LINUX_UC_STACK_OFF 0x10
+#define LINUX_UC_SIGMASK_OFF 0x28
+#define LINUX_UC_MCONTEXT_OFF 0xb0
+
+/* Offsets for AArch64 Linux "struct sigcontext": */
+
+#define LINUX_SC_FAULTADDRESS_OFF 0x00
+#define LINUX_SC_X0_OFF 0x008
+#define LINUX_SC_X1_OFF 0x010
+#define LINUX_SC_X2_OFF 0x018
+#define LINUX_SC_X3_OFF 0x020
+#define LINUX_SC_X4_OFF 0x028
+#define LINUX_SC_X5_OFF 0x030
+#define LINUX_SC_X6_OFF 0x038
+#define LINUX_SC_X7_OFF 0x040
+#define LINUX_SC_X8_OFF 0x048
+#define LINUX_SC_X9_OFF 0x050
+#define LINUX_SC_X10_OFF 0x058
+#define LINUX_SC_X11_OFF 0x060
+#define LINUX_SC_X12_OFF 0x068
+#define LINUX_SC_X13_OFF 0x070
+#define LINUX_SC_X14_OFF 0x078
+#define LINUX_SC_X15_OFF 0x080
+#define LINUX_SC_X16_OFF 0x088
+#define LINUX_SC_X17_OFF 0x090
+#define LINUX_SC_X18_OFF 0x098
+#define LINUX_SC_X19_OFF 0x0a0
+#define LINUX_SC_X20_OFF 0x0a8
+#define LINUX_SC_X21_OFF 0x0b0
+#define LINUX_SC_X22_OFF 0x0b8
+#define LINUX_SC_X23_OFF 0x0c0
+#define LINUX_SC_X24_OFF 0x0c8
+#define LINUX_SC_X25_OFF 0x0d0
+#define LINUX_SC_X26_OFF 0x0d8
+#define LINUX_SC_X27_OFF 0x0e0
+#define LINUX_SC_X28_OFF 0x0e8
+#define LINUX_SC_X29_OFF 0x0f0
+#define LINUX_SC_X30_OFF 0x0f8
+#define LINUX_SC_SP_OFF 0x100
+#define LINUX_SC_PC_OFF 0x108
+#define LINUX_SC_PSTATE_OFF 0x110
diff --git a/src/pal/src/libunwind/src/aarch64/regname.c b/src/pal/src/libunwind/src/aarch64/regname.c
new file mode 100644
index 0000000000..0f7a8bdcfb
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/regname.c
@@ -0,0 +1,106 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+ Copyright (C) 2013 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+static const char *const regname[] =
+ {
+ [UNW_AARCH64_X0] = "x0",
+ [UNW_AARCH64_X1] = "x1",
+ [UNW_AARCH64_X2] = "x2",
+ [UNW_AARCH64_X3] = "x3",
+ [UNW_AARCH64_X4] = "x4",
+ [UNW_AARCH64_X5] = "x5",
+ [UNW_AARCH64_X6] = "x6",
+ [UNW_AARCH64_X7] = "x7",
+ [UNW_AARCH64_X8] = "x8",
+ [UNW_AARCH64_X9] = "x9",
+ [UNW_AARCH64_X10] = "x10",
+ [UNW_AARCH64_X11] = "x11",
+ [UNW_AARCH64_X12] = "x12",
+ [UNW_AARCH64_X13] = "x13",
+ [UNW_AARCH64_X14] = "x14",
+ [UNW_AARCH64_X15] = "x15",
+ [UNW_AARCH64_X16] = "ip0",
+ [UNW_AARCH64_X17] = "ip1",
+ [UNW_AARCH64_X18] = "x18",
+ [UNW_AARCH64_X19] = "x19",
+ [UNW_AARCH64_X20] = "x20",
+ [UNW_AARCH64_X21] = "x21",
+ [UNW_AARCH64_X22] = "x22",
+ [UNW_AARCH64_X23] = "x23",
+ [UNW_AARCH64_X24] = "x24",
+ [UNW_AARCH64_X25] = "x25",
+ [UNW_AARCH64_X26] = "x26",
+ [UNW_AARCH64_X27] = "x27",
+ [UNW_AARCH64_X28] = "x28",
+ [UNW_AARCH64_X29] = "fp",
+ [UNW_AARCH64_X30] = "lr",
+ [UNW_AARCH64_SP] = "sp",
+ [UNW_AARCH64_PC] = "pc",
+ [UNW_AARCH64_V0] = "v0",
+ [UNW_AARCH64_V1] = "v1",
+ [UNW_AARCH64_V2] = "v2",
+ [UNW_AARCH64_V3] = "v3",
+ [UNW_AARCH64_V4] = "v4",
+ [UNW_AARCH64_V5] = "v5",
+ [UNW_AARCH64_V6] = "v6",
+ [UNW_AARCH64_V7] = "v7",
+ [UNW_AARCH64_V8] = "v8",
+ [UNW_AARCH64_V9] = "v9",
+ [UNW_AARCH64_V10] = "v10",
+ [UNW_AARCH64_V11] = "v11",
+ [UNW_AARCH64_V12] = "v12",
+ [UNW_AARCH64_V13] = "v13",
+ [UNW_AARCH64_V14] = "v14",
+ [UNW_AARCH64_V15] = "v15",
+ [UNW_AARCH64_V16] = "v16",
+ [UNW_AARCH64_V17] = "v17",
+ [UNW_AARCH64_V18] = "v18",
+ [UNW_AARCH64_V19] = "v19",
+ [UNW_AARCH64_V20] = "v20",
+ [UNW_AARCH64_V21] = "v21",
+ [UNW_AARCH64_V22] = "v22",
+ [UNW_AARCH64_V23] = "v23",
+ [UNW_AARCH64_V24] = "v24",
+ [UNW_AARCH64_V25] = "v25",
+ [UNW_AARCH64_V26] = "v26",
+ [UNW_AARCH64_V27] = "v27",
+ [UNW_AARCH64_V28] = "v28",
+ [UNW_AARCH64_V29] = "v29",
+ [UNW_AARCH64_V30] = "v30",
+ [UNW_AARCH64_V31] = "v31",
+ [UNW_AARCH64_FPSR] = "fpsr",
+ [UNW_AARCH64_FPCR] = "fpcr",
+ };
+
+const char *
+unw_regname (unw_regnum_t reg)
+{
+ if (reg < (unw_regnum_t) ARRAY_SIZE (regname) && regname[reg] != NULL)
+ return regname[reg];
+ else
+ return "???";
+}
diff --git a/src/pal/src/libunwind/src/aarch64/siglongjmp.S b/src/pal/src/libunwind/src/aarch64/siglongjmp.S
new file mode 100644
index 0000000000..9985c4b4aa
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/siglongjmp.S
@@ -0,0 +1,12 @@
+ /* Dummy implementation for now. */
+
+ .global _UI_siglongjmp_cont
+ .global _UI_longjmp_cont
+
+_UI_siglongjmp_cont:
+_UI_longjmp_cont:
+ ret
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",%progbits
+#endif
diff --git a/src/pal/src/libunwind/src/aarch64/unwind_i.h b/src/pal/src/libunwind/src/aarch64/unwind_i.h
new file mode 100644
index 0000000000..3d324c2b08
--- /dev/null
+++ b/src/pal/src/libunwind/src/aarch64/unwind_i.h
@@ -0,0 +1,64 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2013 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef unwind_i_h
+#define unwind_i_h
+
+#include <stdint.h>
+
+#include <libunwind-aarch64.h>
+
+#include "libunwind_i.h"
+
+/* DWARF column numbers for AArch64: */
+#define X29 29
+#define FP 29
+#define X30 30
+#define LR 30
+#define SP 31
+
+#define aarch64_lock UNW_OBJ(lock)
+#define aarch64_local_resume UNW_OBJ(local_resume)
+#define aarch64_local_addr_space_init UNW_OBJ(local_addr_space_init)
+
+extern void aarch64_local_addr_space_init (void);
+extern int aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
+ void *arg);
+
+/* By-pass calls to access_mem() when known to be safe. */
+#ifdef UNW_LOCAL_ONLY
+# undef ACCESS_MEM_FAST
+# define ACCESS_MEM_FAST(ret,validate,cur,addr,to) \
+ do { \
+ if (unlikely(validate)) \
+ (ret) = dwarf_get ((cur), DWARF_MEM_LOC ((cur), (addr)), &(to)); \
+ else \
+ (ret) = 0, (to) = *(unw_word_t *)(addr); \
+ } while (0)
+#endif
+
+#define GET_FPCTX(uc) ((struct fpsimd_context *)(&uc->uc_mcontext.__reserved))
+
+#endif /* unwind_i_h */
diff --git a/src/pal/src/libunwind/src/arm/Gapply_reg_state.c b/src/pal/src/libunwind/src/arm/Gapply_reg_state.c
new file mode 100644
index 0000000000..82f056da67
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Gapply_reg_state.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+ void *reg_states_data)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
diff --git a/src/pal/src/libunwind/src/arm/Gcreate_addr_space.c b/src/pal/src/libunwind/src/arm/Gcreate_addr_space.c
new file mode 100644
index 0000000000..7b2d6bacfd
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Gcreate_addr_space.c
@@ -0,0 +1,60 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+
+#include "unwind_i.h"
+
+unw_addr_space_t
+unw_create_addr_space (unw_accessors_t *a, int byte_order)
+{
+#ifdef UNW_LOCAL_ONLY
+ return NULL;
+#else
+ unw_addr_space_t as;
+
+ /*
+ * ARM supports little-endian and big-endian.
+ */
+ if (byte_order != 0 && byte_order != __LITTLE_ENDIAN
+ && byte_order != __BIG_ENDIAN)
+ return NULL;
+
+ as = malloc (sizeof (*as));
+ if (!as)
+ return NULL;
+
+ memset (as, 0, sizeof (*as));
+
+ as->acc = *a;
+
+ /* Default to little-endian for ARM. */
+ if (byte_order == 0 || byte_order == __LITTLE_ENDIAN)
+ as->big_endian = 0;
+ else
+ as->big_endian = 1;
+
+ return as;
+#endif
+}
diff --git a/src/pal/src/libunwind/src/arm/Gex_tables.c b/src/pal/src/libunwind/src/arm/Gex_tables.c
new file mode 100644
index 0000000000..d6573a65e0
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Gex_tables.c
@@ -0,0 +1,549 @@
+/* libunwind - a platform-independent unwind library
+ Copyright 2011 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* This file contains functionality for parsing and interpreting the ARM
+specific unwind information. Documentation about the exception handling
+ABI for the ARM architecture can be found at:
+http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf
+*/
+
+#include "libunwind_i.h"
+
+#define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f)
+#define ARM_EXBUF_COUNT(x) ((x) & 0x0f)
+#define ARM_EXBUF_END(x) (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x))
+
+#define ARM_EXIDX_CANT_UNWIND 0x00000001
+#define ARM_EXIDX_COMPACT 0x80000000
+
+#define ARM_EXTBL_OP_FINISH 0xb0
+
+enum arm_exbuf_cmd_flags {
+ ARM_EXIDX_VFP_SHIFT_16 = 1 << 16,
+ ARM_EXIDX_VFP_DOUBLE = 1 << 17,
+};
+
+struct arm_cb_data
+ {
+ /* in: */
+ unw_word_t ip; /* instruction-pointer we're looking for */
+ unw_proc_info_t *pi; /* proc-info pointer */
+ /* out: */
+ unw_dyn_info_t di; /* info about the ARM exidx segment */
+ };
+
+static inline uint32_t CONST_ATTR
+prel31_read (uint32_t prel31)
+{
+ return ((int32_t)prel31 << 1) >> 1;
+}
+
+static inline int
+prel31_to_addr (unw_addr_space_t as, void *arg, unw_word_t prel31,
+ unw_word_t *val)
+{
+ unw_word_t offset;
+
+ if ((*as->acc.access_mem)(as, prel31, &offset, 0, arg) < 0)
+ return -UNW_EINVAL;
+
+ offset = ((long)offset << 1) >> 1;
+ *val = prel31 + offset;
+
+ return 0;
+}
+
+/**
+ * Applies the given command onto the new state to the given dwarf_cursor.
+ */
+HIDDEN int
+arm_exidx_apply_cmd (struct arm_exbuf_data *edata, struct dwarf_cursor *c)
+{
+ int ret = 0;
+ unsigned i;
+
+ switch (edata->cmd)
+ {
+ case ARM_EXIDX_CMD_FINISH:
+ /* Set LR to PC if not set already. */
+ if (DWARF_IS_NULL_LOC (c->loc[UNW_ARM_R15]))
+ c->loc[UNW_ARM_R15] = c->loc[UNW_ARM_R14];
+ /* Set IP. */
+ dwarf_get (c, c->loc[UNW_ARM_R15], &c->ip);
+ break;
+ case ARM_EXIDX_CMD_DATA_PUSH:
+ Debug (2, "vsp = vsp - %d\n", edata->data);
+ c->cfa -= edata->data;
+ break;
+ case ARM_EXIDX_CMD_DATA_POP:
+ Debug (2, "vsp = vsp + %d\n", edata->data);
+ c->cfa += edata->data;
+ break;
+ case ARM_EXIDX_CMD_REG_POP:
+ for (i = 0; i < 16; i++)
+ if (edata->data & (1 << i))
+ {
+ Debug (2, "pop {r%d}\n", i);
+ c->loc[UNW_ARM_R0 + i] = DWARF_LOC (c->cfa, 0);
+ c->cfa += 4;
+ }
+ /* Set cfa in case the SP got popped. */
+ if (edata->data & (1 << 13))
+ dwarf_get (c, c->loc[UNW_ARM_R13], &c->cfa);
+ break;
+ case ARM_EXIDX_CMD_REG_TO_SP:
+ assert (edata->data < 16);
+ Debug (2, "vsp = r%d\n", edata->data);
+ c->loc[UNW_ARM_R13] = c->loc[UNW_ARM_R0 + edata->data];
+ dwarf_get (c, c->loc[UNW_ARM_R13], &c->cfa);
+ break;
+ case ARM_EXIDX_CMD_VFP_POP:
+ /* Skip VFP registers, but be sure to adjust stack */
+ for (i = ARM_EXBUF_START (edata->data); i <= ARM_EXBUF_END (edata->data);
+ i++)
+ c->cfa += 8;
+ if (!(edata->data & ARM_EXIDX_VFP_DOUBLE))
+ c->cfa += 4;
+ break;
+ case ARM_EXIDX_CMD_WREG_POP:
+ for (i = ARM_EXBUF_START (edata->data); i <= ARM_EXBUF_END (edata->data);
+ i++)
+ c->cfa += 8;
+ break;
+ case ARM_EXIDX_CMD_WCGR_POP:
+ for (i = 0; i < 4; i++)
+ if (edata->data & (1 << i))
+ c->cfa += 4;
+ break;
+ case ARM_EXIDX_CMD_REFUSED:
+ case ARM_EXIDX_CMD_RESERVED:
+ ret = -1;
+ break;
+ }
+ return ret;
+}
+
+/**
+ * Decodes the given unwind instructions into arm_exbuf_data and calls
+ * arm_exidx_apply_cmd that applies the command onto the dwarf_cursor.
+ */
+HIDDEN int
+arm_exidx_decode (const uint8_t *buf, uint8_t len, struct dwarf_cursor *c)
+{
+#define READ_OP() *buf++
+ const uint8_t *end = buf + len;
+ int ret;
+ struct arm_exbuf_data edata;
+
+ assert(buf != NULL);
+ assert(len > 0);
+
+ while (buf < end)
+ {
+ uint8_t op = READ_OP ();
+ if ((op & 0xc0) == 0x00)
+ {
+ edata.cmd = ARM_EXIDX_CMD_DATA_POP;
+ edata.data = (((int)op & 0x3f) << 2) + 4;
+ }
+ else if ((op & 0xc0) == 0x40)
+ {
+ edata.cmd = ARM_EXIDX_CMD_DATA_PUSH;
+ edata.data = (((int)op & 0x3f) << 2) + 4;
+ }
+ else if ((op & 0xf0) == 0x80)
+ {
+ uint8_t op2 = READ_OP ();
+ if (op == 0x80 && op2 == 0x00)
+ edata.cmd = ARM_EXIDX_CMD_REFUSED;
+ else
+ {
+ edata.cmd = ARM_EXIDX_CMD_REG_POP;
+ edata.data = ((op & 0xf) << 8) | op2;
+ edata.data = edata.data << 4;
+ }
+ }
+ else if ((op & 0xf0) == 0x90)
+ {
+ if (op == 0x9d || op == 0x9f)
+ edata.cmd = ARM_EXIDX_CMD_RESERVED;
+ else
+ {
+ edata.cmd = ARM_EXIDX_CMD_REG_TO_SP;
+ edata.data = op & 0x0f;
+ }
+ }
+ else if ((op & 0xf0) == 0xa0)
+ {
+ unsigned end = (op & 0x07);
+ edata.data = (1 << (end + 1)) - 1;
+ edata.data = edata.data << 4;
+ if (op & 0x08)
+ edata.data |= 1 << 14;
+ edata.cmd = ARM_EXIDX_CMD_REG_POP;
+ }
+ else if (op == ARM_EXTBL_OP_FINISH)
+ {
+ edata.cmd = ARM_EXIDX_CMD_FINISH;
+ buf = end;
+ }
+ else if (op == 0xb1)
+ {
+ uint8_t op2 = READ_OP ();
+ if (op2 == 0 || (op2 & 0xf0))
+ edata.cmd = ARM_EXIDX_CMD_RESERVED;
+ else
+ {
+ edata.cmd = ARM_EXIDX_CMD_REG_POP;
+ edata.data = op2 & 0x0f;
+ }
+ }
+ else if (op == 0xb2)
+ {
+ uint32_t offset = 0;
+ uint8_t byte, shift = 0;
+ do
+ {
+ byte = READ_OP ();
+ offset |= (byte & 0x7f) << shift;
+ shift += 7;
+ }
+ while (byte & 0x80);
+ edata.data = offset * 4 + 0x204;
+ edata.cmd = ARM_EXIDX_CMD_DATA_POP;
+ }
+ else if (op == 0xb3 || op == 0xc8 || op == 0xc9)
+ {
+ edata.cmd = ARM_EXIDX_CMD_VFP_POP;
+ edata.data = READ_OP ();
+ if (op == 0xc8)
+ edata.data |= ARM_EXIDX_VFP_SHIFT_16;
+ if (op != 0xb3)
+ edata.data |= ARM_EXIDX_VFP_DOUBLE;
+ }
+ else if ((op & 0xf8) == 0xb8 || (op & 0xf8) == 0xd0)
+ {
+ edata.cmd = ARM_EXIDX_CMD_VFP_POP;
+ edata.data = 0x80 | (op & 0x07);
+ if ((op & 0xf8) == 0xd0)
+ edata.data |= ARM_EXIDX_VFP_DOUBLE;
+ }
+ else if (op >= 0xc0 && op <= 0xc5)
+ {
+ edata.cmd = ARM_EXIDX_CMD_WREG_POP;
+ edata.data = 0xa0 | (op & 0x07);
+ }
+ else if (op == 0xc6)
+ {
+ edata.cmd = ARM_EXIDX_CMD_WREG_POP;
+ edata.data = READ_OP ();
+ }
+ else if (op == 0xc7)
+ {
+ uint8_t op2 = READ_OP ();
+ if (op2 == 0 || (op2 & 0xf0))
+ edata.cmd = ARM_EXIDX_CMD_RESERVED;
+ else
+ {
+ edata.cmd = ARM_EXIDX_CMD_WCGR_POP;
+ edata.data = op2 & 0x0f;
+ }
+ }
+ else
+ edata.cmd = ARM_EXIDX_CMD_RESERVED;
+
+ ret = arm_exidx_apply_cmd (&edata, c);
+ if (ret < 0)
+ return ret;
+ }
+ return 0;
+}
+
+/**
+ * Reads the entry from the given cursor and extracts the unwind instructions
+ * into buf. Returns the number of the extracted unwind insns or
+ * -UNW_ESTOPUNWIND if the special bit pattern ARM_EXIDX_CANT_UNWIND (0x1) was
+ * found.
+ */
+HIDDEN int
+arm_exidx_extract (struct dwarf_cursor *c, uint8_t *buf)
+{
+ int nbuf = 0;
+ unw_word_t entry = (unw_word_t) c->pi.unwind_info;
+ unw_word_t addr;
+ uint32_t data;
+
+ /* An ARM unwind entry consists of a prel31 offset to the start of a
+ function followed by 31bits of data:
+ * if set to 0x1: the function cannot be unwound (EXIDX_CANTUNWIND)
+ * if bit 31 is one: this is a table entry itself (ARM_EXIDX_COMPACT)
+ * if bit 31 is zero: this is a prel31 offset of the start of the
+ table entry for this function */
+ if (prel31_to_addr(c->as, c->as_arg, entry, &addr) < 0)
+ return -UNW_EINVAL;
+
+ if ((*c->as->acc.access_mem)(c->as, entry + 4, &data, 0, c->as_arg) < 0)
+ return -UNW_EINVAL;
+
+ if (data == ARM_EXIDX_CANT_UNWIND)
+ {
+ Debug (2, "0x1 [can't unwind]\n");
+ nbuf = -UNW_ESTOPUNWIND;
+ }
+ else if (data & ARM_EXIDX_COMPACT)
+ {
+ Debug (2, "%p compact model %d [%8.8x]\n", (void *)addr,
+ (data >> 24) & 0x7f, data);
+ buf[nbuf++] = data >> 16;
+ buf[nbuf++] = data >> 8;
+ buf[nbuf++] = data;
+ }
+ else
+ {
+ unw_word_t extbl_data;
+ unsigned int n_table_words = 0;
+
+ if (prel31_to_addr(c->as, c->as_arg, entry + 4, &extbl_data) < 0)
+ return -UNW_EINVAL;
+
+ if ((*c->as->acc.access_mem)(c->as, extbl_data, &data, 0, c->as_arg) < 0)
+ return -UNW_EINVAL;
+
+ if (data & ARM_EXIDX_COMPACT)
+ {
+ int pers = (data >> 24) & 0x0f;
+ Debug (2, "%p compact model %d [%8.8x]\n", (void *)addr, pers, data);
+ if (pers == 1 || pers == 2)
+ {
+ n_table_words = (data >> 16) & 0xff;
+ extbl_data += 4;
+ }
+ else
+ buf[nbuf++] = data >> 16;
+ buf[nbuf++] = data >> 8;
+ buf[nbuf++] = data;
+ }
+ else
+ {
+ unw_word_t pers;
+ if (prel31_to_addr (c->as, c->as_arg, extbl_data, &pers) < 0)
+ return -UNW_EINVAL;
+ Debug (2, "%p Personality routine: %8p\n", (void *)addr,
+ (void *)pers);
+ if ((*c->as->acc.access_mem)(c->as, extbl_data + 4, &data, 0,
+ c->as_arg) < 0)
+ return -UNW_EINVAL;
+ n_table_words = data >> 24;
+ buf[nbuf++] = data >> 16;
+ buf[nbuf++] = data >> 8;
+ buf[nbuf++] = data;
+ extbl_data += 8;
+ }
+ assert (n_table_words <= 5);
+ unsigned j;
+ for (j = 0; j < n_table_words; j++)
+ {
+ if ((*c->as->acc.access_mem)(c->as, extbl_data, &data, 0,
+ c->as_arg) < 0)
+ return -UNW_EINVAL;
+ extbl_data += 4;
+ buf[nbuf++] = data >> 24;
+ buf[nbuf++] = data >> 16;
+ buf[nbuf++] = data >> 8;
+ buf[nbuf++] = data >> 0;
+ }
+ }
+
+ if (nbuf > 0 && buf[nbuf - 1] != ARM_EXTBL_OP_FINISH)
+ buf[nbuf++] = ARM_EXTBL_OP_FINISH;
+
+ return nbuf;
+}
+
+int
+arm_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
+ unw_dyn_info_t *di, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg)
+{
+ /* The .ARM.exidx section contains a sorted list of key-value pairs -
+ the unwind entries. The 'key' is a prel31 offset to the start of a
+ function. We binary search this section in order to find the
+ appropriate unwind entry. */
+ unw_word_t first = di->u.rti.table_data;
+ unw_word_t last = di->u.rti.table_data + di->u.rti.table_len - 8;
+ unw_word_t entry, val;
+
+ if (prel31_to_addr (as, arg, first, &val) < 0 || ip < val)
+ return -UNW_ENOINFO;
+
+ if (prel31_to_addr (as, arg, last, &val) < 0)
+ return -UNW_EINVAL;
+
+ if (ip >= val)
+ {
+ entry = last;
+
+ if (prel31_to_addr (as, arg, last, &pi->start_ip) < 0)
+ return -UNW_EINVAL;
+
+ pi->end_ip = di->end_ip -1;
+ }
+ else
+ {
+ while (first < last - 8)
+ {
+ entry = first + (((last - first) / 8 + 1) >> 1) * 8;
+
+ if (prel31_to_addr (as, arg, entry, &val) < 0)
+ return -UNW_EINVAL;
+
+ if (ip < val)
+ last = entry;
+ else
+ first = entry;
+ }
+
+ entry = first;
+
+ if (prel31_to_addr (as, arg, entry, &pi->start_ip) < 0)
+ return -UNW_EINVAL;
+
+ if (prel31_to_addr (as, arg, entry + 8, &pi->end_ip) < 0)
+ return -UNW_EINVAL;
+
+ pi->end_ip--;
+ }
+
+ if (need_unwind_info)
+ {
+ pi->unwind_info_size = 8;
+ pi->unwind_info = (void *) entry;
+ pi->format = UNW_INFO_FORMAT_ARM_EXIDX;
+ }
+ return 0;
+}
+
+int
+tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
+ unw_dyn_info_t *di, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg)
+{
+ if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)
+ && di->format == UNW_INFO_FORMAT_ARM_EXIDX)
+ return arm_search_unwind_table (as, ip, di, pi, need_unwind_info, arg);
+ else if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)
+ && di->format != UNW_INFO_FORMAT_ARM_EXIDX)
+ return dwarf_search_unwind_table (as, ip, di, pi, need_unwind_info, arg);
+
+ return -UNW_ENOINFO;
+}
+
+#ifndef UNW_REMOTE_ONLY
+/**
+ * Callback to dl_iterate_phdr to find infos about the ARM exidx segment.
+ */
+static int
+arm_phdr_cb (struct dl_phdr_info *info, size_t size, void *data)
+{
+ struct arm_cb_data *cb_data = data;
+ const Elf_W(Phdr) *p_text = NULL;
+ const Elf_W(Phdr) *p_arm_exidx = NULL;
+ const Elf_W(Phdr) *phdr = info->dlpi_phdr;
+ long n;
+
+ for (n = info->dlpi_phnum; --n >= 0; phdr++)
+ {
+ switch (phdr->p_type)
+ {
+ case PT_LOAD:
+ if (cb_data->ip >= phdr->p_vaddr + info->dlpi_addr &&
+ cb_data->ip < phdr->p_vaddr + info->dlpi_addr + phdr->p_memsz)
+ p_text = phdr;
+ break;
+
+ case PT_ARM_EXIDX:
+ p_arm_exidx = phdr;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (p_text && p_arm_exidx)
+ {
+ cb_data->di.format = UNW_INFO_FORMAT_ARM_EXIDX;
+ cb_data->di.start_ip = p_text->p_vaddr + info->dlpi_addr;
+ cb_data->di.end_ip = cb_data->di.start_ip + p_text->p_memsz;
+ cb_data->di.u.rti.name_ptr = (unw_word_t) info->dlpi_name;
+ cb_data->di.u.rti.table_data = p_arm_exidx->p_vaddr + info->dlpi_addr;
+ cb_data->di.u.rti.table_len = p_arm_exidx->p_memsz;
+ return 1;
+ }
+
+ return 0;
+}
+
+HIDDEN int
+arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
+ unw_proc_info_t *pi, int need_unwind_info, void *arg)
+{
+ int ret = -1;
+ intrmask_t saved_mask;
+
+ Debug (14, "looking for IP=0x%lx\n", (long) ip);
+
+ if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF))
+ ret = dwarf_find_proc_info (as, ip, pi, need_unwind_info, arg);
+
+ if (ret < 0 && UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX))
+ {
+ struct arm_cb_data cb_data;
+
+ memset (&cb_data, 0, sizeof (cb_data));
+ cb_data.ip = ip;
+ cb_data.pi = pi;
+ cb_data.di.format = -1;
+
+ SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask);
+ ret = dl_iterate_phdr (arm_phdr_cb, &cb_data);
+ SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
+
+ if (cb_data.di.format != -1)
+ ret = arm_search_unwind_table (as, ip, &cb_data.di, pi,
+ need_unwind_info, arg);
+ else
+ ret = -UNW_ENOINFO;
+ }
+
+ return ret;
+}
+
+HIDDEN void
+arm_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
+{
+ /* it's a no-op */
+}
+#endif /* !UNW_REMOTE_ONLY */
+
diff --git a/src/pal/src/libunwind/src/arm/Gget_proc_info.c b/src/pal/src/libunwind/src/arm/Gget_proc_info.c
new file mode 100644
index 0000000000..4051a10766
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Gget_proc_info.c
@@ -0,0 +1,41 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ /* We can only unwind using Dwarf into on ARM: return failure code
+ if it's not present. */
+ ret = dwarf_make_proc_info (&c->dwarf);
+ if (ret < 0)
+ return ret;
+
+ *pi = c->dwarf.pi;
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/arm/Gget_save_loc.c b/src/pal/src/libunwind/src/arm/Gget_save_loc.c
new file mode 100644
index 0000000000..9fb070489c
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Gget_save_loc.c
@@ -0,0 +1,81 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ dwarf_loc_t loc;
+
+ loc = DWARF_NULL_LOC; /* default to "not saved" */
+
+ switch (reg)
+ {
+ case UNW_ARM_R0:
+ case UNW_ARM_R1:
+ case UNW_ARM_R2:
+ case UNW_ARM_R3:
+ case UNW_ARM_R4:
+ case UNW_ARM_R5:
+ case UNW_ARM_R6:
+ case UNW_ARM_R7:
+ case UNW_ARM_R8:
+ case UNW_ARM_R9:
+ case UNW_ARM_R10:
+ case UNW_ARM_R11:
+ case UNW_ARM_R12:
+ case UNW_ARM_R13:
+ case UNW_ARM_R14:
+ case UNW_ARM_R15:
+ loc = c->dwarf.loc[reg - UNW_ARM_R0];
+ break;
+
+ default:
+ break;
+ }
+
+ memset (sloc, 0, sizeof (*sloc));
+
+ if (DWARF_IS_NULL_LOC (loc))
+ {
+ sloc->type = UNW_SLT_NONE;
+ return 0;
+ }
+
+#if !defined(UNW_LOCAL_ONLY)
+ if (DWARF_IS_REG_LOC (loc))
+ {
+ sloc->type = UNW_SLT_REG;
+ sloc->u.regnum = DWARF_GET_LOC (loc);
+ }
+ else
+#endif
+ {
+ sloc->type = UNW_SLT_MEMORY;
+ sloc->u.addr = DWARF_GET_LOC (loc);
+ }
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/arm/Gglobal.c b/src/pal/src/libunwind/src/arm/Gglobal.c
new file mode 100644
index 0000000000..7b93fbd89a
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Gglobal.c
@@ -0,0 +1,65 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "dwarf_i.h"
+
+HIDDEN define_lock (arm_lock);
+HIDDEN int tdep_init_done;
+
+/* Unwinding methods to use. See UNW_METHOD_ enums */
+HIDDEN int unwi_unwind_method = UNW_ARM_METHOD_ALL;
+
+HIDDEN void
+tdep_init (void)
+{
+ intrmask_t saved_mask;
+
+ sigfillset (&unwi_full_mask);
+
+ lock_acquire (&arm_lock, saved_mask);
+ {
+ if (tdep_init_done)
+ /* another thread else beat us to it... */
+ goto out;
+
+ /* read ARM unwind method setting */
+ const char* str = getenv ("UNW_ARM_UNWIND_METHOD");
+ if (str)
+ {
+ unwi_unwind_method = atoi (str);
+ }
+
+ mi_init ();
+
+ dwarf_init ();
+
+#ifndef UNW_REMOTE_ONLY
+ arm_local_addr_space_init ();
+#endif
+ tdep_init_done = 1; /* signal that we're initialized... */
+ }
+ out:
+ lock_release (&arm_lock, saved_mask);
+}
diff --git a/src/pal/src/libunwind/src/arm/Ginit.c b/src/pal/src/libunwind/src/arm/Ginit.c
new file mode 100644
index 0000000000..2720d063a2
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Ginit.c
@@ -0,0 +1,235 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "unwind_i.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+/* unw_local_addr_space is a NULL pointer in this case. */
+unw_addr_space_t unw_local_addr_space;
+
+#else /* !UNW_REMOTE_ONLY */
+
+static struct unw_addr_space local_addr_space;
+
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
+
+static inline void *
+uc_addr (unw_tdep_context_t *uc, int reg)
+{
+ if (reg >= UNW_ARM_R0 && reg < UNW_ARM_R0 + 16)
+ return &uc->regs[reg - UNW_ARM_R0];
+ else
+ return NULL;
+}
+
+# ifdef UNW_LOCAL_ONLY
+
+HIDDEN void *
+tdep_uc_addr (unw_tdep_context_t *uc, int reg)
+{
+ return uc_addr (uc, reg);
+}
+
+# endif /* UNW_LOCAL_ONLY */
+
+HIDDEN unw_dyn_info_list_t _U_dyn_info_list;
+
+/* XXX fix me: there is currently no way to locate the dyn-info list
+ by a remote unwinder. On ia64, this is done via a special
+ unwind-table entry. Perhaps something similar can be done with
+ DWARF2 unwind info. */
+
+static int
+get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
+ void *arg)
+{
+ *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list;
+ return 0;
+}
+
+#define PAGE_SIZE 4096
+#define PAGE_START(a) ((a) & ~(PAGE_SIZE-1))
+
+/* Cache of already validated addresses */
+#define NLGA 4
+static unw_word_t last_good_addr[NLGA];
+static int lga_victim;
+
+static int
+validate_mem (unw_word_t addr)
+{
+ int i, victim;
+ size_t len;
+
+ if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr))
+ len = PAGE_SIZE;
+ else
+ len = PAGE_SIZE * 2;
+
+ addr = PAGE_START(addr);
+
+ if (addr == 0)
+ return -1;
+
+ for (i = 0; i < NLGA; i++)
+ {
+ if (last_good_addr[i] && (addr == last_good_addr[i]))
+ return 0;
+ }
+
+ if (msync ((void *) addr, len, MS_ASYNC) == -1)
+ return -1;
+
+ victim = lga_victim;
+ for (i = 0; i < NLGA; i++) {
+ if (!last_good_addr[victim]) {
+ last_good_addr[victim++] = addr;
+ return 0;
+ }
+ victim = (victim + 1) % NLGA;
+ }
+
+ /* All slots full. Evict the victim. */
+ last_good_addr[victim] = addr;
+ victim = (victim + 1) % NLGA;
+ lga_victim = victim;
+
+ return 0;
+}
+
+static int
+access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
+ void *arg)
+{
+ /* validate address */
+ const struct cursor *c = (const struct cursor *) arg;
+ if (c && validate_mem(addr))
+ return -1;
+
+ if (write)
+ {
+ Debug (16, "mem[%x] <- %x\n", addr, *val);
+ *(unw_word_t *) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_word_t *) addr;
+ Debug (16, "mem[%x] -> %x\n", addr, *val);
+ }
+ return 0;
+}
+
+static int
+access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
+ void *arg)
+{
+ unw_word_t *addr;
+ unw_tdep_context_t *uc = arg;
+
+ if (unw_is_fpreg (reg))
+ goto badreg;
+
+Debug (16, "reg = %s\n", unw_regname (reg));
+ if (!(addr = uc_addr (uc, reg)))
+ goto badreg;
+
+ if (write)
+ {
+ *(unw_word_t *) addr = *val;
+ Debug (12, "%s <- %x\n", unw_regname (reg), *val);
+ }
+ else
+ {
+ *val = *(unw_word_t *) addr;
+ Debug (12, "%s -> %x\n", unw_regname (reg), *val);
+ }
+ return 0;
+
+ badreg:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+}
+
+static int
+access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
+ int write, void *arg)
+{
+ unw_tdep_context_t *uc = arg;
+ unw_fpreg_t *addr;
+
+ if (!unw_is_fpreg (reg))
+ goto badreg;
+
+ if (!(addr = uc_addr (uc, reg)))
+ goto badreg;
+
+ if (write)
+ {
+ Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg),
+ ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
+ *(unw_fpreg_t *) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_fpreg_t *) addr;
+ Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg),
+ ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
+ }
+ return 0;
+
+ badreg:
+ Debug (1, "bad register number %u\n", reg);
+ /* attempt to access a non-preserved register */
+ return -UNW_EBADREG;
+}
+
+static int
+get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
+ char *buf, size_t buf_len, unw_word_t *offp,
+ void *arg)
+{
+ return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
+}
+
+HIDDEN void
+arm_local_addr_space_init (void)
+{
+ memset (&local_addr_space, 0, sizeof (local_addr_space));
+ local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
+ local_addr_space.acc.find_proc_info = arm_find_proc_info;
+ local_addr_space.acc.put_unwind_info = arm_put_unwind_info;
+ local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
+ local_addr_space.acc.access_mem = access_mem;
+ local_addr_space.acc.access_reg = access_reg;
+ local_addr_space.acc.access_fpreg = access_fpreg;
+ local_addr_space.acc.resume = arm_local_resume;
+ local_addr_space.acc.get_proc_name = get_static_proc_name;
+ unw_flush_cache (&local_addr_space, 0, 0);
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/arm/Ginit_local.c b/src/pal/src/libunwind/src/arm/Ginit_local.c
new file mode 100644
index 0000000000..e13519b79a
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Ginit_local.c
@@ -0,0 +1,78 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright 2011 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "init.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+int
+unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
+{
+ return -UNW_EINVAL;
+}
+
+#else /* !UNW_REMOTE_ONLY */
+
+static int
+unw_init_local_common (unw_cursor_t *cursor, unw_context_t *uc, unsigned use_prev_instr)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->dwarf.as = unw_local_addr_space;
+ c->dwarf.as_arg = uc;
+
+ return common_init (c, use_prev_instr);
+}
+
+int
+unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
+{
+ return unw_init_local_common(cursor, uc, 1);
+}
+
+int
+unw_init_local2 (unw_cursor_t *cursor, unw_context_t *uc, int flag)
+{
+ if (!flag)
+ {
+ return unw_init_local_common(cursor, uc, 1);
+ }
+ else if (flag == UNW_INIT_SIGNAL_FRAME)
+ {
+ return unw_init_local_common(cursor, uc, 0);
+ }
+ else
+ {
+ return -UNW_EINVAL;
+ }
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/arm/Ginit_remote.c b/src/pal/src/libunwind/src/arm/Ginit_remote.c
new file mode 100644
index 0000000000..9b8ba5b89d
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Ginit_remote.c
@@ -0,0 +1,45 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "init.h"
+#include "unwind_i.h"
+
+int
+unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
+{
+#ifdef UNW_LOCAL_ONLY
+ return -UNW_EINVAL;
+#else /* !UNW_LOCAL_ONLY */
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->dwarf.as = as;
+ c->dwarf.as_arg = as_arg;
+ return common_init (c, 0);
+#endif /* !UNW_LOCAL_ONLY */
+}
diff --git a/src/pal/src/libunwind/src/arm/Gos-freebsd.c b/src/pal/src/libunwind/src/arm/Gos-freebsd.c
new file mode 100644
index 0000000000..a1069223a5
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Gos-freebsd.c
@@ -0,0 +1,129 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright 2011 Linaro Limited
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+ Copyright 2015 The FreeBSD Foundation
+
+ Portions of this software were developed by Konstantin Belousov
+ under sponsorship from the FreeBSD Foundation.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdio.h>
+#include <signal.h>
+#include "unwind_i.h"
+#include "offsets.h"
+#include "ex_tables.h"
+
+HIDDEN int
+arm_handle_signal_frame (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret, fmt;
+ unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa;
+ struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0);
+
+ if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0)
+ return -UNW_EUNSPEC;
+ fmt = unw_is_signal_frame(cursor);
+
+ c->dwarf.pi_valid = 0;
+
+ if (fmt == UNW_ARM_FRAME_SYSCALL)
+ {
+ c->sigcontext_format = ARM_SCF_FREEBSD_SYSCALL;
+ c->frame_info.frame_type = UNW_ARM_FRAME_SYSCALL;
+ c->frame_info.cfa_reg_offset = 0;
+ c->dwarf.loc[UNW_ARM_R7] = c->dwarf.loc[UNW_ARM_R12];
+ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R14], &c->dwarf.ip);
+ return 1;
+ }
+
+ c->sigcontext_format = ARM_SCF_FREEBSD_SIGFRAME;
+ sc_addr = sp_addr;
+
+ /* Save the SP and PC to be able to return execution at this point
+ later in time (unw_resume). */
+ c->sigcontext_sp = c->dwarf.cfa;
+ c->sigcontext_pc = c->dwarf.ip;
+
+ c->sigcontext_addr = sc_addr;
+ c->frame_info.frame_type = UNW_ARM_FRAME_SIGRETURN;
+ c->frame_info.cfa_reg_offset = sc_addr - sp_addr;
+
+ /* Update the dwarf cursor.
+ Set the location of the registers to the corresponding addresses of the
+ uc_mcontext / sigcontext structure contents. */
+#define ROFF(n) (FREEBSD_SC_UCONTEXT_OFF + FREEBSD_UC_MCONTEXT_OFF + \
+ FREEBSD_MC_R0_OFF + (n) * 4)
+#define SL(n) \
+ c->dwarf.loc[UNW_ARM_R ## n] = DWARF_LOC (sc_addr + ROFF(n), 0);
+ SL(0); SL(1); SL(2); SL(3); SL(4); SL(5); SL(6); SL(7);
+ SL(8); SL(9); SL(10); SL(11); SL(12); SL(13); SL(14); SL(15);
+#undef SL
+#undef ROFF
+
+ /* Set SP/CFA and PC/IP. */
+ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R13], &c->dwarf.cfa);
+ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R15], &c->dwarf.ip);
+
+ return 1;
+}
+
+/* Returns 1 in case of a non-RT signal frame and 2 in case of a RT signal
+ frame. */
+int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ unw_word_t w0, w1, w2, w3, ip;
+ unw_addr_space_t as;
+ unw_accessors_t *a;
+ void *arg;
+ int ret;
+
+ as = c->dwarf.as;
+ a = unw_get_accessors_int (as);
+ arg = c->dwarf.as_arg;
+
+ ip = c->dwarf.ip;
+
+ if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0)
+ return ret;
+ if ((ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0)
+ return ret;
+ if ((ret = (*a->access_mem) (as, ip + 8, &w2, 0, arg)) < 0)
+ return ret;
+ if ((ret = (*a->access_mem) (as, ip + 12, &w3, 0, arg)) < 0)
+ return ret;
+
+ if (w0 == 0xe1a0000d && w1 == 0xe2800040 && w2 == 0xe59f700c &&
+ w3 == 0xef0001a1)
+ return UNW_ARM_FRAME_SIGRETURN;
+
+ if ((ret = (*a->access_mem) (as, ip - 4, &w0, 0, arg)) < 0)
+ return ret;
+ if (w0 == 0xef000000)
+ return UNW_ARM_FRAME_SYSCALL;
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/arm/Gos-linux.c b/src/pal/src/libunwind/src/arm/Gos-linux.c
new file mode 100644
index 0000000000..260e086f69
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Gos-linux.c
@@ -0,0 +1,182 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright 2011 Linaro Limited
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdio.h>
+#include <signal.h>
+#include "unwind_i.h"
+#include "offsets.h"
+
+HIDDEN int
+arm_handle_signal_frame (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+ unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa;
+ struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0);
+
+ if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0)
+ return -UNW_EUNSPEC;
+
+ /* Obtain signal frame type (non-RT or RT). */
+ ret = unw_is_signal_frame (cursor);
+
+ /* Save the SP and PC to be able to return execution at this point
+ later in time (unw_resume). */
+ c->sigcontext_sp = c->dwarf.cfa;
+ c->sigcontext_pc = c->dwarf.ip;
+
+ /* Since kernel version 2.6.18 the non-RT signal frame starts with a
+ ucontext while the RT signal frame starts with a siginfo, followed
+ by a sigframe whose first element is an ucontext.
+ Prior 2.6.18 the non-RT signal frame starts with a sigcontext while
+ the RT signal frame starts with two pointers followed by a siginfo
+ and an ucontext. The first pointer points to the start of the siginfo
+ structure and the second one to the ucontext structure. */
+
+ if (ret == 1)
+ {
+ /* Handle non-RT signal frames. Check if the first word on the stack
+ is the magic number. */
+ if (sp == 0x5ac3c35a)
+ {
+ c->sigcontext_format = ARM_SCF_LINUX_SIGFRAME;
+ sc_addr = sp_addr + LINUX_UC_MCONTEXT_OFF;
+ }
+ else
+ {
+ c->sigcontext_format = ARM_SCF_LINUX_OLD_SIGFRAME;
+ sc_addr = sp_addr;
+ }
+ }
+ else if (ret == 2)
+ {
+ /* Handle RT signal frames. Check if the first word on the stack is a
+ pointer to the siginfo structure. */
+ if (sp == sp_addr + 8)
+ {
+ c->sigcontext_format = ARM_SCF_LINUX_OLD_RT_SIGFRAME;
+ sc_addr = sp_addr + 8 + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF;
+ }
+ else
+ {
+ c->sigcontext_format = ARM_SCF_LINUX_RT_SIGFRAME;
+ sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF;
+ }
+ }
+ else
+ return -UNW_EUNSPEC;
+
+ c->sigcontext_addr = sc_addr;
+ c->frame_info.frame_type = UNW_ARM_FRAME_SIGRETURN;
+ c->frame_info.cfa_reg_offset = sc_addr - sp_addr;
+
+ /* Update the dwarf cursor.
+ Set the location of the registers to the corresponding addresses of the
+ uc_mcontext / sigcontext structure contents. */
+ c->dwarf.loc[UNW_ARM_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0);
+ c->dwarf.loc[UNW_ARM_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0);
+ c->dwarf.loc[UNW_ARM_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0);
+ c->dwarf.loc[UNW_ARM_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0);
+ c->dwarf.loc[UNW_ARM_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0);
+ c->dwarf.loc[UNW_ARM_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0);
+ c->dwarf.loc[UNW_ARM_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0);
+ c->dwarf.loc[UNW_ARM_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0);
+ c->dwarf.loc[UNW_ARM_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0);
+ c->dwarf.loc[UNW_ARM_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0);
+ c->dwarf.loc[UNW_ARM_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0);
+ c->dwarf.loc[UNW_ARM_R11] = DWARF_LOC (sc_addr + LINUX_SC_FP_OFF, 0);
+ c->dwarf.loc[UNW_ARM_R12] = DWARF_LOC (sc_addr + LINUX_SC_IP_OFF, 0);
+ c->dwarf.loc[UNW_ARM_R13] = DWARF_LOC (sc_addr + LINUX_SC_SP_OFF, 0);
+ c->dwarf.loc[UNW_ARM_R14] = DWARF_LOC (sc_addr + LINUX_SC_LR_OFF, 0);
+ c->dwarf.loc[UNW_ARM_R15] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0);
+
+ /* Set SP/CFA and PC/IP. */
+ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R13], &c->dwarf.cfa);
+ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R15], &c->dwarf.ip);
+
+ c->dwarf.pi_valid = 0;
+
+ return 1;
+}
+
+#define ARM_NR_sigreturn 119
+#define ARM_NR_rt_sigreturn 173
+#define ARM_NR_OABI_SYSCALL_BASE 0x900000
+
+/* ARM EABI sigreturn (the syscall number is loaded into r7) */
+#define MOV_R7_SIGRETURN (0xe3a07000UL | ARM_NR_sigreturn)
+#define MOV_R7_RT_SIGRETURN (0xe3a07000UL | ARM_NR_rt_sigreturn)
+
+/* ARM OABI sigreturn (using SWI) */
+#define ARM_SIGRETURN \
+ (0xef000000UL | ARM_NR_sigreturn | ARM_NR_OABI_SYSCALL_BASE)
+#define ARM_RT_SIGRETURN \
+ (0xef000000UL | ARM_NR_rt_sigreturn | ARM_NR_OABI_SYSCALL_BASE)
+
+/* Thumb sigreturn (two insns, syscall number is loaded into r7) */
+#define THUMB_SIGRETURN (0xdf00UL << 16 | 0x2700 | ARM_NR_sigreturn)
+#define THUMB_RT_SIGRETURN (0xdf00UL << 16 | 0x2700 | ARM_NR_rt_sigreturn)
+
+/* Thumb2 sigreturn (mov.w r7, $SYS_ify(rt_sigreturn/sigreturn)) */
+#define THUMB2_SIGRETURN (((0x0700 | ARM_NR_sigreturn) << 16) | \
+ 0xf04f)
+#define THUMB2_RT_SIGRETURN (((0x0700 | ARM_NR_rt_sigreturn) << 16) | \
+ 0xf04f)
+/* TODO: with different toolchains, there are a lot more possibilities */
+
+/* Returns 1 in case of a non-RT signal frame and 2 in case of a RT signal
+ frame. */
+int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ unw_word_t w0, ip;
+ unw_addr_space_t as;
+ unw_accessors_t *a;
+ void *arg;
+ int ret;
+
+ as = c->dwarf.as;
+ a = unw_get_accessors_int (as);
+ arg = c->dwarf.as_arg;
+
+ /* The least bit denotes thumb/arm mode. Do not read there. */
+ ip = c->dwarf.ip & ~0x1;
+
+ if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0)
+ return ret;
+
+ /* Return 1 if the IP points to a non-RT sigreturn sequence. */
+ if (w0 == MOV_R7_SIGRETURN || w0 == ARM_SIGRETURN || w0 == THUMB_SIGRETURN
+ || w0 == THUMB2_SIGRETURN)
+ return 1;
+ /* Return 2 if the IP points to a RT sigreturn sequence. */
+ else if (w0 == MOV_R7_RT_SIGRETURN || w0 == ARM_RT_SIGRETURN
+ || w0 == THUMB_RT_SIGRETURN || w0 == THUMB2_RT_SIGRETURN)
+ return 2;
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/arm/Gos-other.c b/src/pal/src/libunwind/src/arm/Gos-other.c
new file mode 100644
index 0000000000..73c102c3d2
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Gos-other.c
@@ -0,0 +1,48 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright 2011 Linaro Limited
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdio.h>
+#include <signal.h>
+#include "unwind_i.h"
+#include "offsets.h"
+
+HIDDEN int
+arm_handle_signal_frame (unw_cursor_t *cursor)
+{
+ return -UNW_EUNSPEC;
+}
+
+int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+#if defined(__QNX__)
+ /* Not supported yet */
+ return 0;
+#else
+ printf ("%s: implement me\n", __FUNCTION__);
+ return -UNW_ENOINFO;
+#endif
+}
diff --git a/src/pal/src/libunwind/src/arm/Greg_states_iterate.c b/src/pal/src/libunwind/src/arm/Greg_states_iterate.c
new file mode 100644
index 0000000000..a17dc1b561
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Greg_states_iterate.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+ unw_reg_states_callback cb, void *token)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
diff --git a/src/pal/src/libunwind/src/arm/Gregs.c b/src/pal/src/libunwind/src/arm/Gregs.c
new file mode 100644
index 0000000000..0d52f0b222
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Gregs.c
@@ -0,0 +1,83 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+HIDDEN int
+tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
+ int write)
+{
+ dwarf_loc_t loc = DWARF_NULL_LOC;
+
+ switch (reg)
+ {
+ case UNW_ARM_R15:
+ if (write)
+ c->dwarf.ip = *valp; /* update the IP cache */
+ case UNW_ARM_R0:
+ case UNW_ARM_R1:
+ case UNW_ARM_R2:
+ case UNW_ARM_R3:
+ case UNW_ARM_R4:
+ case UNW_ARM_R5:
+ case UNW_ARM_R6:
+ case UNW_ARM_R7:
+ case UNW_ARM_R8:
+ case UNW_ARM_R9:
+ case UNW_ARM_R10:
+ case UNW_ARM_R11:
+ case UNW_ARM_R12:
+ case UNW_ARM_R14:
+ loc = c->dwarf.loc[reg - UNW_ARM_R0];
+ break;
+
+ case UNW_ARM_R13:
+ case UNW_ARM_CFA:
+ if (write)
+ return -UNW_EREADONLYREG;
+ *valp = c->dwarf.cfa;
+ return 0;
+
+ /* FIXME: Initialise coprocessor & shadow registers? */
+
+ default:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+ }
+
+ if (write)
+ return dwarf_put (&c->dwarf, loc, *valp);
+ else
+ return dwarf_get (&c->dwarf, loc, valp);
+}
+
+/* FIXME for ARM. */
+
+HIDDEN int
+tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
+ int write)
+{
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+}
diff --git a/src/pal/src/libunwind/src/arm/Gresume.c b/src/pal/src/libunwind/src/arm/Gresume.c
new file mode 100644
index 0000000000..a8288628a6
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Gresume.c
@@ -0,0 +1,154 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright 2011 Linaro Limited
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "offsets.h"
+
+#ifndef UNW_REMOTE_ONLY
+
+HIDDEN inline int
+arm_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
+{
+#ifdef __linux__
+ struct cursor *c = (struct cursor *) cursor;
+ unw_tdep_context_t *uc = c->dwarf.as_arg;
+
+ if (c->sigcontext_format == ARM_SCF_NONE)
+ {
+ /* Since there are no signals involved here we restore the non scratch
+ registers only. */
+ unsigned long regs[10];
+ regs[0] = uc->regs[4];
+ regs[1] = uc->regs[5];
+ regs[2] = uc->regs[6];
+ regs[3] = uc->regs[7];
+ regs[4] = uc->regs[8];
+ regs[5] = uc->regs[9];
+ regs[6] = uc->regs[10];
+ regs[7] = uc->regs[11]; /* FP */
+ regs[8] = uc->regs[13]; /* SP */
+ regs[9] = uc->regs[14]; /* LR */
+
+ struct regs_overlay {
+ char x[sizeof(regs)];
+ };
+
+ asm __volatile__ (
+ "ldmia %0, {r4-r12, lr}\n"
+ "mov sp, r12\n"
+ "bx lr\n"
+ : : "r" (regs),
+ "m" (*(struct regs_overlay *)regs)
+ );
+ }
+ else
+ {
+ /* In case a signal frame is involved, we're using its trampoline which
+ calls sigreturn. */
+ struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
+ sc->arm_r0 = uc->regs[0];
+ sc->arm_r1 = uc->regs[1];
+ sc->arm_r2 = uc->regs[2];
+ sc->arm_r3 = uc->regs[3];
+ sc->arm_r4 = uc->regs[4];
+ sc->arm_r5 = uc->regs[5];
+ sc->arm_r6 = uc->regs[6];
+ sc->arm_r7 = uc->regs[7];
+ sc->arm_r8 = uc->regs[8];
+ sc->arm_r9 = uc->regs[9];
+ sc->arm_r10 = uc->regs[10];
+ sc->arm_fp = uc->regs[11]; /* FP */
+ sc->arm_ip = uc->regs[12]; /* IP */
+ sc->arm_sp = uc->regs[13]; /* SP */
+ sc->arm_lr = uc->regs[14]; /* LR */
+ sc->arm_pc = uc->regs[15]; /* PC */
+ /* clear the ITSTATE bits. */
+ sc->arm_cpsr &= 0xf9ff03ffUL;
+
+ /* Set the SP and the PC in order to continue execution at the modified
+ trampoline which restores the signal mask and the registers. */
+ asm __volatile__ (
+ "mov sp, %0\n"
+ "bx %1\n"
+ : : "r" (c->sigcontext_sp), "r" (c->sigcontext_pc)
+ );
+ }
+ unreachable();
+#else
+ printf ("%s: implement me\n", __FUNCTION__);
+#endif
+ return -UNW_EINVAL;
+}
+
+#endif /* !UNW_REMOTE_ONLY */
+
+static inline void
+establish_machine_state (struct cursor *c)
+{
+ unw_addr_space_t as = c->dwarf.as;
+ void *arg = c->dwarf.as_arg;
+ unw_fpreg_t fpval;
+ unw_word_t val;
+ int reg;
+
+ Debug (8, "copying out cursor state\n");
+
+ for (reg = 0; reg <= UNW_REG_LAST; ++reg)
+ {
+ Debug (16, "copying %s %d\n", unw_regname (reg), reg);
+ if (unw_is_fpreg (reg))
+ {
+ if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0)
+ as->acc.access_fpreg (as, reg, &fpval, 1, arg);
+ }
+ else
+ {
+ if (tdep_access_reg (c, reg, &val, 0) >= 0)
+ as->acc.access_reg (as, reg, &val, 1, arg);
+ }
+ }
+}
+
+int
+unw_resume (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ if (!c->dwarf.ip)
+ {
+ /* This can happen easily when the frame-chain gets truncated
+ due to bad or missing unwind-info. */
+ Debug (1, "refusing to resume execution at address 0\n");
+ return -UNW_EINVAL;
+ }
+
+ establish_machine_state (c);
+
+ return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c,
+ c->dwarf.as_arg);
+}
diff --git a/src/pal/src/libunwind/src/arm/Gstash_frame.c b/src/pal/src/libunwind/src/arm/Gstash_frame.c
new file mode 100644
index 0000000000..c5a76b86d0
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Gstash_frame.c
@@ -0,0 +1,90 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
+ Copyright (C) 2014 CERN and Aalto University
+ Contributed by Filip Nyback
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+HIDDEN void
+tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs)
+{
+ struct cursor *c = (struct cursor *) dwarf_to_cursor (d);
+ unw_tdep_frame_t *f = &c->frame_info;
+
+ Debug (4, "ip=0x%x cfa=0x%x type %d cfa [where=%d val=%d] cfaoff=%d"
+ " ra=0x%x r7 [where=%d val=%d @0x%x] lr [where=%d val=%d @0x%x] "
+ "sp [where=%d val=%d @0x%x]\n",
+ d->ip, d->cfa, f->frame_type,
+ rs->reg.where[DWARF_CFA_REG_COLUMN],
+ rs->reg.val[DWARF_CFA_REG_COLUMN],
+ rs->reg.val[DWARF_CFA_OFF_COLUMN],
+ DWARF_GET_LOC(d->loc[rs->ret_addr_column]),
+ rs->reg.where[R7], rs->reg.val[R7], DWARF_GET_LOC(d->loc[R7]),
+ rs->reg.where[LR], rs->reg.val[LR], DWARF_GET_LOC(d->loc[LR]),
+ rs->reg.where[SP], rs->reg.val[SP], DWARF_GET_LOC(d->loc[SP]));
+
+ /* A standard frame is defined as:
+ - CFA is register-relative offset off R7 or SP;
+ - Return address is saved in LR;
+ - R7 is unsaved or saved at CFA+offset, offset != -1;
+ - LR is unsaved or saved at CFA+offset, offset != -1;
+ - SP is unsaved or saved at CFA+offset, offset != -1. */
+ if (f->frame_type == UNW_ARM_FRAME_OTHER
+ && (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG)
+ && (rs->reg.val[DWARF_CFA_REG_COLUMN] == R7
+ || rs->reg.val[DWARF_CFA_REG_COLUMN] == SP)
+ && labs(rs->reg.val[DWARF_CFA_OFF_COLUMN]) < (1 << 29)
+ && rs->ret_addr_column == LR
+ && (rs->reg.where[R7] == DWARF_WHERE_UNDEF
+ || rs->reg.where[R7] == DWARF_WHERE_SAME
+ || (rs->reg.where[R7] == DWARF_WHERE_CFAREL
+ && labs(rs->reg.val[R7]) < (1 << 29)
+ && rs->reg.val[R7]+1 != 0))
+ && (rs->reg.where[LR] == DWARF_WHERE_UNDEF
+ || rs->reg.where[LR] == DWARF_WHERE_SAME
+ || (rs->reg.where[LR] == DWARF_WHERE_CFAREL
+ && labs(rs->reg.val[LR]) < (1 << 29)
+ && rs->reg.val[LR]+1 != 0))
+ && (rs->reg.where[SP] == DWARF_WHERE_UNDEF
+ || rs->reg.where[SP] == DWARF_WHERE_SAME
+ || (rs->reg.where[SP] == DWARF_WHERE_CFAREL
+ && labs(rs->reg.val[SP]) < (1 << 29)
+ && rs->reg.val[SP]+1 != 0)))
+ {
+ /* Save information for a standard frame. */
+ f->frame_type = UNW_ARM_FRAME_STANDARD;
+ f->cfa_reg_sp = (rs->reg.val[DWARF_CFA_REG_COLUMN] == SP);
+ f->cfa_reg_offset = rs->reg.val[DWARF_CFA_OFF_COLUMN];
+ if (rs->reg.where[R7] == DWARF_WHERE_CFAREL)
+ f->r7_cfa_offset = rs->reg.val[R7];
+ if (rs->reg.where[LR] == DWARF_WHERE_CFAREL)
+ f->lr_cfa_offset = rs->reg.val[LR];
+ if (rs->reg.where[SP] == DWARF_WHERE_CFAREL)
+ f->sp_cfa_offset = rs->reg.val[SP];
+ Debug (4, " standard frame\n");
+ }
+ else
+ Debug (4, " unusual frame\n");
+}
+
diff --git a/src/pal/src/libunwind/src/arm/Gstep.c b/src/pal/src/libunwind/src/arm/Gstep.c
new file mode 100644
index 0000000000..516c9f4d18
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Gstep.c
@@ -0,0 +1,192 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright 2011 Linaro Limited
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "offsets.h"
+#include "ex_tables.h"
+
+#include <signal.h>
+
+#define arm_exidx_step UNW_OBJ(arm_exidx_step)
+
+static inline int
+arm_exidx_step (struct cursor *c)
+{
+ unw_word_t old_ip, old_cfa;
+ uint8_t buf[32];
+ int ret;
+
+ old_ip = c->dwarf.ip;
+ old_cfa = c->dwarf.cfa;
+
+ /* mark PC unsaved */
+ c->dwarf.loc[UNW_ARM_R15] = DWARF_NULL_LOC;
+ unw_word_t ip = c->dwarf.ip;
+ if (c->dwarf.use_prev_instr)
+ --ip;
+
+ /* check dynamic info first --- it overrides everything else */
+ ret = unwi_find_dynamic_proc_info (c->dwarf.as, ip, &c->dwarf.pi, 1,
+ c->dwarf.as_arg);
+ if (ret == -UNW_ENOINFO)
+ {
+ if ((ret = tdep_find_proc_info (&c->dwarf, ip, 1)) < 0)
+ return ret;
+ }
+
+ if (c->dwarf.pi.format != UNW_INFO_FORMAT_ARM_EXIDX)
+ return -UNW_ENOINFO;
+
+ ret = arm_exidx_extract (&c->dwarf, buf);
+ if (ret == -UNW_ESTOPUNWIND)
+ return 0;
+ else if (ret < 0)
+ return ret;
+
+ ret = arm_exidx_decode (buf, ret, &c->dwarf);
+ if (ret < 0)
+ return ret;
+
+ if (c->dwarf.ip == old_ip && c->dwarf.cfa == old_cfa)
+ {
+ Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
+ __FUNCTION__, (long) c->dwarf.ip);
+ return -UNW_EBADFRAME;
+ }
+
+ c->dwarf.pi_valid = 0;
+
+ return (c->dwarf.ip == 0) ? 0 : 1;
+}
+
+int
+unw_step (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret = -UNW_EUNSPEC;
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ /* Check if this is a signal frame. */
+ if (unw_is_signal_frame (cursor) > 0)
+ return arm_handle_signal_frame (cursor);
+
+#ifdef CONFIG_DEBUG_FRAME
+ /* First, try DWARF-based unwinding. */
+ if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF))
+ {
+ ret = dwarf_step (&c->dwarf);
+ Debug(1, "dwarf_step()=%d\n", ret);
+
+ if (likely (ret > 0))
+ return 1;
+ else if (unlikely (ret == -UNW_ESTOPUNWIND))
+ return ret;
+
+ if (ret < 0 && ret != -UNW_ENOINFO)
+ {
+ Debug (2, "returning %d\n", ret);
+ return ret;
+ }
+ }
+#endif /* CONFIG_DEBUG_FRAME */
+
+ /* Next, try extbl-based unwinding. */
+ if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX))
+ {
+ ret = arm_exidx_step (c);
+ if (ret > 0)
+ return 1;
+ if (ret == -UNW_ESTOPUNWIND || ret == 0)
+ return ret;
+ }
+
+ /* Fall back on APCS frame parsing.
+ Note: This won't work in case the ARM EABI is used. */
+#ifdef __FreeBSD__
+ if (0)
+#else
+ if (unlikely (ret < 0))
+#endif
+ {
+ if (UNW_TRY_METHOD(UNW_ARM_METHOD_FRAME))
+ {
+ Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);
+ ret = UNW_ESUCCESS;
+ /* DWARF unwinding failed, try to follow APCS/optimized APCS frame chain */
+ unw_word_t instr, i;
+ dwarf_loc_t ip_loc, fp_loc;
+ unw_word_t frame;
+ /* Mark all registers unsaved, since we don't know where
+ they are saved (if at all), except for the EBP and
+ EIP. */
+ if (dwarf_get(&c->dwarf, c->dwarf.loc[UNW_ARM_R11], &frame) < 0)
+ {
+ return 0;
+ }
+ for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) {
+ c->dwarf.loc[i] = DWARF_NULL_LOC;
+ }
+ if (frame)
+ {
+ if (dwarf_get(&c->dwarf, DWARF_LOC(frame, 0), &instr) < 0)
+ {
+ return 0;
+ }
+ instr -= 8;
+ if (dwarf_get(&c->dwarf, DWARF_LOC(instr, 0), &instr) < 0)
+ {
+ return 0;
+ }
+ if ((instr & 0xFFFFD800) == 0xE92DD800)
+ {
+ /* Standard APCS frame. */
+ ip_loc = DWARF_LOC(frame - 4, 0);
+ fp_loc = DWARF_LOC(frame - 12, 0);
+ }
+ else
+ {
+ /* Codesourcery optimized normal frame. */
+ ip_loc = DWARF_LOC(frame, 0);
+ fp_loc = DWARF_LOC(frame - 4, 0);
+ }
+ if (dwarf_get(&c->dwarf, ip_loc, &c->dwarf.ip) < 0)
+ {
+ return 0;
+ }
+ c->dwarf.loc[UNW_ARM_R12] = ip_loc;
+ c->dwarf.loc[UNW_ARM_R11] = fp_loc;
+ c->dwarf.pi_valid = 0;
+ Debug(15, "ip=%x\n", c->dwarf.ip);
+ }
+ else
+ {
+ ret = -UNW_ENOINFO;
+ }
+ }
+ }
+ return ret == -UNW_ENOINFO ? 0 : ret;
+}
diff --git a/src/pal/src/libunwind/src/arm/Gtrace.c b/src/pal/src/libunwind/src/arm/Gtrace.c
new file mode 100644
index 0000000000..2f277520b3
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Gtrace.c
@@ -0,0 +1,557 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
+ Copyright (C) 2014 CERN and Aalto University
+ Contributed by Filip Nyback
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "offsets.h"
+#include <signal.h>
+#include <limits.h>
+
+#pragma weak pthread_once
+#pragma weak pthread_key_create
+#pragma weak pthread_getspecific
+#pragma weak pthread_setspecific
+
+/* Initial hash table size. Table expands by 2 bits (times four). */
+#define HASH_MIN_BITS 14
+
+typedef struct
+{
+ unw_tdep_frame_t *frames;
+ size_t log_size;
+ size_t used;
+ size_t dtor_count; /* Counts how many times our destructor has already
+ been called. */
+} unw_trace_cache_t;
+
+static const unw_tdep_frame_t empty_frame = { 0, UNW_ARM_FRAME_OTHER, -1, -1, 0, -1, -1, -1 };
+static define_lock (trace_init_lock);
+static pthread_once_t trace_cache_once = PTHREAD_ONCE_INIT;
+static sig_atomic_t trace_cache_once_happen;
+static pthread_key_t trace_cache_key;
+static struct mempool trace_cache_pool;
+static __thread unw_trace_cache_t *tls_cache;
+static __thread int tls_cache_destroyed;
+
+/* Free memory for a thread's trace cache. */
+static void
+trace_cache_free (void *arg)
+{
+ unw_trace_cache_t *cache = arg;
+ if (++cache->dtor_count < PTHREAD_DESTRUCTOR_ITERATIONS)
+ {
+ /* Not yet our turn to get destroyed. Re-install ourselves into the key. */
+ pthread_setspecific(trace_cache_key, cache);
+ Debug(5, "delayed freeing cache %p (%zx to go)\n", cache,
+ PTHREAD_DESTRUCTOR_ITERATIONS - cache->dtor_count);
+ return;
+ }
+ tls_cache_destroyed = 1;
+ tls_cache = NULL;
+ munmap (cache->frames, (1u << cache->log_size) * sizeof(unw_tdep_frame_t));
+ mempool_free (&trace_cache_pool, cache);
+ Debug(5, "freed cache %p\n", cache);
+}
+
+/* Initialise frame tracing for threaded use. */
+static void
+trace_cache_init_once (void)
+{
+ pthread_key_create (&trace_cache_key, &trace_cache_free);
+ mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0);
+ trace_cache_once_happen = 1;
+}
+
+static unw_tdep_frame_t *
+trace_cache_buckets (size_t n)
+{
+ unw_tdep_frame_t *frames;
+ size_t i;
+
+ GET_MEMORY(frames, n * sizeof (unw_tdep_frame_t));
+ if (likely(frames != NULL))
+ for (i = 0; i < n; ++i)
+ frames[i] = empty_frame;
+
+ return frames;
+}
+
+/* Allocate and initialise hash table for frame cache lookups.
+ Returns the cache initialised with (1u << HASH_LOW_BITS) hash
+ buckets, or NULL if there was a memory allocation problem. */
+static unw_trace_cache_t *
+trace_cache_create (void)
+{
+ unw_trace_cache_t *cache;
+
+ if (tls_cache_destroyed)
+ {
+ /* The current thread is in the process of exiting. Don't recreate
+ cache, as we wouldn't have another chance to free it. */
+ Debug(5, "refusing to reallocate cache: "
+ "thread-locals are being deallocated\n");
+ return NULL;
+ }
+
+ if (! (cache = mempool_alloc(&trace_cache_pool)))
+ {
+ Debug(5, "failed to allocate cache\n");
+ return NULL;
+ }
+
+ if (! (cache->frames = trace_cache_buckets(1u << HASH_MIN_BITS)))
+ {
+ Debug(5, "failed to allocate buckets\n");
+ mempool_free(&trace_cache_pool, cache);
+ return NULL;
+ }
+
+ cache->log_size = HASH_MIN_BITS;
+ cache->used = 0;
+ cache->dtor_count = 0;
+ tls_cache_destroyed = 0; /* Paranoia: should already be 0. */
+ Debug(5, "allocated cache %p\n", cache);
+ return cache;
+}
+
+/* Expand the hash table in the frame cache if possible. This always
+ quadruples the hash size, and clears all previous frame entries. */
+static int
+trace_cache_expand (unw_trace_cache_t *cache)
+{
+ size_t old_size = (1u << cache->log_size);
+ size_t new_log_size = cache->log_size + 2;
+ unw_tdep_frame_t *new_frames = trace_cache_buckets (1u << new_log_size);
+
+ if (unlikely(! new_frames))
+ {
+ Debug(5, "failed to expand cache to 2^%u buckets\n", new_log_size);
+ return -UNW_ENOMEM;
+ }
+
+ Debug(5, "expanded cache from 2^%u to 2^%u buckets\n", cache->log_size,
+ new_log_size);
+ munmap(cache->frames, old_size * sizeof(unw_tdep_frame_t));
+ cache->frames = new_frames;
+ cache->log_size = new_log_size;
+ cache->used = 0;
+ return 0;
+}
+
+static unw_trace_cache_t *
+trace_cache_get_unthreaded (void)
+{
+ unw_trace_cache_t *cache;
+ intrmask_t saved_mask;
+ static unw_trace_cache_t *global_cache = NULL;
+ lock_acquire (&trace_init_lock, saved_mask);
+ if (! global_cache)
+ {
+ mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0);
+ global_cache = trace_cache_create ();
+ }
+ cache = global_cache;
+ lock_release (&trace_init_lock, saved_mask);
+ Debug(5, "using cache %p\n", cache);
+ return cache;
+}
+
+/* Get the frame cache for the current thread. Create it if there is none. */
+static unw_trace_cache_t *
+trace_cache_get (void)
+{
+ unw_trace_cache_t *cache;
+ if (likely (pthread_once != NULL))
+ {
+ pthread_once(&trace_cache_once, &trace_cache_init_once);
+ if (!trace_cache_once_happen)
+ {
+ return trace_cache_get_unthreaded();
+ }
+ if (! (cache = tls_cache))
+ {
+ cache = trace_cache_create();
+ pthread_setspecific(trace_cache_key, cache);
+ tls_cache = cache;
+ }
+ Debug(5, "using cache %p\n", cache);
+ return cache;
+ }
+ else
+ {
+ return trace_cache_get_unthreaded();
+ }
+}
+
+/* Initialise frame properties for address cache slot F at address
+ PC using current CFA, R7 and SP values. Modifies CURSOR to
+ that location, performs one unw_step(), and fills F with what
+ was discovered about the location. Returns F.
+
+ FIXME: This probably should tell DWARF handling to never evaluate
+ or use registers other than R7, SP and PC in case there is
+ highly unusual unwind info which uses these creatively. */
+static unw_tdep_frame_t *
+trace_init_addr (unw_tdep_frame_t *f,
+ unw_cursor_t *cursor,
+ unw_word_t cfa,
+ unw_word_t pc,
+ unw_word_t r7,
+ unw_word_t sp)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ struct dwarf_cursor *d = &c->dwarf;
+ int ret = -UNW_EINVAL;
+
+ /* Initialise frame properties: unknown, not last. */
+ f->virtual_address = pc;
+ f->frame_type = UNW_ARM_FRAME_OTHER;
+ f->last_frame = 0;
+ f->cfa_reg_sp = -1;
+ f->cfa_reg_offset = 0;
+ f->r7_cfa_offset = -1;
+ f->lr_cfa_offset = -1;
+ f->sp_cfa_offset = -1;
+
+ /* Reinitialise cursor to this instruction - but undo next/prev RIP
+ adjustment because unw_step will redo it - and force PC, R7 and
+ SP into register locations (=~ ucontext we keep), then set
+ their desired values. Then perform the step. */
+ d->ip = pc + d->use_prev_instr;
+ d->cfa = cfa;
+ d->loc[UNW_ARM_R7] = DWARF_REG_LOC (d, UNW_ARM_R7);
+ d->loc[UNW_ARM_R13] = DWARF_REG_LOC (d, UNW_ARM_R13);
+ d->loc[UNW_ARM_R15] = DWARF_REG_LOC (d, UNW_ARM_R15);
+ c->frame_info = *f;
+
+ if (likely(dwarf_put (d, d->loc[UNW_ARM_R7], r7) >= 0)
+ && likely(dwarf_put (d, d->loc[UNW_ARM_R13], sp) >= 0)
+ && likely(dwarf_put (d, d->loc[UNW_ARM_R15], pc) >= 0)
+ && likely((ret = unw_step (cursor)) >= 0))
+ *f = c->frame_info;
+
+ /* If unw_step() stopped voluntarily, remember that, even if it
+ otherwise could not determine anything useful. This avoids
+ failing trace if we hit frames without unwind info, which is
+ common for the outermost frame (CRT stuff) on many systems.
+ This avoids failing trace in very common circumstances; failing
+ to unw_step() loop wouldn't produce any better result. */
+ if (ret == 0)
+ f->last_frame = -1;
+
+ Debug (3, "frame va %x type %d last %d cfa %s+%d r7 @ cfa%+d lr @ cfa%+d sp @ cfa%+d\n",
+ f->virtual_address, f->frame_type, f->last_frame,
+ f->cfa_reg_sp ? "sp" : "r7", f->cfa_reg_offset,
+ f->r7_cfa_offset, f->lr_cfa_offset, f->sp_cfa_offset);
+
+ return f;
+}
+
+/* Look up and if necessary fill in frame attributes for address PC
+ in CACHE using current CFA, R7 and SP values. Uses CURSOR to
+ perform any unwind steps necessary to fill the cache. Returns the
+ frame cache slot which describes RIP. */
+static unw_tdep_frame_t *
+trace_lookup (unw_cursor_t *cursor,
+ unw_trace_cache_t *cache,
+ unw_word_t cfa,
+ unw_word_t pc,
+ unw_word_t r7,
+ unw_word_t sp)
+{
+ /* First look up for previously cached information using cache as
+ linear probing hash table with probe step of 1. Majority of
+ lookups should be completed within few steps, but it is very
+ important the hash table does not fill up, or performance falls
+ off the cliff. */
+ uint32_t i, addr;
+ uint32_t cache_size = 1u << cache->log_size;
+ uint32_t slot = ((pc * 0x9e3779b9) >> 11) & (cache_size-1);
+ unw_tdep_frame_t *frame;
+
+ for (i = 0; i < 16; ++i)
+ {
+ frame = &cache->frames[slot];
+ addr = frame->virtual_address;
+
+ /* Return if we found the address. */
+ if (likely(addr == pc))
+ {
+ Debug (4, "found address after %d steps\n", i);
+ return frame;
+ }
+
+ /* If slot is empty, reuse it. */
+ if (likely(! addr))
+ break;
+
+ /* Linear probe to next slot candidate, step = 1. */
+ if (++slot >= cache_size)
+ slot -= cache_size;
+ }
+
+ /* If we collided after 16 steps, or if the hash is more than half
+ full, force the hash to expand. Fill the selected slot, whether
+ it's free or collides. Note that hash expansion drops previous
+ contents; further lookups will refill the hash. */
+ Debug (4, "updating slot %u after %d steps, replacing 0x%x\n", slot, i, addr);
+ if (unlikely(addr || cache->used >= cache_size / 2))
+ {
+ if (unlikely(trace_cache_expand (cache) < 0))
+ return NULL;
+
+ cache_size = 1u << cache->log_size;
+ slot = ((pc * 0x9e3779b9) >> 11) & (cache_size-1);
+ frame = &cache->frames[slot];
+ addr = frame->virtual_address;
+ }
+
+ if (! addr)
+ ++cache->used;
+
+ return trace_init_addr (frame, cursor, cfa, pc, r7, sp);
+}
+
+/* Fast stack backtrace for ARM.
+
+ This is used by backtrace() implementation to accelerate frequent
+ queries for current stack, without any desire to unwind. It fills
+ BUFFER with the call tree from CURSOR upwards for at most SIZE
+ stack levels. The first frame, backtrace itself, is omitted. When
+ called, SIZE should give the maximum number of entries that can be
+ stored into BUFFER. Uses an internal thread-specific cache to
+ accelerate queries.
+
+ The caller should fall back to a unw_step() loop if this function
+ fails by returning -UNW_ESTOPUNWIND, meaning the routine hit a
+ stack frame that is too complex to be traced in the fast path.
+
+ This function is tuned for clients which only need to walk the
+ stack to get the call tree as fast as possible but without any
+ other details, for example profilers sampling the stack thousands
+ to millions of times per second. The routine handles the most
+ common ARM ABI stack layouts: CFA is R7 or SP plus/minus
+ constant offset, return address is in LR, and R7, LR and SP are
+ either unchanged or saved on stack at constant offset from the CFA;
+ the signal return frame; and frames without unwind info provided
+ they are at the outermost (final) frame or can conservatively be
+ assumed to be frame-pointer based.
+
+ Any other stack layout will cause the routine to give up. There
+ are only a handful of relatively rarely used functions which do
+ not have a stack in the standard form: vfork, longjmp, setcontext
+ and _dl_runtime_profile on common linux systems for example.
+
+ On success BUFFER and *SIZE reflect the trace progress up to *SIZE
+ stack levels or the outermost frame, which ever is less. It may
+ stop short of outermost frame if unw_step() loop would also do so,
+ e.g. if there is no more unwind information; this is not reported
+ as an error.
+
+ The function returns a negative value for errors, -UNW_ESTOPUNWIND
+ if tracing stopped because of an unusual frame unwind info. The
+ BUFFER and *SIZE reflect tracing progress up to the error frame.
+
+ Callers of this function would normally look like this:
+
+ unw_cursor_t cur;
+ unw_context_t ctx;
+ void addrs[128];
+ int depth = 128;
+ int ret;
+
+ unw_getcontext(&ctx);
+ unw_init_local(&cur, &ctx);
+ if ((ret = unw_tdep_trace(&cur, addrs, &depth)) < 0)
+ {
+ depth = 0;
+ unw_getcontext(&ctx);
+ unw_init_local(&cur, &ctx);
+ while ((ret = unw_step(&cur)) > 0 && depth < 128)
+ {
+ unw_word_t ip;
+ unw_get_reg(&cur, UNW_REG_IP, &ip);
+ addresses[depth++] = (void *) ip;
+ }
+ }
+*/
+HIDDEN int
+tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ struct dwarf_cursor *d = &c->dwarf;
+ unw_trace_cache_t *cache;
+ unw_word_t sp, pc, cfa, r7, lr;
+ int maxdepth = 0;
+ int depth = 0;
+ int ret;
+
+ /* Check input parametres. */
+ if (unlikely(! cursor || ! buffer || ! size || (maxdepth = *size) <= 0))
+ return -UNW_EINVAL;
+
+ Debug (1, "begin ip 0x%x cfa 0x%x\n", d->ip, d->cfa);
+
+ /* Tell core dwarf routines to call back to us. */
+ d->stash_frames = 1;
+
+ /* Determine initial register values. These are direct access safe
+ because we know they come from the initial machine context. */
+ pc = d->ip;
+ sp = cfa = d->cfa;
+ ACCESS_MEM_FAST(ret, 0, d, DWARF_GET_LOC(d->loc[UNW_ARM_R7]), r7);
+ assert(ret == 0);
+ lr = 0;
+
+ /* Get frame cache. */
+ if (unlikely(! (cache = trace_cache_get())))
+ {
+ Debug (1, "returning %d, cannot get trace cache\n", -UNW_ENOMEM);
+ *size = 0;
+ d->stash_frames = 0;
+ return -UNW_ENOMEM;
+ }
+
+ /* Trace the stack upwards, starting from current PC. Adjust
+ the PC address for previous/next instruction as the main
+ unwinding logic would also do. We undo this before calling
+ back into unw_step(). */
+ while (depth < maxdepth)
+ {
+ pc -= d->use_prev_instr;
+ Debug (2, "depth %d cfa 0x%x pc 0x%x sp 0x%x r7 0x%x\n",
+ depth, cfa, pc, sp, r7);
+
+ /* See if we have this address cached. If not, evaluate enough of
+ the dwarf unwind information to fill the cache line data, or to
+ decide this frame cannot be handled in fast trace mode. We
+ cache negative results too to prevent unnecessary dwarf parsing
+ for common failures. */
+ unw_tdep_frame_t *f = trace_lookup (cursor, cache, cfa, pc, r7, sp);
+
+ /* If we don't have information for this frame, give up. */
+ if (unlikely(! f))
+ {
+ ret = -UNW_ENOINFO;
+ break;
+ }
+
+ Debug (3, "frame va %x type %d last %d cfa %s+%d r7 @ cfa%+d lr @ cfa%+d sp @ cfa%+d\n",
+ f->virtual_address, f->frame_type, f->last_frame,
+ f->cfa_reg_sp ? "sp" : "r7", f->cfa_reg_offset,
+ f->r7_cfa_offset, f->lr_cfa_offset, f->sp_cfa_offset);
+
+ assert (f->virtual_address == pc);
+
+ /* Stop if this was the last frame. In particular don't evaluate
+ new register values as it may not be safe - we don't normally
+ run with full validation on, and do not want to - and there's
+ enough bad unwind info floating around that we need to trust
+ what unw_step() previously said, in potentially bogus frames. */
+ if (f->last_frame)
+ break;
+
+ /* Evaluate CFA and registers for the next frame. */
+ switch (f->frame_type)
+ {
+ case UNW_ARM_FRAME_GUESSED:
+ /* Fall thru to standard processing after forcing validation. */
+ c->validate = 1;
+
+ case UNW_ARM_FRAME_STANDARD:
+ /* Advance standard traceable frame. */
+ cfa = (f->cfa_reg_sp ? sp : r7) + f->cfa_reg_offset;
+ if (likely(f->lr_cfa_offset != -1))
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->lr_cfa_offset, pc);
+ else if (lr != 0)
+ {
+ /* Use the saved link register as the new pc. */
+ pc = lr;
+ lr = 0;
+ }
+ if (likely(ret >= 0) && likely(f->r7_cfa_offset != -1))
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->r7_cfa_offset, r7);
+
+ /* Don't bother reading SP from DWARF, CFA becomes new SP. */
+ sp = cfa;
+
+ /* Next frame needs to back up for unwind info lookup. */
+ d->use_prev_instr = 1;
+ break;
+
+ case UNW_ARM_FRAME_SIGRETURN:
+ cfa = cfa + f->cfa_reg_offset; /* cfa now points to ucontext_t. */
+#if defined(__linux__)
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_PC_OFF, pc);
+ if (likely(ret >= 0))
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_R7_OFF, r7);
+ if (likely(ret >= 0))
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_SP_OFF, sp);
+ /* Save the link register here in case we end up in a function that
+ doesn't save the link register in the prologue, e.g. kill. */
+ if (likely(ret >= 0))
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_LR_OFF, lr);
+#elif defined(__FreeBSD__)
+ printf("XXX\n");
+#endif
+
+ /* Resume stack at signal restoration point. The stack is not
+ necessarily continuous here, especially with sigaltstack(). */
+ cfa = sp;
+
+ /* Next frame should not back up. */
+ d->use_prev_instr = 0;
+ break;
+
+ case UNW_ARM_FRAME_SYSCALL:
+ printf("XXX1\n");
+ break;
+
+ default:
+ /* We cannot trace through this frame, give up and tell the
+ caller we had to stop. Data collected so far may still be
+ useful to the caller, so let it know how far we got. */
+ ret = -UNW_ESTOPUNWIND;
+ break;
+ }
+
+ Debug (4, "new cfa 0x%x pc 0x%x sp 0x%x r7 0x%x\n",
+ cfa, pc, sp, r7);
+
+ /* If we failed or ended up somewhere bogus, stop. */
+ if (unlikely(ret < 0 || pc < 0x4000))
+ break;
+
+ /* Record this address in stack trace. We skipped the first address. */
+ buffer[depth++] = (void *) (pc - d->use_prev_instr);
+ }
+
+#if UNW_DEBUG
+ Debug (1, "returning %d, depth %d\n", ret, depth);
+#endif
+ *size = depth;
+ return ret;
+}
+
diff --git a/src/pal/src/libunwind/src/arm/Lapply_reg_state.c b/src/pal/src/libunwind/src/arm/Lapply_reg_state.c
new file mode 100644
index 0000000000..7ebada480e
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Lapply_reg_state.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/pal/src/libunwind/src/arm/Lcreate_addr_space.c b/src/pal/src/libunwind/src/arm/Lcreate_addr_space.c
new file mode 100644
index 0000000000..0f2dc6be90
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Lcreate_addr_space.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gcreate_addr_space.c"
+#endif
diff --git a/src/pal/src/libunwind/src/arm/Lex_tables.c b/src/pal/src/libunwind/src/arm/Lex_tables.c
new file mode 100644
index 0000000000..4a4f925c9c
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Lex_tables.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gex_tables.c"
+#endif
diff --git a/src/pal/src/libunwind/src/arm/Lget_proc_info.c b/src/pal/src/libunwind/src/arm/Lget_proc_info.c
new file mode 100644
index 0000000000..69028b019f
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Lget_proc_info.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_proc_info.c"
+#endif
diff --git a/src/pal/src/libunwind/src/arm/Lget_save_loc.c b/src/pal/src/libunwind/src/arm/Lget_save_loc.c
new file mode 100644
index 0000000000..9ea048a907
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Lget_save_loc.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_save_loc.c"
+#endif
diff --git a/src/pal/src/libunwind/src/arm/Lglobal.c b/src/pal/src/libunwind/src/arm/Lglobal.c
new file mode 100644
index 0000000000..6d7b489e14
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Lglobal.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gglobal.c"
+#endif
diff --git a/src/pal/src/libunwind/src/arm/Linit.c b/src/pal/src/libunwind/src/arm/Linit.c
new file mode 100644
index 0000000000..e9abfdd46a
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Linit.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit.c"
+#endif
diff --git a/src/pal/src/libunwind/src/arm/Linit_local.c b/src/pal/src/libunwind/src/arm/Linit_local.c
new file mode 100644
index 0000000000..68a1687e85
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Linit_local.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_local.c"
+#endif
diff --git a/src/pal/src/libunwind/src/arm/Linit_remote.c b/src/pal/src/libunwind/src/arm/Linit_remote.c
new file mode 100644
index 0000000000..58cb04ab7c
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Linit_remote.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_remote.c"
+#endif
diff --git a/src/pal/src/libunwind/src/arm/Lis_signal_frame.c b/src/pal/src/libunwind/src/arm/Lis_signal_frame.c
new file mode 100644
index 0000000000..b9a7c4f51a
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Lis_signal_frame.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gis_signal_frame.c"
+#endif
diff --git a/src/pal/src/libunwind/src/arm/Los-freebsd.c b/src/pal/src/libunwind/src/arm/Los-freebsd.c
new file mode 100644
index 0000000000..a75a205df1
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Los-freebsd.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gos-freebsd.c"
+#endif
diff --git a/src/pal/src/libunwind/src/arm/Los-linux.c b/src/pal/src/libunwind/src/arm/Los-linux.c
new file mode 100644
index 0000000000..3cc18aabcc
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Los-linux.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gos-linux.c"
+#endif
diff --git a/src/pal/src/libunwind/src/arm/Los-other.c b/src/pal/src/libunwind/src/arm/Los-other.c
new file mode 100644
index 0000000000..a75a205df1
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Los-other.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gos-freebsd.c"
+#endif
diff --git a/src/pal/src/libunwind/src/arm/Lreg_states_iterate.c b/src/pal/src/libunwind/src/arm/Lreg_states_iterate.c
new file mode 100644
index 0000000000..f1eb1e79dc
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Lreg_states_iterate.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
diff --git a/src/pal/src/libunwind/src/arm/Lregs.c b/src/pal/src/libunwind/src/arm/Lregs.c
new file mode 100644
index 0000000000..2c9c75cd7d
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Lregs.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gregs.c"
+#endif
diff --git a/src/pal/src/libunwind/src/arm/Lresume.c b/src/pal/src/libunwind/src/arm/Lresume.c
new file mode 100644
index 0000000000..41a8cf003d
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Lresume.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gresume.c"
+#endif
diff --git a/src/pal/src/libunwind/src/arm/Lstash_frame.c b/src/pal/src/libunwind/src/arm/Lstash_frame.c
new file mode 100644
index 0000000000..77587803d0
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Lstash_frame.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gstash_frame.c"
+#endif
diff --git a/src/pal/src/libunwind/src/arm/Lstep.c b/src/pal/src/libunwind/src/arm/Lstep.c
new file mode 100644
index 0000000000..c1ac3c7547
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Lstep.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gstep.c"
+#endif
diff --git a/src/pal/src/libunwind/src/arm/Ltrace.c b/src/pal/src/libunwind/src/arm/Ltrace.c
new file mode 100644
index 0000000000..24b7b3cfa6
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/Ltrace.c
@@ -0,0 +1,6 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gtrace.c"
+#endif
+
diff --git a/src/pal/src/libunwind/src/arm/gen-offsets.c b/src/pal/src/libunwind/src/arm/gen-offsets.c
new file mode 100644
index 0000000000..7d6bf2f1c5
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/gen-offsets.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+#include <stddef.h>
+#include <ucontext.h>
+#include <asm/sigcontext.h>
+
+#define UC(N,X) \
+ printf ("#define LINUX_UC_" N "_OFF\t0x%X\n", offsetof (ucontext_t, X))
+
+#define SC(N,X) \
+ printf ("#define LINUX_SC_" N "_OFF\t0x%X\n", offsetof (struct sigcontext, X))
+
+int
+main (void)
+{
+ printf (
+"/* Linux-specific definitions: */\n\n"
+
+"/* Define various structure offsets to simplify cross-compilation. */\n\n"
+
+"/* Offsets for ARM Linux \"ucontext_t\": */\n\n");
+
+ UC ("FLAGS", uc_flags);
+ UC ("LINK", uc_link);
+ UC ("STACK", uc_stack);
+ UC ("MCONTEXT", uc_mcontext);
+ UC ("SIGMASK", uc_sigmask);
+ UC ("REGSPACE", uc_regspace);
+
+ printf ("\n/* Offsets for ARM Linux \"struct sigcontext\": */\n\n");
+
+ SC ("TRAPNO", trap_no);
+ SC ("ERRORCODE", error_code);
+ SC ("OLDMASK", oldmask);
+ SC ("R0", arm_r0);
+ SC ("R1", arm_r1);
+ SC ("R2", arm_r2);
+ SC ("R3", arm_r3);
+ SC ("R4", arm_r4);
+ SC ("R5", arm_r5);
+ SC ("R6", arm_r6);
+ SC ("R7", arm_r7);
+ SC ("R8", arm_r8);
+ SC ("R9", arm_r9);
+ SC ("R10", arm_r10);
+ SC ("FP", arm_fp);
+ SC ("IP", arm_ip);
+ SC ("SP", arm_sp);
+ SC ("LR", arm_lr);
+ SC ("PC", arm_pc);
+ SC ("CPSR", arm_cpsr);
+ SC ("FAULTADDR", fault_address);
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/arm/getcontext.S b/src/pal/src/libunwind/src/arm/getcontext.S
new file mode 100644
index 0000000000..7e18784477
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/getcontext.S
@@ -0,0 +1,63 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "offsets.h"
+
+ .text
+ .arm
+
+ .global _Uarm_getcontext
+ .type _Uarm_getcontext, %function
+ @ This is a stub version of getcontext() for ARM which only stores core
+ @ registers. It must be called in a special way, not as a regular
+ @ function -- see also the libunwind-arm.h:unw_tdep_getcontext macro.
+_Uarm_getcontext:
+ stmfd sp!, {r0, r1}
+ @ store r0
+#if defined(__linux__)
+ str r0, [r0, #LINUX_UC_MCONTEXT_OFF + LINUX_SC_R0_OFF]
+ add r0, r0, #LINUX_UC_MCONTEXT_OFF + LINUX_SC_R0_OFF
+#elif defined(__FreeBSD__)
+ str r0, [r0, #FREEBSD_UC_MCONTEXT_OFF + FREEBSD_MC_R0_OFF]
+ add r0, r0, #FREEBSD_UC_MCONTEXT_OFF + FREEBSD_MC_R0_OFF
+#else
+#error Fix me
+#endif
+ @ store r1 to r12
+ stmib r0, {r1-r12}
+ @ reconstruct r13 at call site, then store
+ add r1, sp, #12
+ str r1, [r0, #13 * 4]
+ @ retrieve r14 from call site, then store
+ ldr r1, [sp, #8]
+ str r1, [r0, #14 * 4]
+ @ point lr to instruction after call site's stack adjustment
+ add r1, lr, #4
+ str r1, [r0, #15 * 4]
+ ldmfd sp!, {r0, r1}
+ bx lr
+#if defined(__linux__) || defined(__FreeBSD__)
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",%progbits
+#endif
diff --git a/src/pal/src/libunwind/src/arm/init.h b/src/pal/src/libunwind/src/arm/init.h
new file mode 100644
index 0000000000..7d765ecf09
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/init.h
@@ -0,0 +1,77 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+static inline int
+common_init (struct cursor *c, unsigned use_prev_instr)
+{
+ int ret, i;
+
+ c->dwarf.loc[UNW_ARM_R0] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R0);
+ c->dwarf.loc[UNW_ARM_R1] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R1);
+ c->dwarf.loc[UNW_ARM_R2] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R2);
+ c->dwarf.loc[UNW_ARM_R3] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R3);
+ c->dwarf.loc[UNW_ARM_R4] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R4);
+ c->dwarf.loc[UNW_ARM_R5] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R5);
+ c->dwarf.loc[UNW_ARM_R6] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R6);
+ c->dwarf.loc[UNW_ARM_R7] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R7);
+ c->dwarf.loc[UNW_ARM_R8] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R8);
+ c->dwarf.loc[UNW_ARM_R9] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R9);
+ c->dwarf.loc[UNW_ARM_R10] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R10);
+ c->dwarf.loc[UNW_ARM_R11] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R11);
+ c->dwarf.loc[UNW_ARM_R12] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R12);
+ c->dwarf.loc[UNW_ARM_R13] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R13);
+ c->dwarf.loc[UNW_ARM_R14] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R14);
+ c->dwarf.loc[UNW_ARM_R15] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R15);
+ for (i = UNW_ARM_R15 + 1; i < DWARF_NUM_PRESERVED_REGS; ++i)
+ c->dwarf.loc[i] = DWARF_NULL_LOC;
+
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R15], &c->dwarf.ip);
+ if (ret < 0)
+ return ret;
+
+ /* FIXME: correct for ARM? */
+ ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_ARM_R13),
+ &c->dwarf.cfa);
+ if (ret < 0)
+ return ret;
+
+ c->sigcontext_format = ARM_SCF_NONE;
+ c->sigcontext_addr = 0;
+ c->sigcontext_sp = 0;
+ c->sigcontext_pc = 0;
+
+ /* FIXME: Initialisation for other registers. */
+
+ c->dwarf.args_size = 0;
+ c->dwarf.stash_frames = 0;
+ c->dwarf.use_prev_instr = use_prev_instr;
+ c->dwarf.pi_valid = 0;
+ c->dwarf.pi_is_dynamic = 0;
+ c->dwarf.hint = 0;
+ c->dwarf.prev_rs = 0;
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/arm/is_fpreg.c b/src/pal/src/libunwind/src/arm/is_fpreg.c
new file mode 100644
index 0000000000..e55bcff03e
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/is_fpreg.c
@@ -0,0 +1,39 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+/* FIXME: I'm not sure if libunwind's GP/FP register distinction is very useful
+ on ARM. Count all the FP or coprocessor registers we know about for now. */
+
+int
+unw_is_fpreg (int regnum)
+{
+ return ((regnum >= UNW_ARM_S0 && regnum <= UNW_ARM_S31)
+ || (regnum >= UNW_ARM_F0 && regnum <= UNW_ARM_F7)
+ || (regnum >= UNW_ARM_wCGR0 && regnum <= UNW_ARM_wCGR7)
+ || (regnum >= UNW_ARM_wR0 && regnum <= UNW_ARM_wR15)
+ || (regnum >= UNW_ARM_wC0 && regnum <= UNW_ARM_wC7)
+ || (regnum >= UNW_ARM_D0 && regnum <= UNW_ARM_D31));
+}
diff --git a/src/pal/src/libunwind/src/arm/offsets.h b/src/pal/src/libunwind/src/arm/offsets.h
new file mode 100644
index 0000000000..621701106c
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/offsets.h
@@ -0,0 +1,42 @@
+/* Linux-specific definitions: */
+
+/* Define various structure offsets to simplify cross-compilation. */
+
+/* Offsets for ARM Linux "ucontext_t": */
+
+#define LINUX_UC_FLAGS_OFF 0x00
+#define LINUX_UC_LINK_OFF 0x04
+#define LINUX_UC_STACK_OFF 0x08
+#define LINUX_UC_MCONTEXT_OFF 0x14
+#define LINUX_UC_SIGMASK_OFF 0x68
+#define LINUX_UC_REGSPACE_OFF 0xE8
+
+/* Offsets for ARM Linux "struct sigcontext": */
+
+#define LINUX_SC_TRAPNO_OFF 0x00
+#define LINUX_SC_ERRORCODE_OFF 0x04
+#define LINUX_SC_OLDMASK_OFF 0x08
+#define LINUX_SC_R0_OFF 0x0C
+#define LINUX_SC_R1_OFF 0x10
+#define LINUX_SC_R2_OFF 0x14
+#define LINUX_SC_R3_OFF 0x18
+#define LINUX_SC_R4_OFF 0x1C
+#define LINUX_SC_R5_OFF 0x20
+#define LINUX_SC_R6_OFF 0x24
+#define LINUX_SC_R7_OFF 0x28
+#define LINUX_SC_R8_OFF 0x2C
+#define LINUX_SC_R9_OFF 0x30
+#define LINUX_SC_R10_OFF 0x34
+#define LINUX_SC_FP_OFF 0x38
+#define LINUX_SC_IP_OFF 0x3C
+#define LINUX_SC_SP_OFF 0x40
+#define LINUX_SC_LR_OFF 0x44
+#define LINUX_SC_PC_OFF 0x48
+#define LINUX_SC_CPSR_OFF 0x4C
+#define LINUX_SC_FAULTADDR_OFF 0x50
+
+/* FreeBSD-specific definitions: */
+
+#define FREEBSD_SC_UCONTEXT_OFF 0x40
+#define FREEBSD_UC_MCONTEXT_OFF 0x10
+#define FREEBSD_MC_R0_OFF 0
diff --git a/src/pal/src/libunwind/src/arm/regname.c b/src/pal/src/libunwind/src/arm/regname.c
new file mode 100644
index 0000000000..7cac630c17
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/regname.c
@@ -0,0 +1,90 @@
+#include "unwind_i.h"
+
+static const char *regname[] =
+ {
+ /* 0. */
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ /* 8. */
+ "r8", "r9", "r10", "fp", "ip", "sp", "lr", "pc",
+ /* 16. Obsolete FPA names. */
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ /* 24. */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 32. */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 40. */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 48. */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 56. */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 64. */
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+ /* 72. */
+ "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
+ /* 80. */
+ "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
+ /* 88. */
+ "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
+ /* 96. */
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ /* 104. */
+ "wCGR0", "wCGR1", "wCGR2", "wCGR3", "wCGR4", "wCGR5", "wCGR6", "wCGR7",
+ /* 112. */
+ "wR0", "wR1", "wR2", "wR3", "wR4", "wR5", "wR6", "wR7",
+ /* 128. */
+ "spsr", "spsr_fiq", "spsr_irq", "spsr_abt", "spsr_und", "spsr_svc", 0, 0,
+ /* 136. */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 144. */
+ "r8_usr", "r9_usr", "r10_usr", "r11_usr", "r12_usr", "r13_usr", "r14_usr",
+ /* 151. */
+ "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "r14_fiq",
+ /* 158. */
+ "r13_irq", "r14_irq",
+ /* 160. */
+ "r13_abt", "r14_abt",
+ /* 162. */
+ "r13_und", "r14_und",
+ /* 164. */
+ "r13_svc", "r14_svc", 0, 0,
+ /* 168. */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 176. */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 184. */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 192. */
+ "wC0", "wC1", "wC2", "wC3", "wC4", "wC5", "wC6", "wC7",
+ /* 200. */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 208. */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 216. */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 224. */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 232. */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 240. */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 248. */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 256. */
+ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+ /* 264. */
+ "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
+ /* 272. */
+ "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
+ /* 280. */
+ "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
+ };
+
+const char *
+unw_regname (unw_regnum_t reg)
+{
+ if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
+ return regname[reg];
+ else
+ return "???";
+}
diff --git a/src/pal/src/libunwind/src/arm/siglongjmp.S b/src/pal/src/libunwind/src/arm/siglongjmp.S
new file mode 100644
index 0000000000..4df0736683
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/siglongjmp.S
@@ -0,0 +1,12 @@
+ /* Dummy implementation for now. */
+
+ .globl _UI_siglongjmp_cont
+ .globl _UI_longjmp_cont
+
+_UI_siglongjmp_cont:
+_UI_longjmp_cont:
+ bx lr
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",%progbits
+#endif
diff --git a/src/pal/src/libunwind/src/arm/unwind_i.h b/src/pal/src/libunwind/src/arm/unwind_i.h
new file mode 100644
index 0000000000..fe0bca005b
--- /dev/null
+++ b/src/pal/src/libunwind/src/arm/unwind_i.h
@@ -0,0 +1,62 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef unwind_i_h
+#define unwind_i_h
+
+#include <stdint.h>
+
+#include <libunwind-arm.h>
+
+#include "libunwind_i.h"
+
+/* DWARF column numbers for ARM: */
+#define R7 7
+#define SP 13
+#define LR 14
+#define PC 15
+
+#define arm_lock UNW_OBJ(lock)
+#define arm_local_resume UNW_OBJ(local_resume)
+#define arm_local_addr_space_init UNW_OBJ(local_addr_space_init)
+
+extern void arm_local_addr_space_init (void);
+extern int arm_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
+ void *arg);
+#define arm_handle_signal_frame UNW_OBJ(handle_signal_frame)
+extern int arm_handle_signal_frame(unw_cursor_t *cursor);
+
+/* By-pass calls to access_mem() when known to be safe. */
+#ifdef UNW_LOCAL_ONLY
+# undef ACCESS_MEM_FAST
+# define ACCESS_MEM_FAST(ret,validate,cur,addr,to) \
+ do { \
+ if (unlikely(validate)) \
+ (ret) = dwarf_get ((cur), DWARF_MEM_LOC ((cur), (addr)), &(to)); \
+ else \
+ (ret) = 0, (to) = *(unw_word_t *)(addr); \
+ } while (0)
+#endif
+
+#endif /* unwind_i_h */
diff --git a/src/pal/src/libunwind/src/config.h.in b/src/pal/src/libunwind/src/config.h.in
new file mode 100644
index 0000000000..5e3421b4a9
--- /dev/null
+++ b/src/pal/src/libunwind/src/config.h.in
@@ -0,0 +1,16 @@
+#ifndef __LIBUNWIND_CONFIG_H__
+#define __LIBUNWIND_CONFIG_H__
+
+#cmakedefine HAVE_ELF_H
+#cmakedefine HAVE_SYS_ELF_H
+
+#cmakedefine HAVE_ENDIAN_H
+#cmakedefine HAVE_SYS_ENDIAN_H
+
+#cmakedefine HAVE_LINK_H
+#cmakedefine HAVE_SYS_LINK_H
+
+#cmakedefine HAVE__BUILTIN_UNREACHABLE
+#cmakedefine HAVE_SYNC_ATOMICS
+
+#endif
diff --git a/src/pal/src/libunwind/src/configure.cmake b/src/pal/src/libunwind/src/configure.cmake
new file mode 100644
index 0000000000..3e45405e70
--- /dev/null
+++ b/src/pal/src/libunwind/src/configure.cmake
@@ -0,0 +1,31 @@
+include(CheckCXXSourceCompiles)
+include(CheckIncludeFiles)
+
+check_include_files(elf.h HAVE_ELF_H)
+check_include_files(sys/elf.h HAVE_SYS_ELF_H)
+
+check_include_files(endian.h HAVE_ENDIAN_H)
+check_include_files(sys/endian.h HAVE_SYS_ENDIAN_H)
+
+check_include_files(link.h HAVE_LINK_H)
+check_include_files(sys/link.h HAVE_SYS_LINK_H)
+
+check_cxx_source_compiles("
+int main(int argc, char **argv)
+{
+ __sync_bool_compare_and_swap((int *)0, 0, 1);
+ __sync_fetch_and_add((int *)0, 1);
+
+ return 0;
+}" HAVE_SYNC_ATOMICS)
+
+
+check_cxx_source_compiles("
+int main(int argc, char **argv)
+{
+ __builtin_unreachable();
+
+ return 0;
+}" HAVE__BUILTIN_UNREACHABLE)
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
diff --git a/src/pal/src/libunwind/src/coredump/README b/src/pal/src/libunwind/src/coredump/README
new file mode 100644
index 0000000000..204493c93e
--- /dev/null
+++ b/src/pal/src/libunwind/src/coredump/README
@@ -0,0 +1,8 @@
+This code is based on "unwinding via ptrace" code from ptrace/
+directory.
+
+Files with names starting with _UCD_ are substantially changed
+from their ptrace/_UPT_... progenitors.
+
+Files which still have _UPT_... names are either verbiatim copies
+from ptrace/, or unimplemented stubs.
diff --git a/src/pal/src/libunwind/src/coredump/_UCD_access_mem.c b/src/pal/src/libunwind/src/coredump/_UCD_access_mem.c
new file mode 100644
index 0000000000..1fdbd128ff
--- /dev/null
+++ b/src/pal/src/libunwind/src/coredump/_UCD_access_mem.c
@@ -0,0 +1,98 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UCD_lib.h"
+#include "_UCD_internal.h"
+
+int
+_UCD_access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
+ int write, void *arg)
+{
+ if (write)
+ {
+ Debug(0, "write is not supported\n");
+ return -UNW_EINVAL;
+ }
+
+ struct UCD_info *ui = arg;
+
+ unw_word_t addr_last = addr + sizeof(*val)-1;
+ coredump_phdr_t *phdr;
+ unsigned i;
+ for (i = 0; i < ui->phdrs_count; i++)
+ {
+ phdr = &ui->phdrs[i];
+ if (phdr->p_vaddr <= addr && addr_last < phdr->p_vaddr + phdr->p_memsz)
+ {
+ goto found;
+ }
+ }
+ Debug(1, "addr 0x%llx is unmapped\n", (unsigned long long)addr);
+ return -UNW_EINVAL;
+
+ found: ;
+
+ const char *filename UNUSED;
+ off_t fileofs;
+ int fd;
+ if (addr_last >= phdr->p_vaddr + phdr->p_filesz)
+ {
+ /* This part of mapped address space is not present in coredump file */
+ /* Do we have it in the backup file? */
+ if (phdr->backing_fd < 0)
+ {
+ Debug(1, "access to not-present data in phdr[%d]: addr:0x%llx\n",
+ i, (unsigned long long)addr
+ );
+ return -UNW_EINVAL;
+ }
+ filename = phdr->backing_filename;
+ fileofs = addr - phdr->p_vaddr;
+ fd = phdr->backing_fd;
+ goto read;
+ }
+
+ filename = ui->coredump_filename;
+ fileofs = phdr->p_offset + (addr - phdr->p_vaddr);
+ fd = ui->coredump_fd;
+ read:
+ if (lseek(fd, fileofs, SEEK_SET) != fileofs)
+ goto read_error;
+ if (read(fd, val, sizeof(*val)) != sizeof(*val))
+ goto read_error;
+
+ Debug(1, "0x%llx <- [addr:0x%llx fileofs:0x%llx]\n",
+ (unsigned long long)(*val),
+ (unsigned long long)addr,
+ (unsigned long long)fileofs
+ );
+ return 0;
+
+ read_error:
+ Debug(1, "access out of file: addr:0x%llx fileofs:%llx file:'%s'\n",
+ (unsigned long long)addr,
+ (unsigned long long)fileofs,
+ filename
+ );
+ return -UNW_EINVAL;
+}
diff --git a/src/pal/src/libunwind/src/coredump/_UCD_access_reg_freebsd.c b/src/pal/src/libunwind/src/coredump/_UCD_access_reg_freebsd.c
new file mode 100644
index 0000000000..0e3a83bdc6
--- /dev/null
+++ b/src/pal/src/libunwind/src/coredump/_UCD_access_reg_freebsd.c
@@ -0,0 +1,137 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UCD_lib.h"
+
+#include "_UCD_internal.h"
+
+int
+_UCD_access_reg (unw_addr_space_t as,
+ unw_regnum_t regnum, unw_word_t *valp,
+ int write, void *arg)
+{
+ if (write)
+ {
+ Debug(0, "write is not supported\n");
+ return -UNW_EINVAL;
+ }
+
+ struct UCD_info *ui = arg;
+
+#if defined(UNW_TARGET_X86)
+ switch (regnum) {
+ case UNW_X86_EAX:
+ *valp = ui->prstatus->pr_reg.r_eax;
+ break;
+ case UNW_X86_EDX:
+ *valp = ui->prstatus->pr_reg.r_edx;
+ break;
+ case UNW_X86_ECX:
+ *valp = ui->prstatus->pr_reg.r_ecx;
+ break;
+ case UNW_X86_EBX:
+ *valp = ui->prstatus->pr_reg.r_ebx;
+ break;
+ case UNW_X86_ESI:
+ *valp = ui->prstatus->pr_reg.r_esi;
+ break;
+ case UNW_X86_EDI:
+ *valp = ui->prstatus->pr_reg.r_edi;
+ break;
+ case UNW_X86_EBP:
+ *valp = ui->prstatus->pr_reg.r_ebp;
+ break;
+ case UNW_X86_ESP:
+ *valp = ui->prstatus->pr_reg.r_esp;
+ break;
+ case UNW_X86_EIP:
+ *valp = ui->prstatus->pr_reg.r_eip;
+ break;
+ case UNW_X86_EFLAGS:
+ *valp = ui->prstatus->pr_reg.r_eflags;
+ break;
+ case UNW_X86_TRAPNO:
+ *valp = ui->prstatus->pr_reg.r_trapno;
+ break;
+ default:
+ Debug(0, "bad regnum:%d\n", regnum);
+ return -UNW_EINVAL;
+ }
+#elif defined(UNW_TARGET_X86_64)
+ switch (regnum) {
+ case UNW_X86_64_RAX:
+ *valp = ui->prstatus->pr_reg.r_rax;
+ break;
+ case UNW_X86_64_RDX:
+ *valp = ui->prstatus->pr_reg.r_rdx;
+ break;
+ case UNW_X86_64_RCX:
+ *valp = ui->prstatus->pr_reg.r_rcx;
+ break;
+ case UNW_X86_64_RBX:
+ *valp = ui->prstatus->pr_reg.r_rbx;
+ break;
+ case UNW_X86_64_RSI:
+ *valp = ui->prstatus->pr_reg.r_rsi;
+ break;
+ case UNW_X86_64_RDI:
+ *valp = ui->prstatus->pr_reg.r_rdi;
+ break;
+ case UNW_X86_64_RBP:
+ *valp = ui->prstatus->pr_reg.r_rbp;
+ break;
+ case UNW_X86_64_RSP:
+ *valp = ui->prstatus->pr_reg.r_rsp;
+ break;
+ case UNW_X86_64_RIP:
+ *valp = ui->prstatus->pr_reg.r_rip;
+ break;
+ default:
+ Debug(0, "bad regnum:%d\n", regnum);
+ return -UNW_EINVAL;
+ }
+#elif defined(UNW_TARGET_ARM)
+ if (regnum >= UNW_ARM_R0 && regnum <= UNW_ARM_R12) {
+ *valp = ui->prstatus->pr_reg.r[regnum];
+ } else {
+ switch (regnum) {
+ case UNW_ARM_R13:
+ *valp = ui->prstatus->pr_reg.r_sp;
+ break;
+ case UNW_ARM_R14:
+ *valp = ui->prstatus->pr_reg.r_lr;
+ break;
+ case UNW_ARM_R15:
+ *valp = ui->prstatus->pr_reg.r_pc;
+ break;
+ default:
+ Debug(0, "bad regnum:%d\n", regnum);
+ return -UNW_EINVAL;
+ }
+ }
+#else
+#error Port me
+#endif
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/coredump/_UCD_access_reg_linux.c b/src/pal/src/libunwind/src/coredump/_UCD_access_reg_linux.c
new file mode 100644
index 0000000000..208d8d27b6
--- /dev/null
+++ b/src/pal/src/libunwind/src/coredump/_UCD_access_reg_linux.c
@@ -0,0 +1,146 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UCD_lib.h"
+
+#include "_UCD_internal.h"
+
+int
+_UCD_access_reg (unw_addr_space_t as,
+ unw_regnum_t regnum, unw_word_t *valp,
+ int write, void *arg)
+{
+ struct UCD_info *ui = arg;
+
+ if (write)
+ {
+ Debug(0, "write is not supported\n");
+ return -UNW_EINVAL;
+ }
+
+ if (regnum < 0)
+ goto badreg;
+
+#if defined(UNW_TARGET_AARCH64)
+ if (regnum >= UNW_AARCH64_FPCR)
+ goto badreg;
+#elif defined(UNW_TARGET_ARM)
+ if (regnum >= 16)
+ goto badreg;
+#elif defined(UNW_TARGET_SH)
+ if (regnum > UNW_SH_PR)
+ goto badreg;
+#elif defined(UNW_TARGET_TILEGX)
+ if (regnum > UNW_TILEGX_CFA)
+ goto badreg;
+#else
+#if defined(UNW_TARGET_MIPS)
+ static const uint8_t remap_regs[] =
+ {
+ [UNW_MIPS_R0] = EF_REG0,
+ [UNW_MIPS_R1] = EF_REG1,
+ [UNW_MIPS_R2] = EF_REG2,
+ [UNW_MIPS_R3] = EF_REG3,
+ [UNW_MIPS_R4] = EF_REG4,
+ [UNW_MIPS_R5] = EF_REG5,
+ [UNW_MIPS_R6] = EF_REG6,
+ [UNW_MIPS_R7] = EF_REG7,
+ [UNW_MIPS_R8] = EF_REG8,
+ [UNW_MIPS_R9] = EF_REG9,
+ [UNW_MIPS_R10] = EF_REG10,
+ [UNW_MIPS_R11] = EF_REG11,
+ [UNW_MIPS_R12] = EF_REG12,
+ [UNW_MIPS_R13] = EF_REG13,
+ [UNW_MIPS_R14] = EF_REG14,
+ [UNW_MIPS_R15] = EF_REG15,
+ [UNW_MIPS_R16] = EF_REG16,
+ [UNW_MIPS_R17] = EF_REG17,
+ [UNW_MIPS_R18] = EF_REG18,
+ [UNW_MIPS_R19] = EF_REG19,
+ [UNW_MIPS_R20] = EF_REG20,
+ [UNW_MIPS_R21] = EF_REG21,
+ [UNW_MIPS_R22] = EF_REG22,
+ [UNW_MIPS_R23] = EF_REG23,
+ [UNW_MIPS_R24] = EF_REG24,
+ [UNW_MIPS_R25] = EF_REG25,
+ [UNW_MIPS_R28] = EF_REG28,
+ [UNW_MIPS_R29] = EF_REG29,
+ [UNW_MIPS_R30] = EF_REG30,
+ [UNW_MIPS_R31] = EF_REG31,
+ [UNW_MIPS_PC] = EF_CP0_EPC,
+ };
+#elif defined(UNW_TARGET_X86)
+ static const uint8_t remap_regs[] =
+ {
+ /* names from libunwind-x86.h */
+ [UNW_X86_EAX] = offsetof(struct user_regs_struct, eax) / sizeof(long),
+ [UNW_X86_EDX] = offsetof(struct user_regs_struct, edx) / sizeof(long),
+ [UNW_X86_ECX] = offsetof(struct user_regs_struct, ecx) / sizeof(long),
+ [UNW_X86_EBX] = offsetof(struct user_regs_struct, ebx) / sizeof(long),
+ [UNW_X86_ESI] = offsetof(struct user_regs_struct, esi) / sizeof(long),
+ [UNW_X86_EDI] = offsetof(struct user_regs_struct, edi) / sizeof(long),
+ [UNW_X86_EBP] = offsetof(struct user_regs_struct, ebp) / sizeof(long),
+ [UNW_X86_ESP] = offsetof(struct user_regs_struct, esp) / sizeof(long),
+ [UNW_X86_EIP] = offsetof(struct user_regs_struct, eip) / sizeof(long),
+ [UNW_X86_EFLAGS] = offsetof(struct user_regs_struct, eflags) / sizeof(long),
+ [UNW_X86_TRAPNO] = offsetof(struct user_regs_struct, orig_eax) / sizeof(long),
+ };
+#elif defined(UNW_TARGET_X86_64)
+ static const int8_t remap_regs[] =
+ {
+ [UNW_X86_64_RAX] = offsetof(struct user_regs_struct, rax) / sizeof(long),
+ [UNW_X86_64_RDX] = offsetof(struct user_regs_struct, rdx) / sizeof(long),
+ [UNW_X86_64_RCX] = offsetof(struct user_regs_struct, rcx) / sizeof(long),
+ [UNW_X86_64_RBX] = offsetof(struct user_regs_struct, rbx) / sizeof(long),
+ [UNW_X86_64_RSI] = offsetof(struct user_regs_struct, rsi) / sizeof(long),
+ [UNW_X86_64_RDI] = offsetof(struct user_regs_struct, rdi) / sizeof(long),
+ [UNW_X86_64_RBP] = offsetof(struct user_regs_struct, rbp) / sizeof(long),
+ [UNW_X86_64_RSP] = offsetof(struct user_regs_struct, rsp) / sizeof(long),
+ [UNW_X86_64_RIP] = offsetof(struct user_regs_struct, rip) / sizeof(long),
+ };
+#else
+#error Port me
+#endif
+
+ if (regnum >= (unw_regnum_t)ARRAY_SIZE(remap_regs))
+ goto badreg;
+
+ regnum = remap_regs[regnum];
+#endif
+
+ /* pr_reg is a long[] array, but it contains struct user_regs_struct's
+ * image.
+ */
+ Debug(1, "pr_reg[%d]:%ld (0x%lx)\n", regnum,
+ (long)ui->prstatus->pr_reg[regnum],
+ (long)ui->prstatus->pr_reg[regnum]
+ );
+ *valp = ui->prstatus->pr_reg[regnum];
+
+ return 0;
+
+badreg:
+ Debug(0, "bad regnum:%d\n", regnum);
+ return -UNW_EINVAL;
+}
diff --git a/src/pal/src/libunwind/src/coredump/_UCD_accessors.c b/src/pal/src/libunwind/src/coredump/_UCD_accessors.c
new file mode 100644
index 0000000000..ae5c23d219
--- /dev/null
+++ b/src/pal/src/libunwind/src/coredump/_UCD_accessors.c
@@ -0,0 +1,36 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UCD_internal.h"
+
+unw_accessors_t _UCD_accessors =
+ {
+ .find_proc_info = _UCD_find_proc_info,
+ .put_unwind_info = _UCD_put_unwind_info,
+ .get_dyn_info_list_addr = _UCD_get_dyn_info_list_addr,
+ .access_mem = _UCD_access_mem,
+ .access_reg = _UCD_access_reg,
+ .access_fpreg = _UCD_access_fpreg,
+ .resume = _UCD_resume,
+ .get_proc_name = _UCD_get_proc_name
+ };
diff --git a/src/pal/src/libunwind/src/coredump/_UCD_create.c b/src/pal/src/libunwind/src/coredump/_UCD_create.c
new file mode 100644
index 0000000000..62f6ee05c7
--- /dev/null
+++ b/src/pal/src/libunwind/src/coredump/_UCD_create.c
@@ -0,0 +1,417 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/* Endian detection */
+#include <limits.h>
+#if defined(HAVE_BYTESWAP_H)
+#include <byteswap.h>
+#endif
+#if defined(HAVE_ENDIAN_H)
+# include <endian.h>
+#elif defined(HAVE_SYS_ENDIAN_H)
+# include <sys/endian.h>
+#endif
+#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN
+# define WE_ARE_BIG_ENDIAN 1
+# define WE_ARE_LITTLE_ENDIAN 0
+#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
+# define WE_ARE_BIG_ENDIAN 0
+# define WE_ARE_LITTLE_ENDIAN 1
+#elif defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN
+# define WE_ARE_BIG_ENDIAN 1
+# define WE_ARE_LITTLE_ENDIAN 0
+#elif defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN
+# define WE_ARE_BIG_ENDIAN 0
+# define WE_ARE_LITTLE_ENDIAN 1
+#elif defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN
+# define WE_ARE_BIG_ENDIAN 1
+# define WE_ARE_LITTLE_ENDIAN 0
+#elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN
+# define WE_ARE_BIG_ENDIAN 0
+# define WE_ARE_LITTLE_ENDIAN 1
+#elif defined(__386__)
+# define WE_ARE_BIG_ENDIAN 0
+# define WE_ARE_LITTLE_ENDIAN 1
+#else
+# error "Can't determine endianness"
+#endif
+
+#include <elf.h>
+#include <sys/procfs.h> /* struct elf_prstatus */
+
+#include "_UCD_lib.h"
+#include "_UCD_internal.h"
+
+#define NOTE_DATA(_hdr) STRUCT_MEMBER_P((_hdr), sizeof (Elf32_Nhdr) + UNW_ALIGN((_hdr)->n_namesz, 4))
+#define NOTE_SIZE(_hdr) (sizeof (Elf32_Nhdr) + UNW_ALIGN((_hdr)->n_namesz, 4) + UNW_ALIGN((_hdr)->n_descsz, 4))
+#define NOTE_NEXT(_hdr) STRUCT_MEMBER_P((_hdr), NOTE_SIZE(_hdr))
+#define NOTE_FITS_IN(_hdr, _size) ((_size) >= sizeof (Elf32_Nhdr) && (_size) >= NOTE_SIZE (_hdr))
+#define NOTE_FITS(_hdr, _end) NOTE_FITS_IN((_hdr), (unsigned long)((char *)(_end) - (char *)(_hdr)))
+
+struct UCD_info *
+_UCD_create(const char *filename)
+{
+ union
+ {
+ Elf32_Ehdr h32;
+ Elf64_Ehdr h64;
+ } elf_header;
+#define elf_header32 elf_header.h32
+#define elf_header64 elf_header.h64
+ bool _64bits;
+
+ struct UCD_info *ui = memset(malloc(sizeof(*ui)), 0, sizeof(*ui));
+ ui->edi.di_cache.format = -1;
+ ui->edi.di_debug.format = -1;
+#if UNW_TARGET_IA64
+ ui->edi.ktab.format = -1;
+#endif
+
+ int fd = ui->coredump_fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ goto err;
+ ui->coredump_filename = strdup(filename);
+
+ /* No sane ELF32 file is going to be smaller then ELF64 _header_,
+ * so let's just read 64-bit sized one.
+ */
+ if (read(fd, &elf_header64, sizeof(elf_header64)) != sizeof(elf_header64))
+ {
+ Debug(0, "'%s' is not an ELF file\n", filename);
+ goto err;
+ }
+
+ if (memcmp(&elf_header32, ELFMAG, SELFMAG) != 0)
+ {
+ Debug(0, "'%s' is not an ELF file\n", filename);
+ goto err;
+ }
+
+ if (elf_header32.e_ident[EI_CLASS] != ELFCLASS32
+ && elf_header32.e_ident[EI_CLASS] != ELFCLASS64)
+ {
+ Debug(0, "'%s' is not a 32/64 bit ELF file\n", filename);
+ goto err;
+ }
+
+ if (WE_ARE_LITTLE_ENDIAN != (elf_header32.e_ident[EI_DATA] == ELFDATA2LSB))
+ {
+ Debug(0, "'%s' is endian-incompatible\n", filename);
+ goto err;
+ }
+
+ _64bits = (elf_header32.e_ident[EI_CLASS] == ELFCLASS64);
+ if (_64bits && sizeof(elf_header64.e_entry) > sizeof(off_t))
+ {
+ Debug(0, "Can't process '%s': 64-bit file "
+ "while only %ld bits are supported",
+ filename, 8L * sizeof(off_t));
+ goto err;
+ }
+
+ /* paranoia check */
+ if (_64bits
+ ? 0 /* todo: (elf_header64.e_ehsize != NN || elf_header64.e_phentsize != NN) */
+ : (elf_header32.e_ehsize != 52 || elf_header32.e_phentsize != 32)
+ )
+ {
+ Debug(0, "'%s' has wrong e_ehsize or e_phentsize\n", filename);
+ goto err;
+ }
+
+ off_t ofs = (_64bits ? elf_header64.e_phoff : elf_header32.e_phoff);
+ if (lseek(fd, ofs, SEEK_SET) != ofs)
+ {
+ Debug(0, "Can't read phdrs from '%s'\n", filename);
+ goto err;
+ }
+ unsigned size = ui->phdrs_count = (_64bits ? elf_header64.e_phnum : elf_header32.e_phnum);
+ coredump_phdr_t *phdrs = ui->phdrs = memset(malloc(size * sizeof(phdrs[0])), 0, size * sizeof(phdrs[0]));
+ if (_64bits)
+ {
+ coredump_phdr_t *cur = phdrs;
+ unsigned i = 0;
+ while (i < size)
+ {
+ Elf64_Phdr hdr64;
+ if (read(fd, &hdr64, sizeof(hdr64)) != sizeof(hdr64))
+ {
+ Debug(0, "Can't read phdrs from '%s'\n", filename);
+ goto err;
+ }
+ cur->p_type = hdr64.p_type ;
+ cur->p_flags = hdr64.p_flags ;
+ cur->p_offset = hdr64.p_offset;
+ cur->p_vaddr = hdr64.p_vaddr ;
+ /*cur->p_paddr = hdr32.p_paddr ; always 0 */
+//TODO: check that and abort if it isn't?
+ cur->p_filesz = hdr64.p_filesz;
+ cur->p_memsz = hdr64.p_memsz ;
+ cur->p_align = hdr64.p_align ;
+ /* cur->backing_filename = NULL; - done by memset */
+ cur->backing_fd = -1;
+ cur->backing_filesize = hdr64.p_filesz;
+ i++;
+ cur++;
+ }
+ } else {
+ coredump_phdr_t *cur = phdrs;
+ unsigned i = 0;
+ while (i < size)
+ {
+ Elf32_Phdr hdr32;
+ if (read(fd, &hdr32, sizeof(hdr32)) != sizeof(hdr32))
+ {
+ Debug(0, "Can't read phdrs from '%s'\n", filename);
+ goto err;
+ }
+ cur->p_type = hdr32.p_type ;
+ cur->p_flags = hdr32.p_flags ;
+ cur->p_offset = hdr32.p_offset;
+ cur->p_vaddr = hdr32.p_vaddr ;
+ /*cur->p_paddr = hdr32.p_paddr ; always 0 */
+ cur->p_filesz = hdr32.p_filesz;
+ cur->p_memsz = hdr32.p_memsz ;
+ cur->p_align = hdr32.p_align ;
+ /* cur->backing_filename = NULL; - done by memset */
+ cur->backing_fd = -1;
+ cur->backing_filesize = hdr32.p_memsz;
+ i++;
+ cur++;
+ }
+ }
+
+ unsigned i = 0;
+ coredump_phdr_t *cur = phdrs;
+ while (i < size)
+ {
+ Debug(2, "phdr[%03d]: type:%d", i, cur->p_type);
+ if (cur->p_type == PT_NOTE)
+ {
+ Elf32_Nhdr *note_hdr, *note_end;
+ unsigned n_threads;
+
+ ui->note_phdr = malloc(cur->p_filesz);
+ if (lseek(fd, cur->p_offset, SEEK_SET) != (off_t)cur->p_offset
+ || (uoff_t)read(fd, ui->note_phdr, cur->p_filesz) != cur->p_filesz)
+ {
+ Debug(0, "Can't read PT_NOTE from '%s'\n", filename);
+ goto err;
+ }
+
+ note_end = STRUCT_MEMBER_P (ui->note_phdr, cur->p_filesz);
+
+ /* Count number of threads */
+ n_threads = 0;
+ note_hdr = (Elf32_Nhdr *)ui->note_phdr;
+ while (NOTE_FITS (note_hdr, note_end))
+ {
+ if (note_hdr->n_type == NT_PRSTATUS)
+ n_threads++;
+
+ note_hdr = NOTE_NEXT (note_hdr);
+ }
+
+ ui->n_threads = n_threads;
+ ui->threads = malloc(sizeof (void *) * n_threads);
+
+ n_threads = 0;
+ note_hdr = (Elf32_Nhdr *)ui->note_phdr;
+ while (NOTE_FITS (note_hdr, note_end))
+ {
+ if (note_hdr->n_type == NT_PRSTATUS)
+ ui->threads[n_threads++] = NOTE_DATA (note_hdr);
+
+ note_hdr = NOTE_NEXT (note_hdr);
+ }
+ }
+ if (cur->p_type == PT_LOAD)
+ {
+ Debug(2, " ofs:%08llx va:%08llx filesize:%08llx memsize:%08llx flg:%x",
+ (unsigned long long) cur->p_offset,
+ (unsigned long long) cur->p_vaddr,
+ (unsigned long long) cur->p_filesz,
+ (unsigned long long) cur->p_memsz,
+ cur->p_flags
+ );
+ if (cur->p_filesz < cur->p_memsz)
+ Debug(2, " partial");
+ if (cur->p_flags & PF_X)
+ Debug(2, " executable");
+ }
+ Debug(2, "\n");
+ i++;
+ cur++;
+ }
+
+ if (ui->n_threads == 0)
+ {
+ Debug(0, "No NT_PRSTATUS note found in '%s'\n", filename);
+ goto err;
+ }
+
+ ui->prstatus = ui->threads[0];
+
+ return ui;
+
+ err:
+ _UCD_destroy(ui);
+ return NULL;
+}
+
+int _UCD_get_num_threads(struct UCD_info *ui)
+{
+ return ui->n_threads;
+}
+
+void _UCD_select_thread(struct UCD_info *ui, int n)
+{
+ if (n >= 0 && n < ui->n_threads)
+ ui->prstatus = ui->threads[n];
+}
+
+pid_t _UCD_get_pid(struct UCD_info *ui)
+{
+ return ui->prstatus->pr_pid;
+}
+
+int _UCD_get_cursig(struct UCD_info *ui)
+{
+ return ui->prstatus->pr_cursig;
+}
+
+int _UCD_add_backing_file_at_segment(struct UCD_info *ui, int phdr_no, const char *filename)
+{
+ if ((unsigned)phdr_no >= ui->phdrs_count)
+ {
+ Debug(0, "There is no segment %d in this coredump\n", phdr_no);
+ return -1;
+ }
+
+ struct coredump_phdr *phdr = &ui->phdrs[phdr_no];
+ if (phdr->backing_filename)
+ {
+ Debug(0, "Backing file already added to segment %d\n", phdr_no);
+ return -1;
+ }
+
+ int fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ {
+ Debug(0, "Can't open '%s'\n", filename);
+ return -1;
+ }
+
+ phdr->backing_fd = fd;
+ phdr->backing_filename = strdup(filename);
+
+ struct stat statbuf;
+ if (fstat(fd, &statbuf) != 0)
+ {
+ Debug(0, "Can't stat '%s'\n", filename);
+ goto err;
+ }
+ phdr->backing_filesize = (uoff_t)statbuf.st_size;
+
+ if (phdr->p_flags != (PF_X | PF_R))
+ Debug(1, "Note: phdr[%u] is not r-x: flags are 0x%x\n", phdr_no, phdr->p_flags);
+
+ if (phdr->backing_filesize > phdr->p_memsz)
+ {
+ /* This is expected */
+ Debug(2, "Note: phdr[%u] is %lld bytes, file is larger: %lld bytes\n",
+ phdr_no,
+ (unsigned long long)phdr->p_memsz,
+ (unsigned long long)phdr->backing_filesize
+ );
+ }
+//TODO: else loudly complain? Maybe even fail?
+
+ if (phdr->p_filesz != 0)
+ {
+//TODO: loop and compare in smaller blocks
+ char *core_buf = malloc(phdr->p_filesz);
+ char *file_buf = malloc(phdr->p_filesz);
+ if (lseek(ui->coredump_fd, phdr->p_offset, SEEK_SET) != (off_t)phdr->p_offset
+ || (uoff_t)read(ui->coredump_fd, core_buf, phdr->p_filesz) != phdr->p_filesz
+ )
+ {
+ Debug(0, "Error reading from coredump file\n");
+ err_read:
+ free(core_buf);
+ free(file_buf);
+ goto err;
+ }
+ if ((uoff_t)read(fd, file_buf, phdr->p_filesz) != phdr->p_filesz)
+ {
+ Debug(0, "Error reading from '%s'\n", filename);
+ goto err_read;
+ }
+ int r = memcmp(core_buf, file_buf, phdr->p_filesz);
+ free(core_buf);
+ free(file_buf);
+ if (r != 0)
+ {
+ Debug(1, "Note: phdr[%u] first %lld bytes in core dump and in file do not match\n",
+ phdr_no, (unsigned long long)phdr->p_filesz
+ );
+ } else {
+ Debug(1, "Note: phdr[%u] first %lld bytes in core dump and in file match\n",
+ phdr_no, (unsigned long long)phdr->p_filesz
+ );
+ }
+ }
+
+ /* Success */
+ return 0;
+
+ err:
+ if (phdr->backing_fd >= 0)
+ {
+ close(phdr->backing_fd);
+ phdr->backing_fd = -1;
+ }
+ free(phdr->backing_filename);
+ phdr->backing_filename = NULL;
+ return -1;
+}
+
+int _UCD_add_backing_file_at_vaddr(struct UCD_info *ui,
+ unsigned long vaddr,
+ const char *filename)
+{
+ unsigned i;
+ for (i = 0; i < ui->phdrs_count; i++)
+ {
+ struct coredump_phdr *phdr = &ui->phdrs[i];
+ if (phdr->p_vaddr != vaddr)
+ continue;
+ /* It seems to match. Add it. */
+ return _UCD_add_backing_file_at_segment(ui, i, filename);
+ }
+ return -1;
+}
diff --git a/src/pal/src/libunwind/src/coredump/_UCD_destroy.c b/src/pal/src/libunwind/src/coredump/_UCD_destroy.c
new file mode 100644
index 0000000000..ddc36ec898
--- /dev/null
+++ b/src/pal/src/libunwind/src/coredump/_UCD_destroy.c
@@ -0,0 +1,52 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UCD_internal.h"
+
+void
+_UCD_destroy (struct UCD_info *ui)
+{
+ if (!ui)
+ return;
+
+ if (ui->coredump_fd >= 0)
+ close(ui->coredump_fd);
+ free(ui->coredump_filename);
+
+ invalidate_edi (&ui->edi);
+
+ unsigned i;
+ for (i = 0; i < ui->phdrs_count; i++)
+ {
+ struct coredump_phdr *phdr = &ui->phdrs[i];
+ free(phdr->backing_filename);
+ if (phdr->backing_fd >= 0)
+ close(phdr->backing_fd);
+ }
+
+ free(ui->phdrs);
+ free(ui->note_phdr);
+ free(ui->threads);
+
+ free(ui);
+}
diff --git a/src/pal/src/libunwind/src/coredump/_UCD_elf_map_image.c b/src/pal/src/libunwind/src/coredump/_UCD_elf_map_image.c
new file mode 100644
index 0000000000..4b3db0bbff
--- /dev/null
+++ b/src/pal/src/libunwind/src/coredump/_UCD_elf_map_image.c
@@ -0,0 +1,98 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <elf.h>
+
+#include "_UCD_lib.h"
+#include "_UCD_internal.h"
+
+static coredump_phdr_t *
+CD_elf_map_image(struct UCD_info *ui, coredump_phdr_t *phdr)
+{
+ struct elf_image *ei = &ui->edi.ei;
+
+ if (phdr->backing_fd < 0)
+ {
+ /* Note: coredump file contains only phdr->p_filesz bytes.
+ * We want to map bigger area (phdr->p_memsz bytes) to make sure
+ * these pages are allocated, but non-accessible.
+ */
+ /* addr, length, prot, flags, fd, fd_offset */
+ ei->image = mmap(NULL, phdr->p_memsz, PROT_READ, MAP_PRIVATE, ui->coredump_fd, phdr->p_offset);
+ if (ei->image == MAP_FAILED)
+ {
+ ei->image = NULL;
+ return NULL;
+ }
+ ei->size = phdr->p_filesz;
+ size_t remainder_len = phdr->p_memsz - phdr->p_filesz;
+ if (remainder_len > 0)
+ {
+ void *remainder_base = (char*) ei->image + phdr->p_filesz;
+ munmap(remainder_base, remainder_len);
+ }
+ } else {
+ /* We have a backing file for this segment.
+ * This file is always longer than phdr->p_memsz,
+ * and if phdr->p_filesz !=0, first phdr->p_filesz bytes in coredump
+ * are the same as first bytes in the file. (Thus no need to map coredump)
+ * We map the entire file:
+ * unwinding may need data which is past phdr->p_memsz bytes.
+ */
+ /* addr, length, prot, flags, fd, fd_offset */
+ ei->image = mmap(NULL, phdr->backing_filesize, PROT_READ, MAP_PRIVATE, phdr->backing_fd, 0);
+ if (ei->image == MAP_FAILED)
+ {
+ ei->image = NULL;
+ return NULL;
+ }
+ ei->size = phdr->backing_filesize;
+ }
+
+ /* Check ELF header for sanity */
+ if (!elf_w(valid_object)(ei))
+ {
+ munmap(ei->image, ei->size);
+ ei->image = NULL;
+ ei->size = 0;
+ return NULL;
+ }
+
+ return phdr;
+}
+
+HIDDEN coredump_phdr_t *
+_UCD_get_elf_image(struct UCD_info *ui, unw_word_t ip)
+{
+ unsigned i;
+ for (i = 0; i < ui->phdrs_count; i++)
+ {
+ coredump_phdr_t *phdr = &ui->phdrs[i];
+ if (phdr->p_vaddr <= ip && ip < phdr->p_vaddr + phdr->p_memsz)
+ {
+ phdr = CD_elf_map_image(ui, phdr);
+ return phdr;
+ }
+ }
+ return NULL;
+}
diff --git a/src/pal/src/libunwind/src/coredump/_UCD_find_proc_info.c b/src/pal/src/libunwind/src/coredump/_UCD_find_proc_info.c
new file mode 100644
index 0000000000..33b66c8edb
--- /dev/null
+++ b/src/pal/src/libunwind/src/coredump/_UCD_find_proc_info.c
@@ -0,0 +1,163 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <elf.h>
+
+#include "_UCD_lib.h"
+#include "_UCD_internal.h"
+
+static int
+get_unwind_info(struct UCD_info *ui, unw_addr_space_t as, unw_word_t ip)
+{
+ unsigned long segbase, mapoff;
+
+#if UNW_TARGET_IA64 && defined(__linux)
+ if (!ui->edi.ktab.start_ip && _Uia64_get_kernel_table (&ui->edi.ktab) < 0)
+ return -UNW_ENOINFO;
+
+ if (ui->edi.ktab.format != -1 && ip >= ui->edi.ktab.start_ip && ip < ui->edi.ktab.end_ip)
+ return 0;
+#endif
+
+ if ((ui->edi.di_cache.format != -1
+ && ip >= ui->edi.di_cache.start_ip && ip < ui->edi.di_cache.end_ip)
+#if UNW_TARGET_ARM
+ || (ui->edi.di_debug.format != -1
+ && ip >= ui->edi.di_arm.start_ip && ip < ui->edi.di_arm.end_ip)
+#endif
+ || (ui->edi.di_debug.format != -1
+ && ip >= ui->edi.di_debug.start_ip && ip < ui->edi.di_debug.end_ip))
+ return 0;
+
+ invalidate_edi (&ui->edi);
+
+ /* Used to be tdep_get_elf_image() in ptrace unwinding code */
+ coredump_phdr_t *phdr = _UCD_get_elf_image(ui, ip);
+ if (!phdr)
+ {
+ Debug(1, "returns error: _UCD_get_elf_image failed\n");
+ return -UNW_ENOINFO;
+ }
+ /* segbase: where it is mapped in virtual memory */
+ /* mapoff: offset in the file */
+ segbase = phdr->p_vaddr;
+ /*mapoff = phdr->p_offset; WRONG! phdr->p_offset is the offset in COREDUMP file */
+ mapoff = 0;
+///FIXME. text segment is USUALLY, not always, at offset 0 in the binary/.so file.
+// ensure that at initialization.
+
+ /* Here, SEGBASE is the starting-address of the (mmap'ped) segment
+ which covers the IP we're looking for. */
+ if (tdep_find_unwind_table(&ui->edi, as, phdr->backing_filename, segbase, mapoff, ip) < 0)
+ {
+ Debug(1, "returns error: tdep_find_unwind_table failed\n");
+ return -UNW_ENOINFO;
+ }
+
+ /* This can happen in corner cases where dynamically generated
+ code falls into the same page that contains the data-segment
+ and the page-offset of the code is within the first page of
+ the executable. */
+ if (ui->edi.di_cache.format != -1
+ && (ip < ui->edi.di_cache.start_ip || ip >= ui->edi.di_cache.end_ip))
+ ui->edi.di_cache.format = -1;
+
+ if (ui->edi.di_debug.format != -1
+ && (ip < ui->edi.di_debug.start_ip || ip >= ui->edi.di_debug.end_ip))
+ ui->edi.di_debug.format = -1;
+
+ if (ui->edi.di_cache.format == -1
+#if UNW_TARGET_ARM
+ && ui->edi.di_arm.format == -1
+#endif
+ && ui->edi.di_debug.format == -1)
+ {
+ Debug(1, "returns error: all formats are -1\n");
+ return -UNW_ENOINFO;
+ }
+
+ Debug(1, "returns success\n");
+ return 0;
+}
+
+int
+_UCD_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg)
+{
+ struct UCD_info *ui = arg;
+
+ Debug(1, "entering\n");
+
+ int ret = -UNW_ENOINFO;
+
+ if (get_unwind_info(ui, as, ip) < 0) {
+ Debug(1, "returns error: get_unwind_info failed\n");
+ return -UNW_ENOINFO;
+ }
+
+#if UNW_TARGET_IA64
+ if (ui->edi.ktab.format != -1)
+ {
+ /* The kernel unwind table resides in local memory, so we have
+ to use the local address space to search it. Since
+ _UCD_put_unwind_info() has no easy way of detecting this
+ case, we simply make a copy of the unwind-info, so
+ _UCD_put_unwind_info() can always free() the unwind-info
+ without ill effects. */
+ ret = tdep_search_unwind_table (unw_local_addr_space, ip, &ui->edi.ktab, pi,
+ need_unwind_info, arg);
+ if (ret >= 0)
+ {
+ if (!need_unwind_info)
+ pi->unwind_info = NULL;
+ else
+ {
+ void *mem = malloc (pi->unwind_info_size);
+
+ if (!mem)
+ return -UNW_ENOMEM;
+ memcpy (mem, pi->unwind_info, pi->unwind_info_size);
+ pi->unwind_info = mem;
+ }
+ }
+ }
+#endif
+
+ if (ret == -UNW_ENOINFO && ui->edi.di_cache.format != -1)
+ ret = tdep_search_unwind_table (as, ip, &ui->edi.di_cache,
+ pi, need_unwind_info, arg);
+
+#if UNW_TARGET_ARM
+ if (ret == -UNW_ENOINFO && ui->edi.di_arm.format != -1)
+ ret = tdep_search_unwind_table (as, ip, &ui->edi.di_arm, pi,
+ need_unwind_info, arg);
+#endif
+
+ if (ret == -UNW_ENOINFO && ui->edi.di_debug.format != -1)
+ ret = tdep_search_unwind_table (as, ip, &ui->edi.di_debug, pi,
+ need_unwind_info, arg);
+
+ Debug(1, "returns %d\n", ret);
+
+ return ret;
+}
diff --git a/src/pal/src/libunwind/src/coredump/_UCD_get_proc_name.c b/src/pal/src/libunwind/src/coredump/_UCD_get_proc_name.c
new file mode 100644
index 0000000000..00096c48d0
--- /dev/null
+++ b/src/pal/src/libunwind/src/coredump/_UCD_get_proc_name.c
@@ -0,0 +1,70 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UCD_lib.h"
+#include "_UCD_internal.h"
+
+
+/* Find the ELF image that contains IP and return the "closest"
+ procedure name, if there is one. With some caching, this could be
+ sped up greatly, but until an application materializes that's
+ sensitive to the performance of this routine, why bother... */
+static int
+elf_w (CD_get_proc_name) (struct UCD_info *ui, unw_addr_space_t as, unw_word_t ip,
+ char *buf, size_t buf_len, unw_word_t *offp)
+{
+ unsigned long segbase, mapoff;
+ int ret;
+
+ /* Used to be tdep_get_elf_image() in ptrace unwinding code */
+ coredump_phdr_t *cphdr = _UCD_get_elf_image(ui, ip);
+ if (!cphdr)
+ {
+ Debug(1, "returns error: _UCD_get_elf_image failed\n");
+ return -UNW_ENOINFO;
+ }
+ /* segbase: where it is mapped in virtual memory */
+ /* mapoff: offset in the file */
+ segbase = cphdr->p_vaddr;
+ /*mapoff = phdr->p_offset; WRONG! phdr->p_offset is the offset in COREDUMP file */
+ mapoff = 0;
+
+ ret = elf_w (get_proc_name_in_image) (as, &ui->edi.ei, segbase, mapoff, ip, buf, buf_len, offp);
+
+ return ret;
+}
+
+int
+_UCD_get_proc_name (unw_addr_space_t as, unw_word_t ip,
+ char *buf, size_t buf_len, unw_word_t *offp, void *arg)
+{
+ struct UCD_info *ui = arg;
+
+#if ELF_CLASS == ELFCLASS64
+ return _Uelf64_CD_get_proc_name (ui, as, ip, buf, buf_len, offp);
+#elif ELF_CLASS == ELFCLASS32
+ return _Uelf32_CD_get_proc_name (ui, as, ip, buf, buf_len, offp);
+#else
+ return -UNW_ENOINFO;
+#endif
+}
diff --git a/src/pal/src/libunwind/src/coredump/_UCD_internal.h b/src/pal/src/libunwind/src/coredump/_UCD_internal.h
new file mode 100644
index 0000000000..3c95a2a003
--- /dev/null
+++ b/src/pal/src/libunwind/src/coredump/_UCD_internal.h
@@ -0,0 +1,105 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _UCD_internal_h
+#define _UCD_internal_h
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_PROCFS_H
+#include <sys/procfs.h> /* struct elf_prstatus */
+#endif
+#include <errno.h>
+#include <string.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <libunwind-coredump.h>
+
+#include "libunwind_i.h"
+
+
+#if SIZEOF_OFF_T == 4
+typedef uint32_t uoff_t;
+#elif SIZEOF_OFF_T == 8
+typedef uint64_t uoff_t;
+#else
+# error Unknown size of off_t!
+#endif
+
+
+/* Similar to ELF phdrs. p_paddr element is absent,
+ * since it's always 0 in coredumps.
+ */
+struct coredump_phdr
+ {
+ uint32_t p_type;
+ uint32_t p_flags;
+ uoff_t p_offset;
+ uoff_t p_vaddr;
+ uoff_t p_filesz;
+ uoff_t p_memsz;
+ uoff_t p_align;
+ /* Data for backing file. If backing_fd < 0, there is no file */
+ uoff_t backing_filesize;
+ char *backing_filename; /* for error meesages only */
+ int backing_fd;
+ };
+
+typedef struct coredump_phdr coredump_phdr_t;
+
+#if defined(HAVE_STRUCT_ELF_PRSTATUS)
+#define PRSTATUS_STRUCT elf_prstatus
+#elif defined(HAVE_STRUCT_PRSTATUS)
+#define PRSTATUS_STRUCT prstatus
+#else
+#define PRSTATUS_STRUCT non_existent
+#endif
+
+struct UCD_info
+ {
+ int big_endian; /* bool */
+ int coredump_fd;
+ char *coredump_filename; /* for error meesages only */
+ coredump_phdr_t *phdrs; /* array, allocated */
+ unsigned phdrs_count;
+ void *note_phdr; /* allocated or NULL */
+ struct PRSTATUS_STRUCT *prstatus; /* points inside note_phdr */
+ int n_threads;
+ struct PRSTATUS_STRUCT **threads;
+
+ struct elf_dyn_info edi;
+ };
+
+extern coredump_phdr_t * _UCD_get_elf_image(struct UCD_info *ui, unw_word_t ip);
+
+#define STRUCT_MEMBER_P(struct_p, struct_offset) ((void *) ((char*) (struct_p) + (long) (struct_offset)))
+#define STRUCT_MEMBER(member_type, struct_p, struct_offset) (*(member_type*) STRUCT_MEMBER_P ((struct_p), (struct_offset)))
+
+#endif
diff --git a/src/pal/src/libunwind/src/coredump/_UCD_lib.h b/src/pal/src/libunwind/src/coredump/_UCD_lib.h
new file mode 100644
index 0000000000..22be32ed1e
--- /dev/null
+++ b/src/pal/src/libunwind/src/coredump/_UCD_lib.h
@@ -0,0 +1,57 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _UCD_lib_h
+#define _UCD_lib_h
+
+#include <assert.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/poll.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <limits.h>
+#include <sys/param.h>
+#include <pwd.h>
+#include <grp.h>
+#include <syslog.h>
+
+#endif
diff --git a/src/pal/src/libunwind/src/coredump/_UPT_access_fpreg.c b/src/pal/src/libunwind/src/coredump/_UPT_access_fpreg.c
new file mode 100644
index 0000000000..0b8b86ac90
--- /dev/null
+++ b/src/pal/src/libunwind/src/coredump/_UPT_access_fpreg.c
@@ -0,0 +1,34 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UCD_lib.h"
+#include "_UCD_internal.h"
+
+int
+_UCD_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
+ int write, void *arg)
+{
+ print_error (__func__);
+ print_error (" not implemented\n");
+ return -UNW_EINVAL;
+}
diff --git a/src/pal/src/libunwind/src/coredump/_UPT_elf.c b/src/pal/src/libunwind/src/coredump/_UPT_elf.c
new file mode 100644
index 0000000000..fb7b19a7cb
--- /dev/null
+++ b/src/pal/src/libunwind/src/coredump/_UPT_elf.c
@@ -0,0 +1,5 @@
+/* We need to get a separate copy of the ELF-code into
+ libunwind-coredump since it cannot (and must not) have any ELF
+ dependencies on libunwind. */
+#include "libunwind_i.h" /* get ELFCLASS defined */
+#include "../elfxx.c"
diff --git a/src/pal/src/libunwind/src/coredump/_UPT_get_dyn_info_list_addr.c b/src/pal/src/libunwind/src/coredump/_UPT_get_dyn_info_list_addr.c
new file mode 100644
index 0000000000..0d11905566
--- /dev/null
+++ b/src/pal/src/libunwind/src/coredump/_UPT_get_dyn_info_list_addr.c
@@ -0,0 +1,108 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UCD_lib.h"
+#include "_UCD_internal.h"
+
+#if UNW_TARGET_IA64 && defined(__linux)
+# include "elf64.h"
+# include "os-linux.h"
+
+static inline int
+get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg,
+ int *countp)
+{
+ unsigned long lo, hi, off;
+ struct UPT_info *ui = arg;
+ struct map_iterator mi;
+ char path[PATH_MAX];
+ unw_dyn_info_t *di;
+ unw_word_t res;
+ int count = 0;
+
+ maps_init (&mi, ui->pid);
+ while (maps_next (&mi, &lo, &hi, &off))
+ {
+ if (off)
+ continue;
+
+ invalidate_edi (&ui->edi);
+
+ if (elf_map_image (&ui->ei, path) < 0)
+ /* ignore unmappable stuff like "/SYSV00001b58 (deleted)" */
+ continue;
+
+ Debug (16, "checking object %s\n", path);
+
+ di = tdep_find_unwind_table (&ui->edi, as, path, lo, off);
+ if (di)
+ {
+ res = _Uia64_find_dyn_list (as, di, arg);
+ if (res && count++ == 0)
+ {
+ Debug (12, "dyn_info_list_addr = 0x%lx\n", (long) res);
+ *dil_addr = res;
+ }
+ }
+ }
+ maps_close (&mi);
+ *countp = count;
+ return 0;
+}
+
+#else
+
+static inline int
+get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg,
+ int *countp)
+{
+# warning Implement get_list_addr(), please.
+ *countp = 0;
+ return 0;
+}
+
+#endif
+
+int
+_UCD_get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dil_addr,
+ void *arg)
+{
+ int count, ret;
+
+ Debug (12, "looking for dyn_info list\n");
+
+ if ((ret = get_list_addr (as, dil_addr, arg, &count)) < 0)
+ return ret;
+
+ /* If multiple dynamic-info list addresses are found, we would have
+ to determine which was is the one actually in use (since the
+ dynamic name resolution algorithm will pick one "winner").
+ Perhaps we'd have to track them all until we find one that's
+ non-empty. Hopefully, this case simply will never arise, since
+ only libunwind defines the dynamic info list head. */
+ assert (count <= 1);
+
+ return (count > 0) ? 0 : -UNW_ENOINFO;
+}
diff --git a/src/pal/src/libunwind/src/coredump/_UPT_put_unwind_info.c b/src/pal/src/libunwind/src/coredump/_UPT_put_unwind_info.c
new file mode 100644
index 0000000000..462e1d048c
--- /dev/null
+++ b/src/pal/src/libunwind/src/coredump/_UPT_put_unwind_info.c
@@ -0,0 +1,36 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UCD_lib.h"
+#include "_UCD_internal.h"
+
+void
+_UCD_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg)
+{
+ if (!pi->unwind_info)
+ return;
+ free (pi->unwind_info);
+ pi->unwind_info = NULL;
+}
diff --git a/src/pal/src/libunwind/src/coredump/_UPT_resume.c b/src/pal/src/libunwind/src/coredump/_UPT_resume.c
new file mode 100644
index 0000000000..a729c908cb
--- /dev/null
+++ b/src/pal/src/libunwind/src/coredump/_UPT_resume.c
@@ -0,0 +1,35 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UCD_lib.h"
+#include "_UCD_internal.h"
+
+int
+_UCD_resume (unw_addr_space_t as, unw_cursor_t *c, void *arg)
+{
+ print_error (__func__);
+ print_error (" not implemented\n");
+ return -UNW_EINVAL;
+}
diff --git a/src/pal/src/libunwind/src/coredump/libunwind-coredump.pc.in b/src/pal/src/libunwind/src/coredump/libunwind-coredump.pc.in
new file mode 100644
index 0000000000..9cb62c086d
--- /dev/null
+++ b/src/pal/src/libunwind/src/coredump/libunwind-coredump.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libunwind-coredump
+Description: libunwind coredump library
+Version: @VERSION@
+Requires: libunwind-generic libunwind
+Libs: -L${libdir} -lunwind-coredump
+Cflags: -I${includedir}
diff --git a/src/pal/src/libunwind/src/dwarf/Gexpr.c b/src/pal/src/libunwind/src/dwarf/Gexpr.c
new file mode 100644
index 0000000000..f63c3d220c
--- /dev/null
+++ b/src/pal/src/libunwind/src/dwarf/Gexpr.c
@@ -0,0 +1,696 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "dwarf_i.h"
+#include "libunwind_i.h"
+
+/* The "pick" operator provides an index range of 0..255 indicating
+ that the stack could at least have a depth of up to 256 elements,
+ but the GCC unwinder restricts the depth to 64, which seems
+ reasonable so we use the same value here. */
+#define MAX_EXPR_STACK_SIZE 64
+
+#define NUM_OPERANDS(signature) (((signature) >> 6) & 0x3)
+#define OPND1_TYPE(signature) (((signature) >> 3) & 0x7)
+#define OPND2_TYPE(signature) (((signature) >> 0) & 0x7)
+
+#define OPND_SIGNATURE(n, t1, t2) (((n) << 6) | ((t1) << 3) | ((t2) << 0))
+#define OPND1(t1) OPND_SIGNATURE(1, t1, 0)
+#define OPND2(t1, t2) OPND_SIGNATURE(2, t1, t2)
+
+#define VAL8 0x0
+#define VAL16 0x1
+#define VAL32 0x2
+#define VAL64 0x3
+#define ULEB128 0x4
+#define SLEB128 0x5
+#define OFFSET 0x6 /* 32-bit offset for 32-bit DWARF, 64-bit otherwise */
+#define ADDR 0x7 /* Machine address. */
+
+static const uint8_t operands[256] =
+ {
+ [DW_OP_addr] = OPND1 (ADDR),
+ [DW_OP_const1u] = OPND1 (VAL8),
+ [DW_OP_const1s] = OPND1 (VAL8),
+ [DW_OP_const2u] = OPND1 (VAL16),
+ [DW_OP_const2s] = OPND1 (VAL16),
+ [DW_OP_const4u] = OPND1 (VAL32),
+ [DW_OP_const4s] = OPND1 (VAL32),
+ [DW_OP_const8u] = OPND1 (VAL64),
+ [DW_OP_const8s] = OPND1 (VAL64),
+ [DW_OP_pick] = OPND1 (VAL8),
+ [DW_OP_plus_uconst] = OPND1 (ULEB128),
+ [DW_OP_skip] = OPND1 (VAL16),
+ [DW_OP_bra] = OPND1 (VAL16),
+ [DW_OP_breg0 + 0] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 1] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 2] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 3] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 4] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 5] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 6] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 7] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 8] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 9] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 10] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 11] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 12] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 13] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 14] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 15] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 16] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 17] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 18] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 19] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 20] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 21] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 22] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 23] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 24] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 25] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 26] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 27] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 28] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 29] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 30] = OPND1 (SLEB128),
+ [DW_OP_breg0 + 31] = OPND1 (SLEB128),
+ [DW_OP_regx] = OPND1 (ULEB128),
+ [DW_OP_fbreg] = OPND1 (SLEB128),
+ [DW_OP_bregx] = OPND2 (ULEB128, SLEB128),
+ [DW_OP_piece] = OPND1 (ULEB128),
+ [DW_OP_deref_size] = OPND1 (VAL8),
+ [DW_OP_xderef_size] = OPND1 (VAL8),
+ [DW_OP_call2] = OPND1 (VAL16),
+ [DW_OP_call4] = OPND1 (VAL32),
+ [DW_OP_call_ref] = OPND1 (OFFSET)
+ };
+
+static inline unw_sword_t
+sword (unw_addr_space_t as, unw_word_t val)
+{
+ switch (dwarf_addr_size (as))
+ {
+ case 1: return (int8_t) val;
+ case 2: return (int16_t) val;
+ case 4: return (int32_t) val;
+ case 8: return (int64_t) val;
+ default: abort ();
+ }
+}
+
+static inline unw_word_t
+read_operand (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t *addr, int operand_type, unw_word_t *val, void *arg)
+{
+ uint8_t u8;
+ uint16_t u16;
+ uint32_t u32;
+ uint64_t u64;
+ int ret;
+
+ if (operand_type == ADDR)
+ switch (dwarf_addr_size (as))
+ {
+ case 1: operand_type = VAL8; break;
+ case 2: operand_type = VAL16; break;
+ case 4: operand_type = VAL32; break;
+ case 8: operand_type = VAL64; break;
+ default: abort ();
+ }
+
+ switch (operand_type)
+ {
+ case VAL8:
+ ret = dwarf_readu8 (as, a, addr, &u8, arg);
+ if (ret < 0)
+ return ret;
+ *val = u8;
+ break;
+
+ case VAL16:
+ ret = dwarf_readu16 (as, a, addr, &u16, arg);
+ if (ret < 0)
+ return ret;
+ *val = u16;
+ break;
+
+ case VAL32:
+ ret = dwarf_readu32 (as, a, addr, &u32, arg);
+ if (ret < 0)
+ return ret;
+ *val = u32;
+ break;
+
+ case VAL64:
+ ret = dwarf_readu64 (as, a, addr, &u64, arg);
+ if (ret < 0)
+ return ret;
+ *val = u64;
+ break;
+
+ case ULEB128:
+ ret = dwarf_read_uleb128 (as, a, addr, val, arg);
+ break;
+
+ case SLEB128:
+ ret = dwarf_read_sleb128 (as, a, addr, val, arg);
+ break;
+
+ case OFFSET: /* only used by DW_OP_call_ref, which we don't implement */
+ default:
+ Debug (1, "Unexpected operand type %d\n", operand_type);
+ ret = -UNW_EINVAL;
+ }
+ return ret;
+}
+
+HIDDEN int
+dwarf_stack_aligned(struct dwarf_cursor *c, unw_word_t cfa_addr,
+ unw_word_t rbp_addr, unw_word_t *cfa_offset) {
+ unw_accessors_t *a;
+ int ret;
+ void *arg;
+ unw_word_t len;
+ uint8_t opcode;
+ unw_word_t operand1;
+
+ a = unw_get_accessors_int (c->as);
+ arg = c->as_arg;
+
+ ret = dwarf_read_uleb128(c->as, a, &rbp_addr, &len, arg);
+ if (len != 2 || ret < 0)
+ return 0;
+
+ ret = dwarf_readu8(c->as, a, &rbp_addr, &opcode, arg);
+ if (ret < 0 || opcode != DW_OP_breg6)
+ return 0;
+
+ ret = read_operand(c->as, a, &rbp_addr,
+ OPND1_TYPE(operands[opcode]), &operand1, arg);
+
+ if (ret < 0 || operand1 != 0)
+ return 0;
+
+ ret = dwarf_read_uleb128(c->as, a, &cfa_addr, &len, arg);
+ if (ret < 0 || len != 3)
+ return 0;
+
+ ret = dwarf_readu8(c->as, a, &cfa_addr, &opcode, arg);
+ if (ret < 0 || opcode != DW_OP_breg6)
+ return 0;
+
+ ret = read_operand(c->as, a, &cfa_addr,
+ OPND1_TYPE(operands[opcode]), &operand1, arg);
+ if (ret < 0)
+ return 0;
+
+ ret = dwarf_readu8(c->as, a, &cfa_addr, &opcode, arg);
+ if (ret < 0 || opcode != DW_OP_deref)
+ return 0;
+
+ *cfa_offset = operand1;
+ return 1;
+}
+
+HIDDEN int
+dwarf_eval_expr (struct dwarf_cursor *c, unw_word_t *addr, unw_word_t len,
+ unw_word_t *valp, int *is_register)
+{
+ unw_word_t operand1 = 0, operand2 = 0, tmp1, tmp2 = 0, tmp3, end_addr;
+ uint8_t opcode, operands_signature, u8;
+ unw_addr_space_t as;
+ unw_accessors_t *a;
+ void *arg;
+ unw_word_t stack[MAX_EXPR_STACK_SIZE];
+ unsigned int tos = 0;
+ uint16_t u16;
+ uint32_t u32;
+ uint64_t u64;
+ int ret;
+# define pop() \
+({ \
+ if ((tos - 1) >= MAX_EXPR_STACK_SIZE) \
+ { \
+ Debug (1, "Stack underflow\n"); \
+ return -UNW_EINVAL; \
+ } \
+ stack[--tos]; \
+})
+# define push(x) \
+do { \
+ unw_word_t _x = (x); \
+ if (tos >= MAX_EXPR_STACK_SIZE) \
+ { \
+ Debug (1, "Stack overflow\n"); \
+ return -UNW_EINVAL; \
+ } \
+ stack[tos++] = _x; \
+} while (0)
+# define pick(n) \
+({ \
+ unsigned int _index = tos - 1 - (n); \
+ if (_index >= MAX_EXPR_STACK_SIZE) \
+ { \
+ Debug (1, "Out-of-stack pick\n"); \
+ return -UNW_EINVAL; \
+ } \
+ stack[_index]; \
+})
+
+ as = c->as;
+ arg = c->as_arg;
+ a = unw_get_accessors_int (as);
+ end_addr = *addr + len;
+ *is_register = 0;
+
+ Debug (14, "len=%lu, pushing cfa=0x%lx\n",
+ (unsigned long) len, (unsigned long) c->cfa);
+
+ push (c->cfa); /* push current CFA as required by DWARF spec */
+
+ while (*addr < end_addr)
+ {
+ if ((ret = dwarf_readu8 (as, a, addr, &opcode, arg)) < 0)
+ return ret;
+
+ operands_signature = operands[opcode];
+
+ if (unlikely (NUM_OPERANDS (operands_signature) > 0))
+ {
+ if ((ret = read_operand (as, a, addr,
+ OPND1_TYPE (operands_signature),
+ &operand1, arg)) < 0)
+ return ret;
+ if (NUM_OPERANDS (operands_signature) > 1)
+ if ((ret = read_operand (as, a, addr,
+ OPND2_TYPE (operands_signature),
+ &operand2, arg)) < 0)
+ return ret;
+ }
+
+ switch ((dwarf_expr_op_t) opcode)
+ {
+ case DW_OP_lit0: case DW_OP_lit1: case DW_OP_lit2:
+ case DW_OP_lit3: case DW_OP_lit4: case DW_OP_lit5:
+ case DW_OP_lit6: case DW_OP_lit7: case DW_OP_lit8:
+ case DW_OP_lit9: case DW_OP_lit10: case DW_OP_lit11:
+ case DW_OP_lit12: case DW_OP_lit13: case DW_OP_lit14:
+ case DW_OP_lit15: case DW_OP_lit16: case DW_OP_lit17:
+ case DW_OP_lit18: case DW_OP_lit19: case DW_OP_lit20:
+ case DW_OP_lit21: case DW_OP_lit22: case DW_OP_lit23:
+ case DW_OP_lit24: case DW_OP_lit25: case DW_OP_lit26:
+ case DW_OP_lit27: case DW_OP_lit28: case DW_OP_lit29:
+ case DW_OP_lit30: case DW_OP_lit31:
+ Debug (15, "OP_lit(%d)\n", (int) opcode - DW_OP_lit0);
+ push (opcode - DW_OP_lit0);
+ break;
+
+ case DW_OP_breg0: case DW_OP_breg1: case DW_OP_breg2:
+ case DW_OP_breg3: case DW_OP_breg4: case DW_OP_breg5:
+ case DW_OP_breg6: case DW_OP_breg7: case DW_OP_breg8:
+ case DW_OP_breg9: case DW_OP_breg10: case DW_OP_breg11:
+ case DW_OP_breg12: case DW_OP_breg13: case DW_OP_breg14:
+ case DW_OP_breg15: case DW_OP_breg16: case DW_OP_breg17:
+ case DW_OP_breg18: case DW_OP_breg19: case DW_OP_breg20:
+ case DW_OP_breg21: case DW_OP_breg22: case DW_OP_breg23:
+ case DW_OP_breg24: case DW_OP_breg25: case DW_OP_breg26:
+ case DW_OP_breg27: case DW_OP_breg28: case DW_OP_breg29:
+ case DW_OP_breg30: case DW_OP_breg31:
+ Debug (15, "OP_breg(r%d,0x%lx)\n",
+ (int) opcode - DW_OP_breg0, (unsigned long) operand1);
+ if ((ret = unw_get_reg (dwarf_to_cursor (c),
+ dwarf_to_unw_regnum (opcode - DW_OP_breg0),
+ &tmp1)) < 0)
+ return ret;
+ push (tmp1 + operand1);
+ break;
+
+ case DW_OP_bregx:
+ Debug (15, "OP_bregx(r%d,0x%lx)\n",
+ (int) operand1, (unsigned long) operand2);
+ if ((ret = unw_get_reg (dwarf_to_cursor (c),
+ dwarf_to_unw_regnum (operand1), &tmp1)) < 0)
+ return ret;
+ push (tmp1 + operand2);
+ break;
+
+ case DW_OP_reg0: case DW_OP_reg1: case DW_OP_reg2:
+ case DW_OP_reg3: case DW_OP_reg4: case DW_OP_reg5:
+ case DW_OP_reg6: case DW_OP_reg7: case DW_OP_reg8:
+ case DW_OP_reg9: case DW_OP_reg10: case DW_OP_reg11:
+ case DW_OP_reg12: case DW_OP_reg13: case DW_OP_reg14:
+ case DW_OP_reg15: case DW_OP_reg16: case DW_OP_reg17:
+ case DW_OP_reg18: case DW_OP_reg19: case DW_OP_reg20:
+ case DW_OP_reg21: case DW_OP_reg22: case DW_OP_reg23:
+ case DW_OP_reg24: case DW_OP_reg25: case DW_OP_reg26:
+ case DW_OP_reg27: case DW_OP_reg28: case DW_OP_reg29:
+ case DW_OP_reg30: case DW_OP_reg31:
+ Debug (15, "OP_reg(r%d)\n", (int) opcode - DW_OP_reg0);
+ *valp = dwarf_to_unw_regnum (opcode - DW_OP_reg0);
+ *is_register = 1;
+ return 0;
+
+ case DW_OP_regx:
+ Debug (15, "OP_regx(r%d)\n", (int) operand1);
+ *valp = dwarf_to_unw_regnum (operand1);
+ *is_register = 1;
+ return 0;
+
+ case DW_OP_addr:
+ case DW_OP_const1u:
+ case DW_OP_const2u:
+ case DW_OP_const4u:
+ case DW_OP_const8u:
+ case DW_OP_constu:
+ case DW_OP_const8s:
+ case DW_OP_consts:
+ Debug (15, "OP_const(0x%lx)\n", (unsigned long) operand1);
+ push (operand1);
+ break;
+
+ case DW_OP_const1s:
+ if (operand1 & 0x80)
+ operand1 |= ((unw_word_t) -1) << 8;
+ Debug (15, "OP_const1s(%ld)\n", (long) operand1);
+ push (operand1);
+ break;
+
+ case DW_OP_const2s:
+ if (operand1 & 0x8000)
+ operand1 |= ((unw_word_t) -1) << 16;
+ Debug (15, "OP_const2s(%ld)\n", (long) operand1);
+ push (operand1);
+ break;
+
+ case DW_OP_const4s:
+ if (operand1 & 0x80000000)
+ operand1 |= (((unw_word_t) -1) << 16) << 16;
+ Debug (15, "OP_const4s(%ld)\n", (long) operand1);
+ push (operand1);
+ break;
+
+ case DW_OP_deref:
+ Debug (15, "OP_deref\n");
+ tmp1 = pop ();
+ if ((ret = dwarf_readw (as, a, &tmp1, &tmp2, arg)) < 0)
+ return ret;
+ push (tmp2);
+ break;
+
+ case DW_OP_deref_size:
+ Debug (15, "OP_deref_size(%d)\n", (int) operand1);
+ tmp1 = pop ();
+ switch (operand1)
+ {
+ default:
+ Debug (1, "Unexpected DW_OP_deref_size size %d\n",
+ (int) operand1);
+ return -UNW_EINVAL;
+
+ case 1:
+ if ((ret = dwarf_readu8 (as, a, &tmp1, &u8, arg)) < 0)
+ return ret;
+ tmp2 = u8;
+ break;
+
+ case 2:
+ if ((ret = dwarf_readu16 (as, a, &tmp1, &u16, arg)) < 0)
+ return ret;
+ tmp2 = u16;
+ break;
+
+ case 3:
+ case 4:
+ if ((ret = dwarf_readu32 (as, a, &tmp1, &u32, arg)) < 0)
+ return ret;
+ tmp2 = u32;
+ if (operand1 == 3)
+ {
+ if (dwarf_is_big_endian (as))
+ tmp2 >>= 8;
+ else
+ tmp2 &= 0xffffff;
+ }
+ break;
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ if ((ret = dwarf_readu64 (as, a, &tmp1, &u64, arg)) < 0)
+ return ret;
+ tmp2 = u64;
+ if (operand1 != 8)
+ {
+ if (dwarf_is_big_endian (as))
+ tmp2 >>= 64 - 8 * operand1;
+ else
+ tmp2 &= (~ (unw_word_t) 0) << (8 * operand1);
+ }
+ break;
+ }
+ push (tmp2);
+ break;
+
+ case DW_OP_dup:
+ Debug (15, "OP_dup\n");
+ push (pick (0));
+ break;
+
+ case DW_OP_drop:
+ Debug (15, "OP_drop\n");
+ (void) pop ();
+ break;
+
+ case DW_OP_pick:
+ Debug (15, "OP_pick(%d)\n", (int) operand1);
+ push (pick (operand1));
+ break;
+
+ case DW_OP_over:
+ Debug (15, "OP_over\n");
+ push (pick (1));
+ break;
+
+ case DW_OP_swap:
+ Debug (15, "OP_swap\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ push (tmp1);
+ push (tmp2);
+ break;
+
+ case DW_OP_rot:
+ Debug (15, "OP_rot\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ tmp3 = pop ();
+ push (tmp1);
+ push (tmp3);
+ push (tmp2);
+ break;
+
+ case DW_OP_abs:
+ Debug (15, "OP_abs\n");
+ tmp1 = pop ();
+ if (tmp1 & ((unw_word_t) 1 << (8 * dwarf_addr_size (as) - 1)))
+ tmp1 = -tmp1;
+ push (tmp1);
+ break;
+
+ case DW_OP_and:
+ Debug (15, "OP_and\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ push (tmp1 & tmp2);
+ break;
+
+ case DW_OP_div:
+ Debug (15, "OP_div\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ if (tmp1)
+ tmp1 = sword (as, tmp2) / sword (as, tmp1);
+ push (tmp1);
+ break;
+
+ case DW_OP_minus:
+ Debug (15, "OP_minus\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ tmp1 = tmp2 - tmp1;
+ push (tmp1);
+ break;
+
+ case DW_OP_mod:
+ Debug (15, "OP_mod\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ if (tmp1)
+ tmp1 = tmp2 % tmp1;
+ push (tmp1);
+ break;
+
+ case DW_OP_mul:
+ Debug (15, "OP_mul\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ if (tmp1)
+ tmp1 = tmp2 * tmp1;
+ push (tmp1);
+ break;
+
+ case DW_OP_neg:
+ Debug (15, "OP_neg\n");
+ push (-pop ());
+ break;
+
+ case DW_OP_not:
+ Debug (15, "OP_not\n");
+ push (~pop ());
+ break;
+
+ case DW_OP_or:
+ Debug (15, "OP_or\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ push (tmp1 | tmp2);
+ break;
+
+ case DW_OP_plus:
+ Debug (15, "OP_plus\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ push (tmp1 + tmp2);
+ break;
+
+ case DW_OP_plus_uconst:
+ Debug (15, "OP_plus_uconst(%lu)\n", (unsigned long) operand1);
+ tmp1 = pop ();
+ push (tmp1 + operand1);
+ break;
+
+ case DW_OP_shl:
+ Debug (15, "OP_shl\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ push (tmp2 << tmp1);
+ break;
+
+ case DW_OP_shr:
+ Debug (15, "OP_shr\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ push (tmp2 >> tmp1);
+ break;
+
+ case DW_OP_shra:
+ Debug (15, "OP_shra\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ push (sword (as, tmp2) >> tmp1);
+ break;
+
+ case DW_OP_xor:
+ Debug (15, "OP_xor\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ push (tmp1 ^ tmp2);
+ break;
+
+ case DW_OP_le:
+ Debug (15, "OP_le\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ push (sword (as, tmp2) <= sword (as, tmp1));
+ break;
+
+ case DW_OP_ge:
+ Debug (15, "OP_ge\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ push (sword (as, tmp2) >= sword (as, tmp1));
+ break;
+
+ case DW_OP_eq:
+ Debug (15, "OP_eq\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ push (sword (as, tmp2) == sword (as, tmp1));
+ break;
+
+ case DW_OP_lt:
+ Debug (15, "OP_lt\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ push (sword (as, tmp2) < sword (as, tmp1));
+ break;
+
+ case DW_OP_gt:
+ Debug (15, "OP_gt\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ push (sword (as, tmp2) > sword (as, tmp1));
+ break;
+
+ case DW_OP_ne:
+ Debug (15, "OP_ne\n");
+ tmp1 = pop ();
+ tmp2 = pop ();
+ push (sword (as, tmp2) != sword (as, tmp1));
+ break;
+
+ case DW_OP_skip:
+ Debug (15, "OP_skip(%d)\n", (int16_t) operand1);
+ *addr += (int16_t) operand1;
+ break;
+
+ case DW_OP_bra:
+ Debug (15, "OP_skip(%d)\n", (int16_t) operand1);
+ tmp1 = pop ();
+ if (tmp1)
+ *addr += (int16_t) operand1;
+ break;
+
+ case DW_OP_nop:
+ Debug (15, "OP_nop\n");
+ break;
+
+ case DW_OP_call2:
+ case DW_OP_call4:
+ case DW_OP_call_ref:
+ case DW_OP_fbreg:
+ case DW_OP_piece:
+ case DW_OP_push_object_address:
+ case DW_OP_xderef:
+ case DW_OP_xderef_size:
+ default:
+ Debug (1, "Unexpected opcode 0x%x\n", opcode);
+ return -UNW_EINVAL;
+ }
+ }
+ *valp = pop ();
+ Debug (14, "final value = 0x%lx\n", (unsigned long) *valp);
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/dwarf/Gfde.c b/src/pal/src/libunwind/src/dwarf/Gfde.c
new file mode 100644
index 0000000000..9250b895ea
--- /dev/null
+++ b/src/pal/src/libunwind/src/dwarf/Gfde.c
@@ -0,0 +1,359 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "dwarf_i.h"
+
+static inline int
+is_cie_id (unw_word_t val, int is_debug_frame)
+{
+ /* The CIE ID is normally 0xffffffff (for 32-bit ELF) or
+ 0xffffffffffffffff (for 64-bit ELF). However, .eh_frame
+ uses 0. */
+ if (is_debug_frame)
+ return (val == (uint32_t)(-1) || val == (uint64_t)(-1));
+ else
+ return (val == 0);
+}
+
+/* Note: we don't need to keep track of more than the first four
+ characters of the augmentation string, because we (a) ignore any
+ augmentation string contents once we find an unrecognized character
+ and (b) those characters that we do recognize, can't be
+ repeated. */
+static inline int
+parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
+ const unw_proc_info_t *pi, struct dwarf_cie_info *dci,
+ int is_debug_frame, void *arg)
+{
+ uint8_t version, ch, augstr[5], fde_encoding, handler_encoding;
+ unw_word_t len, cie_end_addr, aug_size;
+ uint32_t u32val;
+ uint64_t u64val;
+ size_t i;
+ int ret;
+# define STR2(x) #x
+# define STR(x) STR2(x)
+
+ /* Pick appropriate default for FDE-encoding. DWARF spec says
+ start-IP (initial_location) and the code-size (address_range) are
+ "address-unit sized constants". The `R' augmentation can be used
+ to override this, but by default, we pick an address-sized unit
+ for fde_encoding. */
+ switch (dwarf_addr_size (as))
+ {
+ case 4: fde_encoding = DW_EH_PE_udata4; break;
+ case 8: fde_encoding = DW_EH_PE_udata8; break;
+ default: fde_encoding = DW_EH_PE_omit; break;
+ }
+
+ dci->lsda_encoding = DW_EH_PE_omit;
+ dci->handler = 0;
+
+ if ((ret = dwarf_readu32 (as, a, &addr, &u32val, arg)) < 0)
+ return ret;
+
+ if (u32val != 0xffffffff)
+ {
+ /* the CIE is in the 32-bit DWARF format */
+ uint32_t cie_id;
+ /* DWARF says CIE id should be 0xffffffff, but in .eh_frame, it's 0 */
+ const uint32_t expected_id = (is_debug_frame) ? 0xffffffff : 0;
+
+ len = u32val;
+ cie_end_addr = addr + len;
+ if ((ret = dwarf_readu32 (as, a, &addr, &cie_id, arg)) < 0)
+ return ret;
+ if (cie_id != expected_id)
+ {
+ Debug (1, "Unexpected CIE id %x\n", cie_id);
+ return -UNW_EINVAL;
+ }
+ }
+ else
+ {
+ /* the CIE is in the 64-bit DWARF format */
+ uint64_t cie_id;
+ /* DWARF says CIE id should be 0xffffffffffffffff, but in
+ .eh_frame, it's 0 */
+ const uint64_t expected_id = (is_debug_frame) ? 0xffffffffffffffffull : 0;
+
+ if ((ret = dwarf_readu64 (as, a, &addr, &u64val, arg)) < 0)
+ return ret;
+ len = u64val;
+ cie_end_addr = addr + len;
+ if ((ret = dwarf_readu64 (as, a, &addr, &cie_id, arg)) < 0)
+ return ret;
+ if (cie_id != expected_id)
+ {
+ Debug (1, "Unexpected CIE id %llx\n", (long long) cie_id);
+ return -UNW_EINVAL;
+ }
+ }
+ dci->cie_instr_end = cie_end_addr;
+
+ if ((ret = dwarf_readu8 (as, a, &addr, &version, arg)) < 0)
+ return ret;
+
+ /* GCC emits version 1??? */
+ if (version != 1 && (version < DWARF_CIE_VERSION || version > DWARF_CIE_VERSION_MAX))
+ {
+ Debug (1, "Got CIE version %u, expected version 1 or between "
+ STR (DWARF_CIE_VERSION) " and " STR (DWARF_CIE_VERSION_MAX) "\n", version);
+ return -UNW_EBADVERSION;
+ }
+
+ /* read and parse the augmentation string: */
+ memset (augstr, 0, sizeof (augstr));
+ for (i = 0;;)
+ {
+ if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0)
+ return ret;
+
+ if (!ch)
+ break; /* end of augmentation string */
+
+ if (i < sizeof (augstr) - 1)
+ augstr[i++] = ch;
+ }
+
+ if ((ret = dwarf_read_uleb128 (as, a, &addr, &dci->code_align, arg)) < 0
+ || (ret = dwarf_read_sleb128 (as, a, &addr, &dci->data_align, arg)) < 0)
+ return ret;
+
+ /* Read the return-address column either as a u8 or as a uleb128. */
+ if (version == 1)
+ {
+ if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0)
+ return ret;
+ dci->ret_addr_column = ch;
+ }
+ else if ((ret = dwarf_read_uleb128 (as, a, &addr, &dci->ret_addr_column,
+ arg)) < 0)
+ return ret;
+
+ i = 0;
+ if (augstr[0] == 'z')
+ {
+ dci->sized_augmentation = 1;
+ if ((ret = dwarf_read_uleb128 (as, a, &addr, &aug_size, arg)) < 0)
+ return ret;
+ i++;
+ }
+
+ for (; i < sizeof (augstr) && augstr[i]; ++i)
+ switch (augstr[i])
+ {
+ case 'L':
+ /* read the LSDA pointer-encoding format. */
+ if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0)
+ return ret;
+ dci->lsda_encoding = ch;
+ break;
+
+ case 'R':
+ /* read the FDE pointer-encoding format. */
+ if ((ret = dwarf_readu8 (as, a, &addr, &fde_encoding, arg)) < 0)
+ return ret;
+ break;
+
+ case 'P':
+ /* read the personality-routine pointer-encoding format. */
+ if ((ret = dwarf_readu8 (as, a, &addr, &handler_encoding, arg)) < 0)
+ return ret;
+ if ((ret = dwarf_read_encoded_pointer (as, a, &addr, handler_encoding,
+ pi, &dci->handler, arg)) < 0)
+ return ret;
+ break;
+
+ case 'S':
+ /* This is a signal frame. */
+ dci->signal_frame = 1;
+
+ /* Temporarily set it to one so dwarf_parse_fde() knows that
+ it should fetch the actual ABI/TAG pair from the FDE. */
+ dci->have_abi_marker = 1;
+ break;
+
+ default:
+ Debug (1, "Unexpected augmentation string `%s'\n", augstr);
+ if (dci->sized_augmentation)
+ /* If we have the size of the augmentation body, we can skip
+ over the parts that we don't understand, so we're OK. */
+ goto done;
+ else
+ return -UNW_EINVAL;
+ }
+ done:
+ dci->fde_encoding = fde_encoding;
+ dci->cie_instr_start = addr;
+ Debug (15, "CIE parsed OK, augmentation = \"%s\", handler=0x%lx\n",
+ augstr, (long) dci->handler);
+ return 0;
+}
+
+/* Extract proc-info from the FDE starting at adress ADDR.
+
+ Pass BASE as zero for eh_frame behaviour, or a pointer to
+ debug_frame base for debug_frame behaviour. */
+
+HIDDEN int
+dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t *addrp, unw_proc_info_t *pi,
+ unw_word_t base,
+ int need_unwind_info, int is_debug_frame,
+ void *arg)
+{
+ unw_word_t fde_end_addr, cie_addr, cie_offset_addr, aug_end_addr = 0;
+ unw_word_t start_ip, ip_range, aug_size, addr = *addrp;
+ int ret, ip_range_encoding;
+ struct dwarf_cie_info dci;
+ uint64_t u64val;
+ uint32_t u32val;
+
+ Debug (12, "FDE @ 0x%lx\n", (long) addr);
+
+ memset (&dci, 0, sizeof (dci));
+
+ if ((ret = dwarf_readu32 (as, a, &addr, &u32val, arg)) < 0)
+ return ret;
+
+ if (u32val != 0xffffffff)
+ {
+ int32_t cie_offset = 0;
+
+ /* In some configurations, an FDE with a 0 length indicates the
+ end of the FDE-table. */
+ if (u32val == 0)
+ return -UNW_ENOINFO;
+
+ /* the FDE is in the 32-bit DWARF format */
+
+ *addrp = fde_end_addr = addr + u32val;
+ cie_offset_addr = addr;
+
+ if ((ret = dwarf_reads32 (as, a, &addr, &cie_offset, arg)) < 0)
+ return ret;
+
+ if (is_cie_id (cie_offset, is_debug_frame))
+ /* ignore CIEs (happens during linear searches) */
+ return 0;
+
+ if (is_debug_frame)
+ cie_addr = base + cie_offset;
+ else
+ /* DWARF says that the CIE_pointer in the FDE is a
+ .debug_frame-relative offset, but the GCC-generated .eh_frame
+ sections instead store a "pcrelative" offset, which is just
+ as fine as it's self-contained. */
+ cie_addr = cie_offset_addr - cie_offset;
+ }
+ else
+ {
+ int64_t cie_offset = 0;
+
+ /* the FDE is in the 64-bit DWARF format */
+
+ if ((ret = dwarf_readu64 (as, a, &addr, &u64val, arg)) < 0)
+ return ret;
+
+ *addrp = fde_end_addr = addr + u64val;
+ cie_offset_addr = addr;
+
+ if ((ret = dwarf_reads64 (as, a, &addr, &cie_offset, arg)) < 0)
+ return ret;
+
+ if (is_cie_id (cie_offset, is_debug_frame))
+ /* ignore CIEs (happens during linear searches) */
+ return 0;
+
+ if (is_debug_frame)
+ cie_addr = base + cie_offset;
+ else
+ /* DWARF says that the CIE_pointer in the FDE is a
+ .debug_frame-relative offset, but the GCC-generated .eh_frame
+ sections instead store a "pcrelative" offset, which is just
+ as fine as it's self-contained. */
+ cie_addr = (unw_word_t) ((uint64_t) cie_offset_addr - cie_offset);
+ }
+
+ Debug (15, "looking for CIE at address %lx\n", (long) cie_addr);
+
+ if ((ret = parse_cie (as, a, cie_addr, pi, &dci, is_debug_frame, arg)) < 0)
+ return ret;
+
+ /* IP-range has same encoding as FDE pointers, except that it's
+ always an absolute value: */
+ ip_range_encoding = dci.fde_encoding & DW_EH_PE_FORMAT_MASK;
+
+ if ((ret = dwarf_read_encoded_pointer (as, a, &addr, dci.fde_encoding,
+ pi, &start_ip, arg)) < 0
+ || (ret = dwarf_read_encoded_pointer (as, a, &addr, ip_range_encoding,
+ pi, &ip_range, arg)) < 0)
+ return ret;
+ pi->start_ip = start_ip;
+ pi->end_ip = start_ip + ip_range;
+ pi->handler = dci.handler;
+
+ if (dci.sized_augmentation)
+ {
+ if ((ret = dwarf_read_uleb128 (as, a, &addr, &aug_size, arg)) < 0)
+ return ret;
+ aug_end_addr = addr + aug_size;
+ }
+
+ if ((ret = dwarf_read_encoded_pointer (as, a, &addr, dci.lsda_encoding,
+ pi, &pi->lsda, arg)) < 0)
+ return ret;
+
+ Debug (15, "FDE covers IP 0x%lx-0x%lx, LSDA=0x%lx\n",
+ (long) pi->start_ip, (long) pi->end_ip, (long) pi->lsda);
+
+ if (need_unwind_info)
+ {
+ pi->format = UNW_INFO_FORMAT_TABLE;
+ pi->unwind_info_size = sizeof (dci);
+ pi->unwind_info = mempool_alloc (&dwarf_cie_info_pool);
+ if (!pi->unwind_info)
+ return -UNW_ENOMEM;
+
+ if (dci.have_abi_marker)
+ {
+ if ((ret = dwarf_readu16 (as, a, &addr, &dci.abi, arg)) < 0
+ || (ret = dwarf_readu16 (as, a, &addr, &dci.tag, arg)) < 0)
+ return ret;
+ Debug (13, "Found ABI marker = (abi=%u, tag=%u)\n",
+ dci.abi, dci.tag);
+ }
+
+ if (dci.sized_augmentation)
+ dci.fde_instr_start = aug_end_addr;
+ else
+ dci.fde_instr_start = addr;
+ dci.fde_instr_end = fde_end_addr;
+
+ memcpy (pi->unwind_info, &dci, sizeof (dci));
+ }
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/dwarf/Gfind_proc_info-lsb.c b/src/pal/src/libunwind/src/dwarf/Gfind_proc_info-lsb.c
new file mode 100644
index 0000000000..509ceff47c
--- /dev/null
+++ b/src/pal/src/libunwind/src/dwarf/Gfind_proc_info-lsb.c
@@ -0,0 +1,935 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Locate an FDE via the ELF data-structures defined by LSB v1.3
+ (http://www.linuxbase.org/spec/). */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <limits.h>
+
+#include "dwarf_i.h"
+#include "dwarf-eh.h"
+#include "libunwind_i.h"
+
+struct table_entry
+ {
+ int32_t start_ip_offset;
+ int32_t fde_offset;
+ };
+
+#ifndef UNW_REMOTE_ONLY
+
+#ifdef __linux
+#include "os-linux.h"
+#endif
+
+static ALIAS(dwarf_search_unwind_table) int
+dwarf_search_unwind_table_int (unw_addr_space_t as,
+ unw_word_t ip,
+ unw_dyn_info_t *di,
+ unw_proc_info_t *pi,
+ int need_unwind_info, void *arg);
+static int
+linear_search (unw_addr_space_t as, unw_word_t ip,
+ unw_word_t eh_frame_start, unw_word_t eh_frame_end,
+ unw_word_t fde_count,
+ unw_proc_info_t *pi, int need_unwind_info, void *arg)
+{
+ unw_accessors_t *a = unw_get_accessors_int (unw_local_addr_space);
+ unw_word_t i = 0, fde_addr, addr = eh_frame_start;
+ int ret;
+
+ while (i++ < fde_count && addr < eh_frame_end)
+ {
+ fde_addr = addr;
+ if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi,
+ eh_frame_start,
+ 0, 0, arg)) < 0)
+ return ret;
+
+ if (ip >= pi->start_ip && ip < pi->end_ip)
+ {
+ if (!need_unwind_info)
+ return 1;
+ addr = fde_addr;
+ if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi,
+ eh_frame_start,
+ need_unwind_info, 0,
+ arg))
+ < 0)
+ return ret;
+ return 1;
+ }
+ }
+ return -UNW_ENOINFO;
+}
+#endif /* !UNW_REMOTE_ONLY */
+
+#ifdef CONFIG_DEBUG_FRAME
+/* Load .debug_frame section from FILE. Allocates and returns space
+ in *BUF, and sets *BUFSIZE to its size. IS_LOCAL is 1 if using the
+ local process, in which case we can search the system debug file
+ directory; 0 for other address spaces, in which case we do
+ not. Returns 0 on success, 1 on error. Succeeds even if the file
+ contains no .debug_frame. */
+/* XXX: Could use mmap; but elf_map_image keeps tons mapped in. */
+
+static int
+load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local)
+{
+ struct elf_image ei;
+ Elf_W (Shdr) *shdr;
+ int ret;
+
+ ei.image = NULL;
+
+ ret = elf_w (load_debuglink) (file, &ei, is_local);
+ if (ret != 0)
+ return ret;
+
+ shdr = elf_w (find_section) (&ei, ".debug_frame");
+ if (!shdr ||
+ (shdr->sh_offset + shdr->sh_size > ei.size))
+ {
+ munmap(ei.image, ei.size);
+ return 1;
+ }
+
+ *bufsize = shdr->sh_size;
+ *buf = malloc (*bufsize);
+
+ memcpy(*buf, shdr->sh_offset + ei.image, *bufsize);
+
+ Debug (4, "read %zd bytes of .debug_frame from offset %zd\n",
+ *bufsize, shdr->sh_offset);
+
+ munmap(ei.image, ei.size);
+ return 0;
+}
+
+/* Locate the binary which originated the contents of address ADDR. Return
+ the name of the binary in *name (space is allocated by the caller)
+ Returns 0 if a binary is successfully found, or 1 if an error occurs. */
+
+static int
+find_binary_for_address (unw_word_t ip, char *name, size_t name_size)
+{
+#if defined(__linux) && (!UNW_REMOTE_ONLY)
+ struct map_iterator mi;
+ int found = 0;
+ int pid = getpid ();
+ unsigned long segbase, mapoff, hi;
+
+ if (maps_init (&mi, pid) != 0)
+ return 1;
+
+ while (maps_next (&mi, &segbase, &hi, &mapoff))
+ if (ip >= segbase && ip < hi)
+ {
+ size_t len = strlen (mi.path);
+
+ if (len + 1 <= name_size)
+ {
+ memcpy (name, mi.path, len + 1);
+ found = 1;
+ }
+ break;
+ }
+ maps_close (&mi);
+ return !found;
+#endif
+
+ return 1;
+}
+
+/* Locate and/or try to load a debug_frame section for address ADDR. Return
+ pointer to debug frame descriptor, or zero if not found. */
+
+static struct unw_debug_frame_list *
+locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname,
+ unw_word_t start, unw_word_t end)
+{
+ struct unw_debug_frame_list *w, *fdesc = 0;
+ char path[PATH_MAX];
+ char *name = path;
+ int err;
+ char *buf;
+ size_t bufsize;
+
+ /* First, see if we loaded this frame already. */
+
+ for (w = as->debug_frames; w; w = w->next)
+ {
+ Debug (4, "checking %p: %lx-%lx\n", w, (long)w->start, (long)w->end);
+ if (addr >= w->start && addr < w->end)
+ return w;
+ }
+
+ /* If the object name we receive is blank, there's still a chance of locating
+ the file by parsing /proc/self/maps. */
+
+ if (strcmp (dlname, "") == 0)
+ {
+ err = find_binary_for_address (addr, name, sizeof(path));
+ if (err)
+ {
+ Debug (15, "tried to locate binary for 0x%" PRIx64 ", but no luck\n",
+ (uint64_t) addr);
+ return 0;
+ }
+ }
+ else
+ name = (char*) dlname;
+
+ err = load_debug_frame (name, &buf, &bufsize, as == unw_local_addr_space);
+
+ if (!err)
+ {
+ fdesc = malloc (sizeof (struct unw_debug_frame_list));
+
+ fdesc->start = start;
+ fdesc->end = end;
+ fdesc->debug_frame = buf;
+ fdesc->debug_frame_size = bufsize;
+ fdesc->index = NULL;
+ fdesc->next = as->debug_frames;
+
+ as->debug_frames = fdesc;
+ }
+
+ return fdesc;
+}
+
+struct debug_frame_tab
+ {
+ struct table_entry *tab;
+ uint32_t length;
+ uint32_t size;
+ };
+
+static void
+debug_frame_tab_append (struct debug_frame_tab *tab,
+ unw_word_t fde_offset, unw_word_t start_ip)
+{
+ unsigned int length = tab->length;
+
+ if (length == tab->size)
+ {
+ tab->size *= 2;
+ tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->size);
+ }
+
+ tab->tab[length].fde_offset = fde_offset;
+ tab->tab[length].start_ip_offset = start_ip;
+
+ tab->length = length + 1;
+}
+
+static void
+debug_frame_tab_shrink (struct debug_frame_tab *tab)
+{
+ if (tab->size > tab->length)
+ {
+ tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->length);
+ tab->size = tab->length;
+ }
+}
+
+static int
+debug_frame_tab_compare (const void *a, const void *b)
+{
+ const struct table_entry *fa = a, *fb = b;
+
+ if (fa->start_ip_offset > fb->start_ip_offset)
+ return 1;
+ else if (fa->start_ip_offset < fb->start_ip_offset)
+ return -1;
+ else
+ return 0;
+}
+
+HIDDEN int
+dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, unw_word_t ip,
+ unw_word_t segbase, const char* obj_name,
+ unw_word_t start, unw_word_t end)
+{
+ unw_dyn_info_t *di;
+ struct unw_debug_frame_list *fdesc = 0;
+ unw_accessors_t *a;
+ unw_word_t addr;
+
+ Debug (15, "Trying to find .debug_frame for %s\n", obj_name);
+ di = di_debug;
+
+ fdesc = locate_debug_info (unw_local_addr_space, ip, obj_name, start, end);
+
+ if (!fdesc)
+ {
+ Debug (15, "couldn't load .debug_frame\n");
+ return found;
+ }
+ else
+ {
+ char *buf;
+ size_t bufsize;
+ unw_word_t item_start, item_end = 0;
+ uint32_t u32val = 0;
+ uint64_t cie_id = 0;
+ struct debug_frame_tab tab;
+
+ Debug (15, "loaded .debug_frame\n");
+
+ buf = fdesc->debug_frame;
+ bufsize = fdesc->debug_frame_size;
+
+ if (bufsize == 0)
+ {
+ Debug (15, "zero-length .debug_frame\n");
+ return found;
+ }
+
+ /* Now create a binary-search table, if it does not already exist. */
+ if (!fdesc->index)
+ {
+ addr = (unw_word_t) (uintptr_t) buf;
+
+ a = unw_get_accessors_int (unw_local_addr_space);
+
+ /* Find all FDE entries in debug_frame, and make into a sorted
+ index. */
+
+ tab.length = 0;
+ tab.size = 16;
+ tab.tab = calloc (tab.size, sizeof (struct table_entry));
+
+ while (addr < (unw_word_t) (uintptr_t) (buf + bufsize))
+ {
+ uint64_t id_for_cie;
+ item_start = addr;
+
+ dwarf_readu32 (unw_local_addr_space, a, &addr, &u32val, NULL);
+
+ if (u32val == 0)
+ break;
+ else if (u32val != 0xffffffff)
+ {
+ uint32_t cie_id32 = 0;
+ item_end = addr + u32val;
+ dwarf_readu32 (unw_local_addr_space, a, &addr, &cie_id32,
+ NULL);
+ cie_id = cie_id32;
+ id_for_cie = 0xffffffff;
+ }
+ else
+ {
+ uint64_t u64val = 0;
+ /* Extended length. */
+ dwarf_readu64 (unw_local_addr_space, a, &addr, &u64val, NULL);
+ item_end = addr + u64val;
+
+ dwarf_readu64 (unw_local_addr_space, a, &addr, &cie_id, NULL);
+ id_for_cie = 0xffffffffffffffffull;
+ }
+
+ /*Debug (1, "CIE/FDE id = %.8x\n", (int) cie_id);*/
+
+ if (cie_id == id_for_cie)
+ ;
+ /*Debug (1, "Found CIE at %.8x.\n", item_start);*/
+ else
+ {
+ unw_word_t fde_addr = item_start;
+ unw_proc_info_t this_pi;
+ int err;
+
+ /*Debug (1, "Found FDE at %.8x\n", item_start);*/
+
+ err = dwarf_extract_proc_info_from_fde (unw_local_addr_space,
+ a, &fde_addr,
+ &this_pi,
+ (uintptr_t) buf, 0, 1,
+ NULL);
+ if (err == 0)
+ {
+ Debug (15, "start_ip = %lx, end_ip = %lx\n",
+ (long) this_pi.start_ip, (long) this_pi.end_ip);
+ debug_frame_tab_append (&tab,
+ item_start - (unw_word_t) (uintptr_t) buf,
+ this_pi.start_ip);
+ }
+ /*else
+ Debug (1, "FDE parse failed\n");*/
+ }
+
+ addr = item_end;
+ }
+
+ debug_frame_tab_shrink (&tab);
+ qsort (tab.tab, tab.length, sizeof (struct table_entry),
+ debug_frame_tab_compare);
+ /* for (i = 0; i < tab.length; i++)
+ {
+ fprintf (stderr, "ip %x, fde offset %x\n",
+ (int) tab.tab[i].start_ip_offset,
+ (int) tab.tab[i].fde_offset);
+ }*/
+ fdesc->index = tab.tab;
+ fdesc->index_size = tab.length;
+ }
+
+ di->format = UNW_INFO_FORMAT_TABLE;
+ di->start_ip = fdesc->start;
+ di->end_ip = fdesc->end;
+ di->u.ti.name_ptr = (unw_word_t) (uintptr_t) obj_name;
+ di->u.ti.table_data = (unw_word_t *) fdesc;
+ di->u.ti.table_len = sizeof (*fdesc) / sizeof (unw_word_t);
+ di->u.ti.segbase = segbase;
+
+ found = 1;
+ Debug (15, "found debug_frame table `%s': segbase=0x%lx, len=%lu, "
+ "gp=0x%lx, table_data=0x%lx\n",
+ (char *) (uintptr_t) di->u.ti.name_ptr,
+ (long) di->u.ti.segbase, (long) di->u.ti.table_len,
+ (long) di->gp, (long) di->u.ti.table_data);
+ }
+ return found;
+}
+
+#endif /* CONFIG_DEBUG_FRAME */
+
+#ifndef UNW_REMOTE_ONLY
+
+static Elf_W (Addr)
+dwarf_find_eh_frame_section(struct dl_phdr_info *info)
+{
+ int rc;
+ struct elf_image ei;
+ Elf_W (Addr) eh_frame = 0;
+ Elf_W (Shdr)* shdr;
+ const char *file = info->dlpi_name;
+ char exepath[PATH_MAX];
+
+ if (strlen(file) == 0)
+ {
+ tdep_get_exe_image_path(exepath);
+ file = exepath;
+ }
+
+ Debug (1, "looking for .eh_frame section in %s\n",
+ file);
+
+ rc = elf_map_image (&ei, file);
+ if (rc != 0)
+ return 0;
+
+ shdr = elf_w (find_section) (&ei, ".eh_frame");
+ if (!shdr)
+ goto out;
+
+ eh_frame = shdr->sh_addr + info->dlpi_addr;
+ Debug (4, "found .eh_frame at address %lx\n",
+ eh_frame);
+
+out:
+ munmap (ei.image, ei.size);
+
+ return eh_frame;
+}
+
+struct dwarf_callback_data
+ {
+ /* in: */
+ unw_word_t ip; /* instruction-pointer we're looking for */
+ unw_proc_info_t *pi; /* proc-info pointer */
+ int need_unwind_info;
+ /* out: */
+ int single_fde; /* did we find a single FDE? (vs. a table) */
+ unw_dyn_info_t di; /* table info (if single_fde is false) */
+ unw_dyn_info_t di_debug; /* additional table info for .debug_frame */
+ };
+
+/* ptr is a pointer to a dwarf_callback_data structure and, on entry,
+ member ip contains the instruction-pointer we're looking
+ for. */
+HIDDEN int
+dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
+{
+ struct dwarf_callback_data *cb_data = ptr;
+ unw_dyn_info_t *di = &cb_data->di;
+ const Elf_W(Phdr) *phdr, *p_eh_hdr, *p_dynamic, *p_text;
+ unw_word_t addr, eh_frame_start, eh_frame_end, fde_count, ip;
+ Elf_W(Addr) load_base, max_load_addr = 0;
+ int ret, need_unwind_info = cb_data->need_unwind_info;
+ unw_proc_info_t *pi = cb_data->pi;
+ struct dwarf_eh_frame_hdr *hdr = NULL;
+ unw_accessors_t *a;
+ long n;
+ int found = 0;
+ struct dwarf_eh_frame_hdr synth_eh_frame_hdr;
+#ifdef CONFIG_DEBUG_FRAME
+ unw_word_t start, end;
+#endif /* CONFIG_DEBUG_FRAME*/
+
+ ip = cb_data->ip;
+
+ /* Make sure struct dl_phdr_info is at least as big as we need. */
+ if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
+ + sizeof (info->dlpi_phnum))
+ return -1;
+
+ Debug (15, "checking %s, base=0x%lx)\n",
+ info->dlpi_name, (long) info->dlpi_addr);
+
+ phdr = info->dlpi_phdr;
+ load_base = info->dlpi_addr;
+ p_text = NULL;
+ p_eh_hdr = NULL;
+ p_dynamic = NULL;
+
+ /* See if PC falls into one of the loaded segments. Find the
+ eh-header segment at the same time. */
+ for (n = info->dlpi_phnum; --n >= 0; phdr++)
+ {
+ if (phdr->p_type == PT_LOAD)
+ {
+ Elf_W(Addr) vaddr = phdr->p_vaddr + load_base;
+
+ if (ip >= vaddr && ip < vaddr + phdr->p_memsz)
+ p_text = phdr;
+
+ if (vaddr + phdr->p_filesz > max_load_addr)
+ max_load_addr = vaddr + phdr->p_filesz;
+ }
+ else if (phdr->p_type == PT_GNU_EH_FRAME)
+ p_eh_hdr = phdr;
+ else if (phdr->p_type == PT_DYNAMIC)
+ p_dynamic = phdr;
+ }
+
+ if (!p_text)
+ return 0;
+
+ if (p_eh_hdr)
+ {
+ hdr = (struct dwarf_eh_frame_hdr *) (p_eh_hdr->p_vaddr + load_base);
+ }
+ else
+ {
+ Elf_W (Addr) eh_frame;
+ Debug (1, "no .eh_frame_hdr section found\n");
+ eh_frame = dwarf_find_eh_frame_section (info);
+ if (eh_frame)
+ {
+ Debug (1, "using synthetic .eh_frame_hdr section for %s\n",
+ info->dlpi_name);
+ synth_eh_frame_hdr.version = DW_EH_VERSION;
+ synth_eh_frame_hdr.eh_frame_ptr_enc = DW_EH_PE_absptr |
+ ((sizeof(Elf_W (Addr)) == 4) ? DW_EH_PE_udata4 : DW_EH_PE_udata8);
+ synth_eh_frame_hdr.fde_count_enc = DW_EH_PE_omit;
+ synth_eh_frame_hdr.table_enc = DW_EH_PE_omit;
+ synth_eh_frame_hdr.eh_frame = eh_frame;
+ hdr = &synth_eh_frame_hdr;
+ }
+ }
+
+ if (hdr)
+ {
+ if (p_dynamic)
+ {
+ /* For dynamicly linked executables and shared libraries,
+ DT_PLTGOT is the value that data-relative addresses are
+ relative to for that object. We call this the "gp". */
+ Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(p_dynamic->p_vaddr + load_base);
+ for (; dyn->d_tag != DT_NULL; ++dyn)
+ if (dyn->d_tag == DT_PLTGOT)
+ {
+ /* Assume that _DYNAMIC is writable and GLIBC has
+ relocated it (true for x86 at least). */
+ di->gp = dyn->d_un.d_ptr;
+ break;
+ }
+ }
+ else
+ /* Otherwise this is a static executable with no _DYNAMIC. Assume
+ that data-relative addresses are relative to 0, i.e.,
+ absolute. */
+ di->gp = 0;
+ pi->gp = di->gp;
+
+ if (hdr->version != DW_EH_VERSION)
+ {
+ Debug (1, "table `%s' has unexpected version %d\n",
+ info->dlpi_name, hdr->version);
+ return 0;
+ }
+
+ a = unw_get_accessors_int (unw_local_addr_space);
+ addr = (unw_word_t) (uintptr_t) (&hdr->eh_frame);
+
+ /* (Optionally) read eh_frame_ptr: */
+ if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
+ &addr, hdr->eh_frame_ptr_enc, pi,
+ &eh_frame_start, NULL)) < 0)
+ return ret;
+
+ /* (Optionally) read fde_count: */
+ if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
+ &addr, hdr->fde_count_enc, pi,
+ &fde_count, NULL)) < 0)
+ return ret;
+
+ if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
+ {
+ /* If there is no search table or it has an unsupported
+ encoding, fall back on linear search. */
+ if (hdr->table_enc == DW_EH_PE_omit)
+ Debug (4, "table `%s' lacks search table; doing linear search\n",
+ info->dlpi_name);
+ else
+ Debug (4, "table `%s' has encoding 0x%x; doing linear search\n",
+ info->dlpi_name, hdr->table_enc);
+
+ eh_frame_end = max_load_addr; /* XXX can we do better? */
+
+ if (hdr->fde_count_enc == DW_EH_PE_omit)
+ fde_count = ~0UL;
+ if (hdr->eh_frame_ptr_enc == DW_EH_PE_omit)
+ abort ();
+
+ Debug (1, "eh_frame_start = %lx eh_frame_end = %lx\n",
+ eh_frame_start, eh_frame_end);
+
+ /* XXX we know how to build a local binary search table for
+ .debug_frame, so we could do that here too. */
+ found = linear_search (unw_local_addr_space, ip,
+ eh_frame_start, eh_frame_end, fde_count,
+ pi, need_unwind_info, NULL);
+ if (found != 1)
+ found = 0;
+ else
+ cb_data->single_fde = 1;
+ }
+ else
+ {
+ di->format = UNW_INFO_FORMAT_REMOTE_TABLE;
+ di->start_ip = p_text->p_vaddr + load_base;
+ di->end_ip = p_text->p_vaddr + load_base + p_text->p_memsz;
+ di->u.rti.name_ptr = (unw_word_t) (uintptr_t) info->dlpi_name;
+ di->u.rti.table_data = addr;
+ assert (sizeof (struct table_entry) % sizeof (unw_word_t) == 0);
+ di->u.rti.table_len = (fde_count * sizeof (struct table_entry)
+ / sizeof (unw_word_t));
+ /* For the binary-search table in the eh_frame_hdr, data-relative
+ means relative to the start of that section... */
+ di->u.rti.segbase = (unw_word_t) (uintptr_t) hdr;
+
+ found = 1;
+ Debug (15, "found table `%s': segbase=0x%lx, len=%lu, gp=0x%lx, "
+ "table_data=0x%lx\n", (char *) (uintptr_t) di->u.rti.name_ptr,
+ (long) di->u.rti.segbase, (long) di->u.rti.table_len,
+ (long) di->gp, (long) di->u.rti.table_data);
+ }
+ }
+
+#ifdef CONFIG_DEBUG_FRAME
+ /* Find the start/end of the described region by parsing the phdr_info
+ structure. */
+ start = (unw_word_t) -1;
+ end = 0;
+
+ for (n = 0; n < info->dlpi_phnum; n++)
+ {
+ if (info->dlpi_phdr[n].p_type == PT_LOAD)
+ {
+ unw_word_t seg_start = info->dlpi_addr + info->dlpi_phdr[n].p_vaddr;
+ unw_word_t seg_end = seg_start + info->dlpi_phdr[n].p_memsz;
+
+ if (seg_start < start)
+ start = seg_start;
+
+ if (seg_end > end)
+ end = seg_end;
+ }
+ }
+
+ found = dwarf_find_debug_frame (found, &cb_data->di_debug, ip,
+ info->dlpi_addr, info->dlpi_name, start,
+ end);
+#endif /* CONFIG_DEBUG_FRAME */
+
+ return found;
+}
+
+HIDDEN int
+dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
+ unw_proc_info_t *pi, int need_unwind_info, void *arg)
+{
+ struct dwarf_callback_data cb_data;
+ intrmask_t saved_mask;
+ int ret;
+
+ Debug (14, "looking for IP=0x%lx\n", (long) ip);
+
+ memset (&cb_data, 0, sizeof (cb_data));
+ cb_data.ip = ip;
+ cb_data.pi = pi;
+ cb_data.need_unwind_info = need_unwind_info;
+ cb_data.di.format = -1;
+ cb_data.di_debug.format = -1;
+
+ SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask);
+ ret = dl_iterate_phdr (dwarf_callback, &cb_data);
+ SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
+
+ if (ret > 0)
+ {
+ if (cb_data.single_fde)
+ /* already got the result in *pi */
+ return 0;
+
+ /* search the table: */
+ if (cb_data.di.format != -1)
+ ret = dwarf_search_unwind_table_int (as, ip, &cb_data.di,
+ pi, need_unwind_info, arg);
+ else
+ ret = -UNW_ENOINFO;
+
+ if (ret == -UNW_ENOINFO && cb_data.di_debug.format != -1)
+ ret = dwarf_search_unwind_table_int (as, ip, &cb_data.di_debug, pi,
+ need_unwind_info, arg);
+ }
+ else
+ ret = -UNW_ENOINFO;
+
+ return ret;
+}
+
+static inline const struct table_entry *
+lookup (const struct table_entry *table, size_t table_size, int32_t rel_ip)
+{
+ unsigned long table_len = table_size / sizeof (struct table_entry);
+ const struct table_entry *e = NULL;
+ unsigned long lo, hi, mid;
+
+ /* do a binary search for right entry: */
+ for (lo = 0, hi = table_len; lo < hi;)
+ {
+ mid = (lo + hi) / 2;
+ e = table + mid;
+ Debug (15, "e->start_ip_offset = %lx\n", (long) e->start_ip_offset);
+ if (rel_ip < e->start_ip_offset)
+ hi = mid;
+ else
+ lo = mid + 1;
+ }
+ if (hi <= 0)
+ return NULL;
+ e = table + hi - 1;
+ return e;
+}
+
+#endif /* !UNW_REMOTE_ONLY */
+
+#ifndef UNW_LOCAL_ONLY
+
+/* Lookup an unwind-table entry in remote memory. Returns 1 if an
+ entry is found, 0 if no entry is found, negative if an error
+ occurred reading remote memory. */
+static int
+remote_lookup (unw_addr_space_t as,
+ unw_word_t table, size_t table_size, int32_t rel_ip,
+ struct table_entry *e, int32_t *last_ip_offset, void *arg)
+{
+ unsigned long table_len = table_size / sizeof (struct table_entry);
+ unw_accessors_t *a = unw_get_accessors_int (as);
+ unsigned long lo, hi, mid;
+ unw_word_t e_addr = 0;
+ int32_t start = 0;
+ int ret;
+
+ /* do a binary search for right entry: */
+ for (lo = 0, hi = table_len; lo < hi;)
+ {
+ mid = (lo + hi) / 2;
+ e_addr = table + mid * sizeof (struct table_entry);
+ if ((ret = dwarf_reads32 (as, a, &e_addr, &start, arg)) < 0)
+ return ret;
+
+ if (rel_ip < start)
+ hi = mid;
+ else
+ lo = mid + 1;
+ }
+ if (hi <= 0)
+ return 0;
+ e_addr = table + (hi - 1) * sizeof (struct table_entry);
+ if ((ret = dwarf_reads32 (as, a, &e_addr, &e->start_ip_offset, arg)) < 0
+ || (ret = dwarf_reads32 (as, a, &e_addr, &e->fde_offset, arg)) < 0
+ || (hi < table_len &&
+ (ret = dwarf_reads32 (as, a, &e_addr, last_ip_offset, arg)) < 0))
+ return ret;
+ return 1;
+}
+
+#endif /* !UNW_LOCAL_ONLY */
+
+static int is_remote_table(int format)
+{
+ return (format == UNW_INFO_FORMAT_REMOTE_TABLE ||
+ format == UNW_INFO_FORMAT_IP_OFFSET);
+}
+
+int
+dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
+ unw_dyn_info_t *di, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg)
+{
+ const struct table_entry *e = NULL, *table;
+ unw_word_t ip_base = 0, segbase = 0, last_ip, fde_addr;
+ unw_accessors_t *a;
+#ifndef UNW_LOCAL_ONLY
+ struct table_entry ent;
+#endif
+ int ret;
+ unw_word_t debug_frame_base;
+ size_t table_len;
+
+#ifdef UNW_REMOTE_ONLY
+ assert (is_remote_table(di->format));
+#else
+ assert (is_remote_table(di->format)
+ || di->format == UNW_INFO_FORMAT_TABLE);
+#endif
+ assert (ip >= di->start_ip && ip < di->end_ip);
+
+ if (is_remote_table(di->format))
+ {
+ table = (const struct table_entry *) (uintptr_t) di->u.rti.table_data;
+ table_len = di->u.rti.table_len * sizeof (unw_word_t);
+ debug_frame_base = 0;
+ }
+ else
+ {
+ assert(di->format == UNW_INFO_FORMAT_TABLE);
+#ifndef UNW_REMOTE_ONLY
+ struct unw_debug_frame_list *fdesc = (void *) di->u.ti.table_data;
+
+ /* UNW_INFO_FORMAT_TABLE (i.e. .debug_frame) is read from local address
+ space. Both the index and the unwind tables live in local memory, but
+ the address space to check for properties like the address size and
+ endianness is the target one. */
+ as = unw_local_addr_space;
+ table = fdesc->index;
+ table_len = fdesc->index_size * sizeof (struct table_entry);
+ debug_frame_base = (uintptr_t) fdesc->debug_frame;
+#endif
+ }
+
+ a = unw_get_accessors_int (as);
+
+ segbase = di->u.rti.segbase;
+ if (di->format == UNW_INFO_FORMAT_IP_OFFSET) {
+ ip_base = di->start_ip;
+ } else {
+ ip_base = segbase;
+ }
+
+#ifndef UNW_REMOTE_ONLY
+ if (as == unw_local_addr_space)
+ {
+ e = lookup (table, table_len, ip - ip_base);
+ if (e && &e[1] < &table[table_len])
+ last_ip = e[1].start_ip_offset + ip_base;
+ else
+ last_ip = di->end_ip;
+ }
+ else
+#endif
+ {
+#ifndef UNW_LOCAL_ONLY
+ int32_t last_ip_offset = di->end_ip - ip_base;
+ segbase = di->u.rti.segbase;
+ if ((ret = remote_lookup (as, (uintptr_t) table, table_len,
+ ip - ip_base, &ent, &last_ip_offset, arg)) < 0)
+ return ret;
+ if (ret)
+ {
+ e = &ent;
+ last_ip = last_ip_offset + ip_base;
+ }
+ else
+ e = NULL; /* no info found */
+#endif
+ }
+ if (!e)
+ {
+ Debug (1, "IP %lx inside range %lx-%lx, but no explicit unwind info found\n",
+ (long) ip, (long) di->start_ip, (long) di->end_ip);
+ /* IP is inside this table's range, but there is no explicit
+ unwind info. */
+ return -UNW_ENOINFO;
+ }
+ Debug (15, "ip=0x%lx, start_ip=0x%lx\n",
+ (long) ip, (long) (e->start_ip_offset));
+ if (debug_frame_base)
+ fde_addr = e->fde_offset + debug_frame_base;
+ else
+ fde_addr = e->fde_offset + segbase;
+ Debug (1, "e->fde_offset = %lx, segbase = %lx, debug_frame_base = %lx, "
+ "fde_addr = %lx\n", (long) e->fde_offset, (long) segbase,
+ (long) debug_frame_base, (long) fde_addr);
+ if ((ret = dwarf_extract_proc_info_from_fde (as, a, &fde_addr, pi,
+ debug_frame_base ?
+ debug_frame_base : segbase,
+ need_unwind_info,
+ debug_frame_base != 0, arg)) < 0)
+ return ret;
+
+ /* .debug_frame uses an absolute encoding that does not know about any
+ shared library relocation. */
+ if (di->format == UNW_INFO_FORMAT_TABLE)
+ {
+ pi->start_ip += segbase;
+ pi->end_ip += segbase;
+ pi->flags = UNW_PI_FLAG_DEBUG_FRAME;
+ }
+
+#if defined(NEED_LAST_IP)
+ pi->last_ip = last_ip;
+#else
+ (void)last_ip;
+#endif
+ if (ip < pi->start_ip || ip >= pi->end_ip)
+ return -UNW_ENOINFO;
+
+ return 0;
+}
+
+HIDDEN void
+dwarf_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg)
+{
+ return; /* always a nop */
+}
diff --git a/src/pal/src/libunwind/src/dwarf/Gfind_unwind_table.c b/src/pal/src/libunwind/src/dwarf/Gfind_unwind_table.c
new file mode 100644
index 0000000000..6a2ad50407
--- /dev/null
+++ b/src/pal/src/libunwind/src/dwarf/Gfind_unwind_table.c
@@ -0,0 +1,230 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+
+#include "libunwind_i.h"
+#include "dwarf-eh.h"
+#include "dwarf_i.h"
+
+#define to_unw_word(p) ((unw_word_t) (uintptr_t) (p))
+
+int
+dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
+ char *path, unw_word_t segbase, unw_word_t mapoff,
+ unw_word_t ip)
+{
+ Elf_W(Phdr) *phdr, *ptxt = NULL, *peh_hdr = NULL, *pdyn = NULL;
+ unw_word_t addr, eh_frame_start, fde_count, load_base;
+ unw_word_t max_load_addr = 0;
+ unw_word_t start_ip = to_unw_word (-1);
+ unw_word_t end_ip = 0;
+ struct dwarf_eh_frame_hdr *hdr;
+ unw_proc_info_t pi;
+ unw_accessors_t *a;
+ Elf_W(Ehdr) *ehdr;
+#if UNW_TARGET_ARM
+ const Elf_W(Phdr) *parm_exidx = NULL;
+#endif
+ int i, ret, found = 0;
+
+ /* XXX: Much of this code is Linux/LSB-specific. */
+
+ if (!elf_w(valid_object) (&edi->ei))
+ return -UNW_ENOINFO;
+
+ ehdr = edi->ei.image;
+ phdr = (Elf_W(Phdr) *) ((char *) edi->ei.image + ehdr->e_phoff);
+
+ for (i = 0; i < ehdr->e_phnum; ++i)
+ {
+ switch (phdr[i].p_type)
+ {
+ case PT_LOAD:
+ if (phdr[i].p_vaddr < start_ip)
+ start_ip = phdr[i].p_vaddr;
+
+ if (phdr[i].p_vaddr + phdr[i].p_memsz > end_ip)
+ end_ip = phdr[i].p_vaddr + phdr[i].p_memsz;
+
+ if (phdr[i].p_offset == mapoff)
+ ptxt = phdr + i;
+ if ((uintptr_t) edi->ei.image + phdr->p_filesz > max_load_addr)
+ max_load_addr = (uintptr_t) edi->ei.image + phdr->p_filesz;
+ break;
+
+ case PT_GNU_EH_FRAME:
+ peh_hdr = phdr + i;
+ break;
+
+ case PT_DYNAMIC:
+ pdyn = phdr + i;
+ break;
+
+#if UNW_TARGET_ARM
+ case PT_ARM_EXIDX:
+ parm_exidx = phdr + i;
+ break;
+#endif
+
+ default:
+ break;
+ }
+ }
+
+ if (!ptxt)
+ return 0;
+
+ load_base = segbase - ptxt->p_vaddr;
+ start_ip += load_base;
+ end_ip += load_base;
+
+ if (peh_hdr)
+ {
+ if (pdyn)
+ {
+ /* For dynamicly linked executables and shared libraries,
+ DT_PLTGOT is the value that data-relative addresses are
+ relative to for that object. We call this the "gp". */
+ Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(pdyn->p_offset
+ + (char *) edi->ei.image);
+ for (; dyn->d_tag != DT_NULL; ++dyn)
+ if (dyn->d_tag == DT_PLTGOT)
+ {
+ /* Assume that _DYNAMIC is writable and GLIBC has
+ relocated it (true for x86 at least). */
+ edi->di_cache.gp = dyn->d_un.d_ptr;
+ break;
+ }
+ }
+ else
+ /* Otherwise this is a static executable with no _DYNAMIC. Assume
+ that data-relative addresses are relative to 0, i.e.,
+ absolute. */
+ edi->di_cache.gp = 0;
+
+ hdr = (struct dwarf_eh_frame_hdr *) (peh_hdr->p_offset
+ + (char *) edi->ei.image);
+ if (hdr->version != DW_EH_VERSION)
+ {
+ Debug (1, "table `%s' has unexpected version %d\n",
+ path, hdr->version);
+ return -UNW_ENOINFO;
+ }
+
+ a = unw_get_accessors_int (unw_local_addr_space);
+ addr = to_unw_word (&hdr->eh_frame);
+
+ /* Fill in a dummy proc_info structure. We just need to fill in
+ enough to ensure that dwarf_read_encoded_pointer() can do it's
+ job. Since we don't have a procedure-context at this point, all
+ we have to do is fill in the global-pointer. */
+ memset (&pi, 0, sizeof (pi));
+ pi.gp = edi->di_cache.gp;
+
+ /* (Optionally) read eh_frame_ptr: */
+ if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
+ &addr, hdr->eh_frame_ptr_enc, &pi,
+ &eh_frame_start, NULL)) < 0)
+ return -UNW_ENOINFO;
+
+ /* (Optionally) read fde_count: */
+ if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
+ &addr, hdr->fde_count_enc, &pi,
+ &fde_count, NULL)) < 0)
+ return -UNW_ENOINFO;
+
+ if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
+ {
+ #if 1
+ abort ();
+ #else
+ unw_word_t eh_frame_end;
+
+ /* If there is no search table or it has an unsupported
+ encoding, fall back on linear search. */
+ if (hdr->table_enc == DW_EH_PE_omit)
+ Debug (4, "EH lacks search table; doing linear search\n");
+ else
+ Debug (4, "EH table has encoding 0x%x; doing linear search\n",
+ hdr->table_enc);
+
+ eh_frame_end = max_load_addr; /* XXX can we do better? */
+
+ if (hdr->fde_count_enc == DW_EH_PE_omit)
+ fde_count = ~0UL;
+ if (hdr->eh_frame_ptr_enc == DW_EH_PE_omit)
+ abort ();
+
+ return linear_search (unw_local_addr_space, ip,
+ eh_frame_start, eh_frame_end, fde_count,
+ pi, need_unwind_info, NULL);
+ #endif
+ }
+
+ edi->di_cache.start_ip = start_ip;
+ edi->di_cache.end_ip = end_ip;
+ edi->di_cache.format = UNW_INFO_FORMAT_REMOTE_TABLE;
+ edi->di_cache.u.rti.name_ptr = 0;
+ /* two 32-bit values (ip_offset/fde_offset) per table-entry: */
+ edi->di_cache.u.rti.table_len = (fde_count * 8) / sizeof (unw_word_t);
+ edi->di_cache.u.rti.table_data = ((load_base + peh_hdr->p_vaddr)
+ + (addr - to_unw_word (edi->ei.image)
+ - peh_hdr->p_offset));
+
+ /* For the binary-search table in the eh_frame_hdr, data-relative
+ means relative to the start of that section... */
+ edi->di_cache.u.rti.segbase = ((load_base + peh_hdr->p_vaddr)
+ + (to_unw_word (hdr) -
+ to_unw_word (edi->ei.image)
+ - peh_hdr->p_offset));
+ found = 1;
+ }
+
+#if UNW_TARGET_ARM
+ if (parm_exidx)
+ {
+ edi->di_arm.format = UNW_INFO_FORMAT_ARM_EXIDX;
+ edi->di_arm.start_ip = start_ip;
+ edi->di_arm.end_ip = end_ip;
+ edi->di_arm.u.rti.name_ptr = to_unw_word (path);
+ edi->di_arm.u.rti.table_data = load_base + parm_exidx->p_vaddr;
+ edi->di_arm.u.rti.table_len = parm_exidx->p_memsz;
+ found = 1;
+ }
+#endif
+
+#ifdef CONFIG_DEBUG_FRAME
+ /* Try .debug_frame. */
+ found = dwarf_find_debug_frame (found, &edi->di_debug, ip, load_base, path,
+ start_ip, end_ip);
+#endif
+
+ return found;
+}
diff --git a/src/pal/src/libunwind/src/dwarf/Gparser.c b/src/pal/src/libunwind/src/dwarf/Gparser.c
new file mode 100644
index 0000000000..7d255aeeaf
--- /dev/null
+++ b/src/pal/src/libunwind/src/dwarf/Gparser.c
@@ -0,0 +1,1059 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "dwarf_i.h"
+#include "libunwind_i.h"
+#include <stddef.h>
+#include <limits.h>
+
+#define alloc_reg_state() (mempool_alloc (&dwarf_reg_state_pool))
+#define free_reg_state(rs) (mempool_free (&dwarf_reg_state_pool, rs))
+
+#define DWARF_UNW_CACHE_SIZE(log_size) (1 << log_size)
+#define DWARF_UNW_HASH_SIZE(log_size) (1 << (log_size + 1))
+
+static inline int
+read_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ unw_word_t *valp, void *arg)
+{
+ int ret;
+
+ if ((ret = dwarf_read_uleb128 (as, a, addr, valp, arg)) < 0)
+ return ret;
+
+ if (*valp >= DWARF_NUM_PRESERVED_REGS)
+ {
+ Debug (1, "Invalid register number %u\n", (unsigned int) *valp);
+ return -UNW_EBADREG;
+ }
+ return 0;
+}
+
+static inline void
+set_reg (dwarf_state_record_t *sr, unw_word_t regnum, dwarf_where_t where,
+ unw_word_t val)
+{
+ sr->rs_current.reg.where[regnum] = where;
+ sr->rs_current.reg.val[regnum] = val;
+}
+
+static inline int
+push_rstate_stack(dwarf_stackable_reg_state_t **rs_stack)
+{
+ dwarf_stackable_reg_state_t *old_rs = *rs_stack;
+ if (NULL == (*rs_stack = alloc_reg_state ()))
+ {
+ *rs_stack = old_rs;
+ return -1;
+ }
+ (*rs_stack)->next = old_rs;
+ return 0;
+}
+
+static inline void
+pop_rstate_stack(dwarf_stackable_reg_state_t **rs_stack)
+{
+ dwarf_stackable_reg_state_t *old_rs = *rs_stack;
+ *rs_stack = old_rs->next;
+ free_reg_state (old_rs);
+}
+
+static inline void
+empty_rstate_stack(dwarf_stackable_reg_state_t **rs_stack)
+{
+ while (*rs_stack)
+ pop_rstate_stack(rs_stack);
+}
+
+/* Run a CFI program to update the register state. */
+static int
+run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
+ unw_word_t *ip, unw_word_t end_ip,
+ unw_word_t *addr, unw_word_t end_addr,
+ dwarf_stackable_reg_state_t **rs_stack,
+ struct dwarf_cie_info *dci)
+{
+ unw_addr_space_t as;
+ void *arg;
+
+ if (c->pi.flags & UNW_PI_FLAG_DEBUG_FRAME)
+ {
+ /* .debug_frame CFI is stored in local address space. */
+ as = unw_local_addr_space;
+ arg = NULL;
+ }
+ else
+ {
+ as = c->as;
+ arg = c->as_arg;
+ }
+ unw_accessors_t *a = unw_get_accessors_int (as);
+ int ret = 0;
+
+ while (*ip <= end_ip && *addr < end_addr && ret >= 0)
+ {
+ unw_word_t operand = 0, regnum, val, len;
+ uint8_t u8, op;
+ uint16_t u16;
+ uint32_t u32;
+
+ if ((ret = dwarf_readu8 (as, a, addr, &op, arg)) < 0)
+ break;
+
+ if (op & DWARF_CFA_OPCODE_MASK)
+ {
+ operand = op & DWARF_CFA_OPERAND_MASK;
+ op &= ~DWARF_CFA_OPERAND_MASK;
+ }
+ switch ((dwarf_cfa_t) op)
+ {
+ case DW_CFA_advance_loc:
+ *ip += operand * dci->code_align;
+ Debug (15, "CFA_advance_loc to 0x%lx\n", (long) *ip);
+ break;
+
+ case DW_CFA_advance_loc1:
+ if ((ret = dwarf_readu8 (as, a, addr, &u8, arg)) < 0)
+ break;
+ *ip += u8 * dci->code_align;
+ Debug (15, "CFA_advance_loc1 to 0x%lx\n", (long) *ip);
+ break;
+
+ case DW_CFA_advance_loc2:
+ if ((ret = dwarf_readu16 (as, a, addr, &u16, arg)) < 0)
+ break;
+ *ip += u16 * dci->code_align;
+ Debug (15, "CFA_advance_loc2 to 0x%lx\n", (long) *ip);
+ break;
+
+ case DW_CFA_advance_loc4:
+ if ((ret = dwarf_readu32 (as, a, addr, &u32, arg)) < 0)
+ break;
+ *ip += u32 * dci->code_align;
+ Debug (15, "CFA_advance_loc4 to 0x%lx\n", (long) *ip);
+ break;
+
+ case DW_CFA_MIPS_advance_loc8:
+#ifdef UNW_TARGET_MIPS
+ {
+ uint64_t u64 = 0;
+
+ if ((ret = dwarf_readu64 (as, a, addr, &u64, arg)) < 0)
+ break;
+ *ip += u64 * dci->code_align;
+ Debug (15, "CFA_MIPS_advance_loc8\n");
+ break;
+ }
+#else
+ Debug (1, "DW_CFA_MIPS_advance_loc8 on non-MIPS target\n");
+ ret = -UNW_EINVAL;
+ break;
+#endif
+
+ case DW_CFA_offset:
+ regnum = operand;
+ if (regnum >= DWARF_NUM_PRESERVED_REGS)
+ {
+ Debug (1, "Invalid register number %u in DW_cfa_OFFSET\n",
+ (unsigned int) regnum);
+ ret = -UNW_EBADREG;
+ break;
+ }
+ if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
+ break;
+ set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
+ Debug (15, "CFA_offset r%lu at cfa+0x%lx\n",
+ (long) regnum, (long) (val * dci->data_align));
+ break;
+
+ case DW_CFA_offset_extended:
+ if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
+ || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
+ break;
+ set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
+ Debug (15, "CFA_offset_extended r%lu at cf+0x%lx\n",
+ (long) regnum, (long) (val * dci->data_align));
+ break;
+
+ case DW_CFA_offset_extended_sf:
+ if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
+ || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0))
+ break;
+ set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
+ Debug (15, "CFA_offset_extended_sf r%lu at cf+0x%lx\n",
+ (long) regnum, (long) (val * dci->data_align));
+ break;
+
+ case DW_CFA_restore:
+ regnum = operand;
+ if (regnum >= DWARF_NUM_PRESERVED_REGS)
+ {
+ Debug (1, "Invalid register number %u in DW_CFA_restore\n",
+ (unsigned int) regnum);
+ ret = -UNW_EINVAL;
+ break;
+ }
+ sr->rs_current.reg.where[regnum] = sr->rs_initial.reg.where[regnum];
+ sr->rs_current.reg.val[regnum] = sr->rs_initial.reg.val[regnum];
+ Debug (15, "CFA_restore r%lu\n", (long) regnum);
+ break;
+
+ case DW_CFA_restore_extended:
+ if ((ret = dwarf_read_uleb128 (as, a, addr, &regnum, arg)) < 0)
+ break;
+ if (regnum >= DWARF_NUM_PRESERVED_REGS)
+ {
+ Debug (1, "Invalid register number %u in "
+ "DW_CFA_restore_extended\n", (unsigned int) regnum);
+ ret = -UNW_EINVAL;
+ break;
+ }
+ sr->rs_current.reg.where[regnum] = sr->rs_initial.reg.where[regnum];
+ sr->rs_current.reg.val[regnum] = sr->rs_initial.reg.val[regnum];
+ Debug (15, "CFA_restore_extended r%lu\n", (long) regnum);
+ break;
+
+ case DW_CFA_nop:
+ break;
+
+ case DW_CFA_set_loc:
+ if ((ret = dwarf_read_encoded_pointer (as, a, addr, dci->fde_encoding,
+ &c->pi, ip,
+ arg)) < 0)
+ break;
+ Debug (15, "CFA_set_loc to 0x%lx\n", (long) *ip);
+ break;
+
+ case DW_CFA_undefined:
+ if ((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
+ break;
+ set_reg (sr, regnum, DWARF_WHERE_UNDEF, 0);
+ Debug (15, "CFA_undefined r%lu\n", (long) regnum);
+ break;
+
+ case DW_CFA_same_value:
+ if ((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
+ break;
+ set_reg (sr, regnum, DWARF_WHERE_SAME, 0);
+ Debug (15, "CFA_same_value r%lu\n", (long) regnum);
+ break;
+
+ case DW_CFA_register:
+ if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
+ || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
+ break;
+ set_reg (sr, regnum, DWARF_WHERE_REG, val);
+ Debug (15, "CFA_register r%lu to r%lu\n", (long) regnum, (long) val);
+ break;
+
+ case DW_CFA_remember_state:
+ if (push_rstate_stack(rs_stack) < 0)
+ {
+ Debug (1, "Out of memory in DW_CFA_remember_state\n");
+ ret = -UNW_ENOMEM;
+ break;
+ }
+ (*rs_stack)->state = sr->rs_current;
+ Debug (15, "CFA_remember_state\n");
+ break;
+
+ case DW_CFA_restore_state:
+ if (!*rs_stack)
+ {
+ Debug (1, "register-state stack underflow\n");
+ ret = -UNW_EINVAL;
+ break;
+ }
+ sr->rs_current = (*rs_stack)->state;
+ pop_rstate_stack(rs_stack);
+ Debug (15, "CFA_restore_state\n");
+ break;
+
+ case DW_CFA_def_cfa:
+ if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
+ || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
+ break;
+ set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
+ set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val); /* NOT factored! */
+ Debug (15, "CFA_def_cfa r%lu+0x%lx\n", (long) regnum, (long) val);
+ break;
+
+ case DW_CFA_def_cfa_sf:
+ if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
+ || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0))
+ break;
+ set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
+ set_reg (sr, DWARF_CFA_OFF_COLUMN, 0,
+ val * dci->data_align); /* factored! */
+ Debug (15, "CFA_def_cfa_sf r%lu+0x%lx\n",
+ (long) regnum, (long) (val * dci->data_align));
+ break;
+
+ case DW_CFA_def_cfa_register:
+ if ((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
+ break;
+ set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
+ Debug (15, "CFA_def_cfa_register r%lu\n", (long) regnum);
+ break;
+
+ case DW_CFA_def_cfa_offset:
+ if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
+ break;
+ set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val); /* NOT factored! */
+ Debug (15, "CFA_def_cfa_offset 0x%lx\n", (long) val);
+ break;
+
+ case DW_CFA_def_cfa_offset_sf:
+ if ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0)
+ break;
+ set_reg (sr, DWARF_CFA_OFF_COLUMN, 0,
+ val * dci->data_align); /* factored! */
+ Debug (15, "CFA_def_cfa_offset_sf 0x%lx\n",
+ (long) (val * dci->data_align));
+ break;
+
+ case DW_CFA_def_cfa_expression:
+ /* Save the address of the DW_FORM_block for later evaluation. */
+ set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_EXPR, *addr);
+
+ if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0)
+ break;
+
+ Debug (15, "CFA_def_cfa_expr @ 0x%lx [%lu bytes]\n",
+ (long) *addr, (long) len);
+ *addr += len;
+ break;
+
+ case DW_CFA_expression:
+ if ((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
+ break;
+
+ /* Save the address of the DW_FORM_block for later evaluation. */
+ set_reg (sr, regnum, DWARF_WHERE_EXPR, *addr);
+
+ if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0)
+ break;
+
+ Debug (15, "CFA_expression r%lu @ 0x%lx [%lu bytes]\n",
+ (long) regnum, (long) addr, (long) len);
+ *addr += len;
+ break;
+
+ case DW_CFA_val_expression:
+ if ((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
+ break;
+
+ /* Save the address of the DW_FORM_block for later evaluation. */
+ set_reg (sr, regnum, DWARF_WHERE_VAL_EXPR, *addr);
+
+ if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0)
+ break;
+
+ Debug (15, "CFA_val_expression r%lu @ 0x%lx [%lu bytes]\n",
+ (long) regnum, (long) addr, (long) len);
+ *addr += len;
+ break;
+
+ case DW_CFA_GNU_args_size:
+ if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
+ break;
+ sr->args_size = val;
+ Debug (15, "CFA_GNU_args_size %lu\n", (long) val);
+ break;
+
+ case DW_CFA_GNU_negative_offset_extended:
+ /* A comment in GCC says that this is obsoleted by
+ DW_CFA_offset_extended_sf, but that it's used by older
+ PowerPC code. */
+ if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
+ || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
+ break;
+ set_reg (sr, regnum, DWARF_WHERE_CFAREL, -(val * dci->data_align));
+ Debug (15, "CFA_GNU_negative_offset_extended cfa+0x%lx\n",
+ (long) -(val * dci->data_align));
+ break;
+
+ case DW_CFA_GNU_window_save:
+#ifdef UNW_TARGET_SPARC
+ /* This is a special CFA to handle all 16 windowed registers
+ on SPARC. */
+ for (regnum = 16; regnum < 32; ++regnum)
+ set_reg (sr, regnum, DWARF_WHERE_CFAREL,
+ (regnum - 16) * sizeof (unw_word_t));
+ Debug (15, "CFA_GNU_window_save\n");
+ break;
+#else
+ /* FALL THROUGH */
+#endif
+ case DW_CFA_lo_user:
+ case DW_CFA_hi_user:
+ Debug (1, "Unexpected CFA opcode 0x%x\n", op);
+ ret = -UNW_EINVAL;
+ break;
+ }
+ }
+
+ if (ret > 0)
+ ret = 0;
+ return ret;
+}
+
+static int
+fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip)
+{
+ int ret, dynamic = 1;
+
+ /* The 'ip' can point either to the previous or next instruction
+ depending on what type of frame we have: normal call or a place
+ to resume execution (e.g. after signal frame).
+
+ For a normal call frame we need to back up so we point within the
+ call itself; this is important because a) the call might be the
+ very last instruction of the function and the edge of the FDE,
+ and b) so that run_cfi_program() runs locations up to the call
+ but not more.
+
+ For signal frame, we need to do the exact opposite and look
+ up using the current 'ip' value. That is where execution will
+ continue, and it's important we get this right, as 'ip' could be
+ right at the function entry and hence FDE edge, or at instruction
+ that manipulates CFA (push/pop). */
+ if (c->use_prev_instr)
+ --ip;
+
+ memset (&c->pi, 0, sizeof (c->pi));
+
+ /* check dynamic info first --- it overrides everything else */
+ ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, 1,
+ c->as_arg);
+ if (ret == -UNW_ENOINFO)
+ {
+ dynamic = 0;
+ if ((ret = tdep_find_proc_info (c, ip, 1)) < 0)
+ return ret;
+ }
+
+ if (c->pi.format != UNW_INFO_FORMAT_DYNAMIC
+ && c->pi.format != UNW_INFO_FORMAT_TABLE
+ && c->pi.format != UNW_INFO_FORMAT_REMOTE_TABLE)
+ return -UNW_ENOINFO;
+
+ c->pi_valid = 1;
+ c->pi_is_dynamic = dynamic;
+
+ /* Let system/machine-dependent code determine frame-specific attributes. */
+ if (ret >= 0)
+ tdep_fetch_frame (c, ip, 1);
+
+ return ret;
+}
+
+static int
+parse_dynamic (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr)
+{
+ Debug (1, "Not yet implemented\n");
+ return -UNW_ENOINFO;
+}
+
+static inline void
+put_unwind_info (struct dwarf_cursor *c, unw_proc_info_t *pi)
+{
+ if (c->pi_is_dynamic)
+ unwi_put_dynamic_unwind_info (c->as, pi, c->as_arg);
+ else if (pi->unwind_info && pi->format == UNW_INFO_FORMAT_TABLE)
+ {
+ mempool_free (&dwarf_cie_info_pool, pi->unwind_info);
+ pi->unwind_info = NULL;
+ }
+ c->pi_valid = 0;
+}
+
+static inline int
+setup_fde (struct dwarf_cursor *c, dwarf_state_record_t *sr)
+{
+ int i, ret;
+
+ assert (c->pi_valid);
+
+ memset (sr, 0, sizeof (*sr));
+ for (i = 0; i < DWARF_NUM_PRESERVED_REGS + 2; ++i)
+ set_reg (sr, i, DWARF_WHERE_SAME, 0);
+
+ struct dwarf_cie_info *dci = c->pi.unwind_info;
+ sr->rs_current.ret_addr_column = dci->ret_addr_column;
+ unw_word_t addr = dci->cie_instr_start;
+ unw_word_t curr_ip = 0;
+ dwarf_stackable_reg_state_t *rs_stack = NULL;
+ ret = run_cfi_program (c, sr, &curr_ip, ~(unw_word_t) 0, &addr,
+ dci->cie_instr_end,
+ &rs_stack, dci);
+ empty_rstate_stack(&rs_stack);
+ if (ret < 0)
+ return ret;
+
+ memcpy (&sr->rs_initial, &sr->rs_current, sizeof (sr->rs_initial));
+ return 0;
+}
+
+static inline int
+parse_fde (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr)
+{
+ int ret;
+ struct dwarf_cie_info *dci = c->pi.unwind_info;
+ unw_word_t addr = dci->fde_instr_start;
+ unw_word_t curr_ip = c->pi.start_ip;
+ dwarf_stackable_reg_state_t *rs_stack = NULL;
+ /* Process up to current `ip` for signal frame and `ip - 1` for normal call frame
+ See `c->use_prev_instr` use in `fetch_proc_info` for details. */
+ ret = run_cfi_program (c, sr, &curr_ip, ip - c->use_prev_instr, &addr, dci->fde_instr_end,
+ &rs_stack, dci);
+ empty_rstate_stack(&rs_stack);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+HIDDEN int
+dwarf_flush_rs_cache (struct dwarf_rs_cache *cache)
+{
+ int i;
+
+ if (cache->log_size == DWARF_DEFAULT_LOG_UNW_CACHE_SIZE
+ || !cache->hash) {
+ cache->hash = cache->default_hash;
+ cache->buckets = cache->default_buckets;
+ cache->links = cache->default_links;
+ cache->log_size = DWARF_DEFAULT_LOG_UNW_CACHE_SIZE;
+ } else {
+ if (cache->hash && cache->hash != cache->default_hash)
+ munmap(cache->hash, DWARF_UNW_HASH_SIZE(cache->prev_log_size)
+ * sizeof (cache->hash[0]));
+ if (cache->buckets && cache->buckets != cache->default_buckets)
+ munmap(cache->buckets, DWARF_UNW_CACHE_SIZE(cache->prev_log_size)
+ * sizeof (cache->buckets[0]));
+ if (cache->links && cache->links != cache->default_links)
+ munmap(cache->links, DWARF_UNW_CACHE_SIZE(cache->prev_log_size)
+ * sizeof (cache->links[0]));
+ GET_MEMORY(cache->hash, DWARF_UNW_HASH_SIZE(cache->log_size)
+ * sizeof (cache->hash[0]));
+ GET_MEMORY(cache->buckets, DWARF_UNW_CACHE_SIZE(cache->log_size)
+ * sizeof (cache->buckets[0]));
+ GET_MEMORY(cache->links, DWARF_UNW_CACHE_SIZE(cache->log_size)
+ * sizeof (cache->links[0]));
+ if (!cache->hash || !cache->buckets || !cache->links)
+ {
+ Debug (1, "Unable to allocate cache memory");
+ return -UNW_ENOMEM;
+ }
+ cache->prev_log_size = cache->log_size;
+ }
+
+ cache->rr_head = 0;
+
+ for (i = 0; i < DWARF_UNW_CACHE_SIZE(cache->log_size); ++i)
+ {
+ cache->links[i].coll_chain = -1;
+ cache->links[i].ip = 0;
+ cache->links[i].valid = 0;
+ }
+ for (i = 0; i< DWARF_UNW_HASH_SIZE(cache->log_size); ++i)
+ cache->hash[i] = -1;
+
+ return 0;
+}
+
+static inline struct dwarf_rs_cache *
+get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp)
+{
+ struct dwarf_rs_cache *cache = &as->global_cache;
+ unw_caching_policy_t caching = as->caching_policy;
+
+ if (caching == UNW_CACHE_NONE)
+ return NULL;
+
+#if defined(HAVE___THREAD) && HAVE___THREAD
+ if (likely (caching == UNW_CACHE_PER_THREAD))
+ {
+ static __thread struct dwarf_rs_cache tls_cache __attribute__((tls_model("initial-exec")));
+ Debug (16, "using TLS cache\n");
+ cache = &tls_cache;
+ }
+ else
+#else
+ if (likely (caching == UNW_CACHE_GLOBAL))
+#endif
+ {
+ Debug (16, "acquiring lock\n");
+ lock_acquire (&cache->lock, *saved_maskp);
+ }
+
+ if ((atomic_read (&as->cache_generation) != atomic_read (&cache->generation))
+ || !cache->hash)
+ {
+ /* cache_size is only set in the global_cache, copy it over before flushing */
+ cache->log_size = as->global_cache.log_size;
+ if (dwarf_flush_rs_cache (cache) < 0)
+ return NULL;
+ cache->generation = as->cache_generation;
+ }
+
+ return cache;
+}
+
+static inline void
+put_rs_cache (unw_addr_space_t as, struct dwarf_rs_cache *cache,
+ intrmask_t *saved_maskp)
+{
+ assert (as->caching_policy != UNW_CACHE_NONE);
+
+ Debug (16, "unmasking signals/interrupts and releasing lock\n");
+ if (likely (as->caching_policy == UNW_CACHE_GLOBAL))
+ lock_release (&cache->lock, *saved_maskp);
+}
+
+static inline unw_hash_index_t CONST_ATTR
+hash (unw_word_t ip, unsigned short log_size)
+{
+ /* based on (sqrt(5)/2-1)*2^64 */
+# define magic ((unw_word_t) 0x9e3779b97f4a7c16ULL)
+
+ return ip * magic >> ((sizeof(unw_word_t) * 8) - (log_size + 1));
+}
+
+static inline long
+cache_match (struct dwarf_rs_cache *cache, unsigned short index, unw_word_t ip)
+{
+ return (cache->links[index].valid && (ip == cache->links[index].ip));
+}
+
+static dwarf_reg_state_t *
+rs_lookup (struct dwarf_rs_cache *cache, struct dwarf_cursor *c)
+{
+ unsigned short index;
+ unw_word_t ip = c->ip;
+
+ if (c->hint > 0)
+ {
+ index = c->hint - 1;
+ if (cache_match (cache, index, ip))
+ return &cache->buckets[index];
+ }
+
+ for (index = cache->hash[hash (ip, cache->log_size)];
+ index < DWARF_UNW_CACHE_SIZE(cache->log_size);
+ index = cache->links[index].coll_chain)
+ {
+ if (cache_match (cache, index, ip))
+ return &cache->buckets[index];
+ }
+ return NULL;
+}
+
+static inline dwarf_reg_state_t *
+rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c)
+{
+ unw_hash_index_t index;
+ unsigned short head;
+
+ head = cache->rr_head;
+ cache->rr_head = (head + 1) & (DWARF_UNW_CACHE_SIZE(cache->log_size) - 1);
+
+ /* remove the old rs from the hash table (if it's there): */
+ if (cache->links[head].ip)
+ {
+ unsigned short *pindex;
+ for (pindex = &cache->hash[hash (cache->links[head].ip, cache->log_size)];
+ *pindex < DWARF_UNW_CACHE_SIZE(cache->log_size);
+ pindex = &cache->links[*pindex].coll_chain)
+ {
+ if (*pindex == head)
+ {
+ *pindex = cache->links[*pindex].coll_chain;
+ break;
+ }
+ }
+ }
+
+ /* enter new rs in the hash table */
+ index = hash (c->ip, cache->log_size);
+ cache->links[head].coll_chain = cache->hash[index];
+ cache->hash[index] = head;
+
+ cache->links[head].ip = c->ip;
+ cache->links[head].valid = 1;
+ cache->links[head].signal_frame = tdep_cache_frame(c);
+ return cache->buckets + head;
+}
+
+static int
+create_state_record_for (struct dwarf_cursor *c, dwarf_state_record_t *sr,
+ unw_word_t ip)
+{
+ int ret;
+ switch (c->pi.format)
+ {
+ case UNW_INFO_FORMAT_TABLE:
+ case UNW_INFO_FORMAT_REMOTE_TABLE:
+ if ((ret = setup_fde(c, sr)) < 0)
+ return ret;
+ ret = parse_fde (c, ip, sr);
+ break;
+
+ case UNW_INFO_FORMAT_DYNAMIC:
+ ret = parse_dynamic (c, ip, sr);
+ break;
+
+ default:
+ Debug (1, "Unexpected unwind-info format %d\n", c->pi.format);
+ ret = -UNW_EINVAL;
+ }
+ return ret;
+}
+
+static inline int
+eval_location_expr (struct dwarf_cursor *c, unw_addr_space_t as,
+ unw_accessors_t *a, unw_word_t addr,
+ dwarf_loc_t *locp, void *arg)
+{
+ int ret, is_register;
+ unw_word_t len, val;
+
+ /* read the length of the expression: */
+ if ((ret = dwarf_read_uleb128 (as, a, &addr, &len, arg)) < 0)
+ return ret;
+
+ /* evaluate the expression: */
+ if ((ret = dwarf_eval_expr (c, &addr, len, &val, &is_register)) < 0)
+ return ret;
+
+ if (is_register)
+ *locp = DWARF_REG_LOC (c, dwarf_to_unw_regnum (val));
+ else
+ *locp = DWARF_MEM_LOC (c, val);
+
+ return 0;
+}
+
+static int
+apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
+{
+ unw_word_t regnum, addr, cfa, ip;
+ unw_word_t prev_ip, prev_cfa;
+ unw_addr_space_t as;
+ dwarf_loc_t cfa_loc;
+ unw_accessors_t *a;
+ int i, ret;
+ void *arg;
+
+ prev_ip = c->ip;
+ prev_cfa = c->cfa;
+
+ as = c->as;
+ arg = c->as_arg;
+ a = unw_get_accessors_int (as);
+
+ /* Evaluate the CFA first, because it may be referred to by other
+ expressions. */
+
+ if (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG)
+ {
+ /* CFA is equal to [reg] + offset: */
+
+ /* As a special-case, if the stack-pointer is the CFA and the
+ stack-pointer wasn't saved, popping the CFA implicitly pops
+ the stack-pointer as well. */
+ if ((rs->reg.val[DWARF_CFA_REG_COLUMN] == UNW_TDEP_SP)
+ && (UNW_TDEP_SP < ARRAY_SIZE(rs->reg.val))
+ && (rs->reg.where[UNW_TDEP_SP] == DWARF_WHERE_SAME))
+ cfa = c->cfa;
+ else
+ {
+ regnum = dwarf_to_unw_regnum (rs->reg.val[DWARF_CFA_REG_COLUMN]);
+ if ((ret = unw_get_reg ((unw_cursor_t *) c, regnum, &cfa)) < 0)
+ return ret;
+ }
+ cfa += rs->reg.val[DWARF_CFA_OFF_COLUMN];
+ }
+ else
+ {
+ /* CFA is equal to EXPR: */
+
+ assert (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_EXPR);
+
+ addr = rs->reg.val[DWARF_CFA_REG_COLUMN];
+ if ((ret = eval_location_expr (c, as, a, addr, &cfa_loc, arg)) < 0)
+ return ret;
+ /* the returned location better be a memory location... */
+ if (DWARF_IS_REG_LOC (cfa_loc))
+ return -UNW_EBADFRAME;
+ cfa = DWARF_GET_LOC (cfa_loc);
+ }
+
+ dwarf_loc_t new_loc[DWARF_NUM_PRESERVED_REGS];
+ memcpy(new_loc, c->loc, sizeof(new_loc));
+
+ for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
+ {
+ switch ((dwarf_where_t) rs->reg.where[i])
+ {
+ case DWARF_WHERE_UNDEF:
+ new_loc[i] = DWARF_NULL_LOC;
+ break;
+
+ case DWARF_WHERE_SAME:
+ break;
+
+ case DWARF_WHERE_CFAREL:
+ new_loc[i] = DWARF_MEM_LOC (c, cfa + rs->reg.val[i]);
+ break;
+
+ case DWARF_WHERE_REG:
+ new_loc[i] = DWARF_REG_LOC (c, dwarf_to_unw_regnum (rs->reg.val[i]));
+ break;
+
+ case DWARF_WHERE_EXPR:
+ addr = rs->reg.val[i];
+ if ((ret = eval_location_expr (c, as, a, addr, new_loc + i, arg)) < 0)
+ return ret;
+ break;
+
+ case DWARF_WHERE_VAL_EXPR:
+ addr = rs->reg.val[i];
+ if ((ret = eval_location_expr (c, as, a, addr, new_loc + i, arg)) < 0)
+ return ret;
+ new_loc[i] = DWARF_VAL_LOC (c, DWARF_GET_LOC (new_loc[i]));
+ break;
+ }
+ }
+
+ memcpy(c->loc, new_loc, sizeof(new_loc));
+
+ c->cfa = cfa;
+ /* DWARF spec says undefined return address location means end of stack. */
+ if (DWARF_IS_NULL_LOC (c->loc[rs->ret_addr_column]))
+ {
+ c->ip = 0;
+ ret = 0;
+ }
+ else
+ {
+ ret = dwarf_get (c, c->loc[rs->ret_addr_column], &ip);
+ if (ret < 0)
+ return ret;
+ c->ip = ip;
+ ret = 1;
+ }
+
+ /* XXX: check for ip to be code_aligned */
+ if (c->ip == prev_ip && c->cfa == prev_cfa)
+ {
+ Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
+ __FUNCTION__, (long) c->ip);
+ return -UNW_EBADFRAME;
+ }
+
+ if (c->stash_frames)
+ tdep_stash_frame (c, rs);
+
+ return ret;
+}
+
+/* Find the saved locations. */
+static int
+find_reg_state (struct dwarf_cursor *c, dwarf_state_record_t *sr)
+{
+ dwarf_reg_state_t *rs;
+ struct dwarf_rs_cache *cache;
+ int ret = 0;
+ intrmask_t saved_mask;
+
+ if ((cache = get_rs_cache(c->as, &saved_mask)) &&
+ (rs = rs_lookup(cache, c)))
+ {
+ /* update hint; no locking needed: single-word writes are atomic */
+ unsigned short index = rs - cache->buckets;
+ c->use_prev_instr = ! cache->links[index].signal_frame;
+ memcpy (&sr->rs_current, rs, sizeof (*rs));
+ }
+ else
+ {
+ ret = fetch_proc_info (c, c->ip);
+ int next_use_prev_instr = c->use_prev_instr;
+ if (ret >= 0)
+ {
+ /* Update use_prev_instr for the next frame. */
+ assert(c->pi.unwind_info);
+ struct dwarf_cie_info *dci = c->pi.unwind_info;
+ next_use_prev_instr = ! dci->signal_frame;
+ ret = create_state_record_for (c, sr, c->ip);
+ }
+ put_unwind_info (c, &c->pi);
+ c->use_prev_instr = next_use_prev_instr;
+
+ if (cache && ret >= 0)
+ {
+ rs = rs_new (cache, c);
+ cache->links[rs - cache->buckets].hint = 0;
+ memcpy(rs, &sr->rs_current, sizeof(*rs));
+ }
+ }
+
+ unsigned short index = -1;
+ if (cache)
+ {
+ put_rs_cache (c->as, cache, &saved_mask);
+ if (rs)
+ {
+ index = rs - cache->buckets;
+ c->hint = cache->links[index].hint;
+ cache->links[c->prev_rs].hint = index + 1;
+ c->prev_rs = index;
+ }
+ }
+ if (ret < 0)
+ return ret;
+ if (cache)
+ tdep_reuse_frame (c, cache->links[index].signal_frame);
+ return 0;
+}
+
+/* The function finds the saved locations and applies the register
+ state as well. */
+HIDDEN int
+dwarf_step (struct dwarf_cursor *c)
+{
+ int ret;
+ dwarf_state_record_t sr;
+ if ((ret = find_reg_state (c, &sr)) < 0)
+ return ret;
+ return apply_reg_state (c, &sr.rs_current);
+}
+
+HIDDEN int
+dwarf_make_proc_info (struct dwarf_cursor *c)
+{
+#if 0
+ if (c->as->caching_policy == UNW_CACHE_NONE
+ || get_cached_proc_info (c) < 0)
+#endif
+ /* Need to check if current frame contains
+ args_size, and set cursor appropriately. Only
+ needed for unw_resume */
+ dwarf_state_record_t sr;
+ int ret;
+
+ /* Lookup it up the slow way... */
+ ret = fetch_proc_info (c, c->ip);
+ if (ret >= 0)
+ ret = create_state_record_for (c, &sr, c->ip);
+ put_unwind_info (c, &c->pi);
+ if (ret < 0)
+ return ret;
+ c->args_size = sr.args_size;
+
+ return 0;
+}
+
+static int
+dwarf_reg_states_dynamic_iterate(struct dwarf_cursor *c,
+ unw_reg_states_callback cb,
+ void *token)
+{
+ Debug (1, "Not yet implemented\n");
+ return -UNW_ENOINFO;
+}
+
+static int
+dwarf_reg_states_table_iterate(struct dwarf_cursor *c,
+ unw_reg_states_callback cb,
+ void *token)
+{
+ dwarf_state_record_t sr;
+ int ret = setup_fde(c, &sr);
+ struct dwarf_cie_info *dci = c->pi.unwind_info;
+ unw_word_t addr = dci->fde_instr_start;
+ unw_word_t curr_ip = c->pi.start_ip;
+ dwarf_stackable_reg_state_t *rs_stack = NULL;
+ while (ret >= 0 && curr_ip < c->pi.end_ip && addr < dci->fde_instr_end)
+ {
+ unw_word_t prev_ip = curr_ip;
+ ret = run_cfi_program (c, &sr, &curr_ip, prev_ip, &addr, dci->fde_instr_end,
+ &rs_stack, dci);
+ if (ret >= 0 && prev_ip < curr_ip)
+ ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), prev_ip, curr_ip);
+ }
+ empty_rstate_stack(&rs_stack);
+#if defined(NEED_LAST_IP)
+ if (ret >= 0 && curr_ip < c->pi.last_ip)
+ /* report the dead zone after the procedure ends */
+ ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), curr_ip, c->pi.last_ip);
+#else
+ if (ret >= 0 && curr_ip < c->pi.end_ip)
+ /* report for whatever is left before procedure end */
+ ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), curr_ip, c->pi.end_ip);
+#endif
+ return ret;
+}
+
+HIDDEN int
+dwarf_reg_states_iterate(struct dwarf_cursor *c,
+ unw_reg_states_callback cb,
+ void *token)
+{
+ int ret = fetch_proc_info (c, c->ip);
+ int next_use_prev_instr = c->use_prev_instr;
+ if (ret >= 0)
+ {
+ /* Update use_prev_instr for the next frame. */
+ assert(c->pi.unwind_info);
+ struct dwarf_cie_info *dci = c->pi.unwind_info;
+ next_use_prev_instr = ! dci->signal_frame;
+ switch (c->pi.format)
+ {
+ case UNW_INFO_FORMAT_TABLE:
+ case UNW_INFO_FORMAT_REMOTE_TABLE:
+ ret = dwarf_reg_states_table_iterate(c, cb, token);
+ break;
+
+ case UNW_INFO_FORMAT_DYNAMIC:
+ ret = dwarf_reg_states_dynamic_iterate (c, cb, token);
+ break;
+
+ default:
+ Debug (1, "Unexpected unwind-info format %d\n", c->pi.format);
+ ret = -UNW_EINVAL;
+ }
+ }
+ put_unwind_info (c, &c->pi);
+ c->use_prev_instr = next_use_prev_instr;
+ return ret;
+}
+
+HIDDEN int
+dwarf_apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
+{
+ return apply_reg_state(c, rs);
+}
diff --git a/src/pal/src/libunwind/src/dwarf/Gpe.c b/src/pal/src/libunwind/src/dwarf/Gpe.c
new file mode 100644
index 0000000000..a0e37ba232
--- /dev/null
+++ b/src/pal/src/libunwind/src/dwarf/Gpe.c
@@ -0,0 +1,39 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "dwarf_i.h"
+#include "libunwind_i.h"
+
+#include <assert.h>
+
+HIDDEN int
+dwarf_read_encoded_pointer (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t *addr, unsigned char encoding,
+ const unw_proc_info_t *pi,
+ unw_word_t *valp, void *arg)
+{
+ return dwarf_read_encoded_pointer_inlined (as, a, addr, encoding,
+ pi, valp, arg);
+}
diff --git a/src/pal/src/libunwind/src/dwarf/Lexpr.c b/src/pal/src/libunwind/src/dwarf/Lexpr.c
new file mode 100644
index 0000000000..245970c9e3
--- /dev/null
+++ b/src/pal/src/libunwind/src/dwarf/Lexpr.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gexpr.c"
+#endif
diff --git a/src/pal/src/libunwind/src/dwarf/Lfde.c b/src/pal/src/libunwind/src/dwarf/Lfde.c
new file mode 100644
index 0000000000..e779e8f192
--- /dev/null
+++ b/src/pal/src/libunwind/src/dwarf/Lfde.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gfde.c"
+#endif
diff --git a/src/pal/src/libunwind/src/dwarf/Lfind_proc_info-lsb.c b/src/pal/src/libunwind/src/dwarf/Lfind_proc_info-lsb.c
new file mode 100644
index 0000000000..27a5eeac18
--- /dev/null
+++ b/src/pal/src/libunwind/src/dwarf/Lfind_proc_info-lsb.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gfind_proc_info-lsb.c"
+#endif
diff --git a/src/pal/src/libunwind/src/dwarf/Lfind_unwind_table.c b/src/pal/src/libunwind/src/dwarf/Lfind_unwind_table.c
new file mode 100644
index 0000000000..68e269f1d7
--- /dev/null
+++ b/src/pal/src/libunwind/src/dwarf/Lfind_unwind_table.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gfind_unwind_table.c"
+#endif
diff --git a/src/pal/src/libunwind/src/dwarf/Lparser.c b/src/pal/src/libunwind/src/dwarf/Lparser.c
new file mode 100644
index 0000000000..f23aaf48e9
--- /dev/null
+++ b/src/pal/src/libunwind/src/dwarf/Lparser.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gparser.c"
+#endif
diff --git a/src/pal/src/libunwind/src/dwarf/Lpe.c b/src/pal/src/libunwind/src/dwarf/Lpe.c
new file mode 100644
index 0000000000..a672358f06
--- /dev/null
+++ b/src/pal/src/libunwind/src/dwarf/Lpe.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gpe.c"
+#endif
diff --git a/src/pal/src/libunwind/src/dwarf/global.c b/src/pal/src/libunwind/src/dwarf/global.c
new file mode 100644
index 0000000000..7098507142
--- /dev/null
+++ b/src/pal/src/libunwind/src/dwarf/global.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2003-2004 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "dwarf_i.h"
+
+HIDDEN struct mempool dwarf_reg_state_pool;
+HIDDEN struct mempool dwarf_cie_info_pool;
+
+HIDDEN int
+dwarf_init (void)
+{
+ mempool_init (&dwarf_reg_state_pool, sizeof (dwarf_stackable_reg_state_t), 0);
+ mempool_init (&dwarf_cie_info_pool, sizeof (struct dwarf_cie_info), 0);
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/elf32.c b/src/pal/src/libunwind/src/elf32.c
new file mode 100644
index 0000000000..a70bb58f24
--- /dev/null
+++ b/src/pal/src/libunwind/src/elf32.c
@@ -0,0 +1,4 @@
+#ifndef UNW_REMOTE_ONLY
+# include "elf32.h"
+# include "elfxx.c"
+#endif
diff --git a/src/pal/src/libunwind/src/elf32.h b/src/pal/src/libunwind/src/elf32.h
new file mode 100644
index 0000000000..2c7bca4c9d
--- /dev/null
+++ b/src/pal/src/libunwind/src/elf32.h
@@ -0,0 +1,9 @@
+#ifndef elf32_h
+#define elf32_h
+
+#ifndef ELF_CLASS
+#define ELF_CLASS ELFCLASS32
+#endif
+#include "elfxx.h"
+
+#endif /* elf32_h */
diff --git a/src/pal/src/libunwind/src/elf64.c b/src/pal/src/libunwind/src/elf64.c
new file mode 100644
index 0000000000..195b887948
--- /dev/null
+++ b/src/pal/src/libunwind/src/elf64.c
@@ -0,0 +1,4 @@
+#ifndef UNW_REMOTE_ONLY
+# include "elf64.h"
+# include "elfxx.c"
+#endif
diff --git a/src/pal/src/libunwind/src/elf64.h b/src/pal/src/libunwind/src/elf64.h
new file mode 100644
index 0000000000..091fba8e1f
--- /dev/null
+++ b/src/pal/src/libunwind/src/elf64.h
@@ -0,0 +1,9 @@
+#ifndef elf64_h
+#define elf64_h
+
+#ifndef ELF_CLASS
+#define ELF_CLASS ELFCLASS64
+#endif
+#include "elfxx.h"
+
+#endif /* elf64_h */
diff --git a/src/pal/src/libunwind/src/elfxx.c b/src/pal/src/libunwind/src/elfxx.c
new file mode 100644
index 0000000000..b03dfcb734
--- /dev/null
+++ b/src/pal/src/libunwind/src/elfxx.c
@@ -0,0 +1,481 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2005 Hewlett-Packard Co
+ Copyright (C) 2007 David Mosberger-Tang
+ Contributed by David Mosberger-Tang <dmosberger@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+#include <stdio.h>
+#include <sys/param.h>
+
+#ifdef HAVE_LZMA
+#include <lzma.h>
+#endif /* HAVE_LZMA */
+
+static Elf_W (Shdr)*
+elf_w (section_table) (struct elf_image *ei)
+{
+ Elf_W (Ehdr) *ehdr = ei->image;
+ Elf_W (Off) soff;
+
+ soff = ehdr->e_shoff;
+ if (soff + ehdr->e_shnum * ehdr->e_shentsize > ei->size)
+ {
+ Debug (1, "section table outside of image? (%lu > %lu)\n",
+ (unsigned long) (soff + ehdr->e_shnum * ehdr->e_shentsize),
+ (unsigned long) ei->size);
+ return NULL;
+ }
+
+ return (Elf_W (Shdr) *) ((char *) ei->image + soff);
+}
+
+static char*
+elf_w (string_table) (struct elf_image *ei, int section)
+{
+ Elf_W (Ehdr) *ehdr = ei->image;
+ Elf_W (Off) soff, str_soff;
+ Elf_W (Shdr) *str_shdr;
+
+ /* this offset is assumed to be OK */
+ soff = ehdr->e_shoff;
+
+ str_soff = soff + (section * ehdr->e_shentsize);
+ if (str_soff + ehdr->e_shentsize > ei->size)
+ {
+ Debug (1, "string shdr table outside of image? (%lu > %lu)\n",
+ (unsigned long) (str_soff + ehdr->e_shentsize),
+ (unsigned long) ei->size);
+ return NULL;
+ }
+ str_shdr = (Elf_W (Shdr) *) ((char *) ei->image + str_soff);
+
+ if (str_shdr->sh_offset + str_shdr->sh_size > ei->size)
+ {
+ Debug (1, "string table outside of image? (%lu > %lu)\n",
+ (unsigned long) (str_shdr->sh_offset + str_shdr->sh_size),
+ (unsigned long) ei->size);
+ return NULL;
+ }
+
+ Debug (16, "strtab=0x%lx\n", (long) str_shdr->sh_offset);
+ return ei->image + str_shdr->sh_offset;
+}
+
+static int
+elf_w (lookup_symbol) (unw_addr_space_t as,
+ unw_word_t ip, struct elf_image *ei,
+ Elf_W (Addr) load_offset,
+ char *buf, size_t buf_len, Elf_W (Addr) *min_dist)
+{
+ size_t syment_size;
+ Elf_W (Ehdr) *ehdr = ei->image;
+ Elf_W (Sym) *sym, *symtab, *symtab_end;
+ Elf_W (Shdr) *shdr;
+ Elf_W (Addr) val;
+ int i, ret = -UNW_ENOINFO;
+ char *strtab;
+
+ if (!elf_w (valid_object) (ei))
+ return -UNW_ENOINFO;
+
+ shdr = elf_w (section_table) (ei);
+ if (!shdr)
+ return -UNW_ENOINFO;
+
+ for (i = 0; i < ehdr->e_shnum; ++i)
+ {
+ switch (shdr->sh_type)
+ {
+ case SHT_SYMTAB:
+ case SHT_DYNSYM:
+ symtab = (Elf_W (Sym) *) ((char *) ei->image + shdr->sh_offset);
+ symtab_end = (Elf_W (Sym) *) ((char *) symtab + shdr->sh_size);
+ syment_size = shdr->sh_entsize;
+
+ strtab = elf_w (string_table) (ei, shdr->sh_link);
+ if (!strtab)
+ break;
+
+ Debug (16, "symtab=0x%lx[%d]\n",
+ (long) shdr->sh_offset, shdr->sh_type);
+
+ for (sym = symtab;
+ sym < symtab_end;
+ sym = (Elf_W (Sym) *) ((char *) sym + syment_size))
+ {
+ if (ELF_W (ST_TYPE) (sym->st_info) == STT_FUNC
+ && sym->st_shndx != SHN_UNDEF)
+ {
+ val = sym->st_value;
+ if (sym->st_shndx != SHN_ABS)
+ val += load_offset;
+ if (tdep_get_func_addr (as, val, &val) < 0)
+ continue;
+ Debug (16, "0x%016lx info=0x%02x %s\n",
+ (long) val, sym->st_info, strtab + sym->st_name);
+
+ if ((Elf_W (Addr)) (ip - val) < *min_dist)
+ {
+ *min_dist = (Elf_W (Addr)) (ip - val);
+ strncpy (buf, strtab + sym->st_name, buf_len);
+ buf[buf_len - 1] = '\0';
+ ret = (strlen (strtab + sym->st_name) >= buf_len
+ ? -UNW_ENOMEM : 0);
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ shdr = (Elf_W (Shdr) *) (((char *) shdr) + ehdr->e_shentsize);
+ }
+ return ret;
+}
+
+static Elf_W (Addr)
+elf_w (get_load_offset) (struct elf_image *ei, unsigned long segbase,
+ unsigned long mapoff)
+{
+ Elf_W (Addr) offset = 0;
+ Elf_W (Ehdr) *ehdr;
+ Elf_W (Phdr) *phdr;
+ int i;
+
+ ehdr = ei->image;
+ phdr = (Elf_W (Phdr) *) ((char *) ei->image + ehdr->e_phoff);
+
+ for (i = 0; i < ehdr->e_phnum; ++i)
+ if (phdr[i].p_type == PT_LOAD && phdr[i].p_offset == mapoff)
+ {
+ offset = segbase - phdr[i].p_vaddr;
+ break;
+ }
+
+ return offset;
+}
+
+#if HAVE_LZMA
+static size_t
+xz_uncompressed_size (uint8_t *compressed, size_t length)
+{
+ uint64_t memlimit = UINT64_MAX;
+ size_t ret = 0, pos = 0;
+ lzma_stream_flags options;
+ lzma_index *index;
+
+ if (length < LZMA_STREAM_HEADER_SIZE)
+ return 0;
+
+ uint8_t *footer = compressed + length - LZMA_STREAM_HEADER_SIZE;
+ if (lzma_stream_footer_decode (&options, footer) != LZMA_OK)
+ return 0;
+
+ if (length < LZMA_STREAM_HEADER_SIZE + options.backward_size)
+ return 0;
+
+ uint8_t *indexdata = footer - options.backward_size;
+ if (lzma_index_buffer_decode (&index, &memlimit, NULL, indexdata,
+ &pos, options.backward_size) != LZMA_OK)
+ return 0;
+
+ if (lzma_index_size (index) == options.backward_size)
+ {
+ ret = lzma_index_uncompressed_size (index);
+ }
+
+ lzma_index_end (index, NULL);
+ return ret;
+}
+
+static int
+elf_w (extract_minidebuginfo) (struct elf_image *ei, struct elf_image *mdi)
+{
+ Elf_W (Shdr) *shdr;
+ uint8_t *compressed = NULL;
+ uint64_t memlimit = UINT64_MAX; /* no memory limit */
+ size_t compressed_len, uncompressed_len;
+
+ shdr = elf_w (find_section) (ei, ".gnu_debugdata");
+ if (!shdr)
+ return 0;
+
+ compressed = ((uint8_t *) ei->image) + shdr->sh_offset;
+ compressed_len = shdr->sh_size;
+
+ uncompressed_len = xz_uncompressed_size (compressed, compressed_len);
+ if (uncompressed_len == 0)
+ {
+ Debug (1, "invalid .gnu_debugdata contents\n");
+ return 0;
+ }
+
+ mdi->size = uncompressed_len;
+ mdi->image = mmap (NULL, uncompressed_len, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+
+ if (mdi->image == MAP_FAILED)
+ return 0;
+
+ size_t in_pos = 0, out_pos = 0;
+ lzma_ret lret;
+ lret = lzma_stream_buffer_decode (&memlimit, 0, NULL,
+ compressed, &in_pos, compressed_len,
+ mdi->image, &out_pos, mdi->size);
+ if (lret != LZMA_OK)
+ {
+ Debug (1, "LZMA decompression failed: %d\n", lret);
+ munmap (mdi->image, mdi->size);
+ return 0;
+ }
+
+ return 1;
+}
+#else
+static int
+elf_w (extract_minidebuginfo) (struct elf_image *ei, struct elf_image *mdi)
+{
+ return 0;
+}
+#endif /* !HAVE_LZMA */
+
+/* Find the ELF image that contains IP and return the "closest"
+ procedure name, if there is one. With some caching, this could be
+ sped up greatly, but until an application materializes that's
+ sensitive to the performance of this routine, why bother... */
+
+HIDDEN int
+elf_w (get_proc_name_in_image) (unw_addr_space_t as, struct elf_image *ei,
+ unsigned long segbase,
+ unsigned long mapoff,
+ unw_word_t ip,
+ char *buf, size_t buf_len, unw_word_t *offp)
+{
+ Elf_W (Addr) load_offset;
+ Elf_W (Addr) min_dist = ~(Elf_W (Addr))0;
+ int ret;
+
+ load_offset = elf_w (get_load_offset) (ei, segbase, mapoff);
+ ret = elf_w (lookup_symbol) (as, ip, ei, load_offset, buf, buf_len, &min_dist);
+
+ /* If the ELF image has MiniDebugInfo embedded in it, look up the symbol in
+ there as well and replace the previously found if it is closer. */
+ struct elf_image mdi;
+ if (elf_w (extract_minidebuginfo) (ei, &mdi))
+ {
+ int ret_mdi = elf_w (lookup_symbol) (as, ip, &mdi, load_offset, buf,
+ buf_len, &min_dist);
+
+ /* Closer symbol was found (possibly truncated). */
+ if (ret_mdi == 0 || ret_mdi == -UNW_ENOMEM)
+ {
+ ret = ret_mdi;
+ }
+
+ munmap (mdi.image, mdi.size);
+ }
+
+ if (min_dist >= ei->size)
+ return -UNW_ENOINFO; /* not found */
+ if (offp)
+ *offp = min_dist;
+ return ret;
+}
+
+HIDDEN int
+elf_w (get_proc_name) (unw_addr_space_t as, pid_t pid, unw_word_t ip,
+ char *buf, size_t buf_len, unw_word_t *offp)
+{
+ unsigned long segbase, mapoff;
+ struct elf_image ei;
+ int ret;
+ char file[PATH_MAX];
+
+ ret = tdep_get_elf_image (&ei, pid, ip, &segbase, &mapoff, file, PATH_MAX);
+ if (ret < 0)
+ return ret;
+
+ ret = elf_w (load_debuglink) (file, &ei, 1);
+ if (ret < 0)
+ return ret;
+
+ ret = elf_w (get_proc_name_in_image) (as, &ei, segbase, mapoff, ip, buf, buf_len, offp);
+
+ munmap (ei.image, ei.size);
+ ei.image = NULL;
+
+ return ret;
+}
+
+HIDDEN Elf_W (Shdr)*
+elf_w (find_section) (struct elf_image *ei, const char* secname)
+{
+ Elf_W (Ehdr) *ehdr = ei->image;
+ Elf_W (Shdr) *shdr;
+ char *strtab;
+ int i;
+
+ if (!elf_w (valid_object) (ei))
+ return 0;
+
+ shdr = elf_w (section_table) (ei);
+ if (!shdr)
+ return 0;
+
+ strtab = elf_w (string_table) (ei, ehdr->e_shstrndx);
+ if (!strtab)
+ return 0;
+
+ for (i = 0; i < ehdr->e_shnum; ++i)
+ {
+ if (strcmp (strtab + shdr->sh_name, secname) == 0)
+ {
+ if (shdr->sh_offset + shdr->sh_size > ei->size)
+ {
+ Debug (1, "section \"%s\" outside image? (0x%lu > 0x%lu)\n",
+ secname,
+ (unsigned long) shdr->sh_offset + shdr->sh_size,
+ (unsigned long) ei->size);
+ return 0;
+ }
+
+ Debug (16, "found section \"%s\" at 0x%lx\n",
+ secname, (unsigned long) shdr->sh_offset);
+ return shdr;
+ }
+
+ shdr = (Elf_W (Shdr) *) (((char *) shdr) + ehdr->e_shentsize);
+ }
+
+ /* section not found */
+ return 0;
+}
+
+/* Load a debug section, following .gnu_debuglink if appropriate
+ * Loads ei from file if not already mapped.
+ * If is_local, will also search sys directories /usr/local/dbg
+ *
+ * Returns 0 on success, failure otherwise.
+ * ei will be mapped to file or the located .gnu_debuglink from file
+ */
+HIDDEN int
+elf_w (load_debuglink) (const char* file, struct elf_image *ei, int is_local)
+{
+ int ret;
+ Elf_W (Shdr) *shdr;
+ Elf_W (Ehdr) *prev_image;
+ off_t prev_size;
+
+ if (!ei->image)
+ {
+ ret = elf_map_image(ei, file);
+ if (ret)
+ return ret;
+ }
+
+ prev_image = ei->image;
+ prev_size = ei->size;
+
+ /* Ignore separate debug files which contain a .gnu_debuglink section. */
+ if (is_local == -1) {
+ return 0;
+ }
+
+ shdr = elf_w (find_section) (ei, ".gnu_debuglink");
+ if (shdr) {
+ if (shdr->sh_size >= PATH_MAX ||
+ (shdr->sh_offset + shdr->sh_size > ei->size))
+ {
+ return 0;
+ }
+
+ {
+ char linkbuf[shdr->sh_size];
+ char *link = ((char *) ei->image) + shdr->sh_offset;
+ char *p;
+ static const char *debugdir = "/usr/lib/debug";
+ char basedir[strlen(file) + 1];
+ char newname[shdr->sh_size + strlen (debugdir) + strlen (file) + 9];
+
+ memcpy(linkbuf, link, shdr->sh_size);
+
+ if (memchr (linkbuf, 0, shdr->sh_size) == NULL)
+ return 0;
+
+ ei->image = NULL;
+
+ Debug(1, "Found debuglink section, following %s\n", linkbuf);
+
+ p = strrchr (file, '/');
+ if (p != NULL)
+ {
+ memcpy (basedir, file, p - file);
+ basedir[p - file] = '\0';
+ }
+ else
+ basedir[0] = 0;
+
+ strcpy (newname, basedir);
+ strcat (newname, "/");
+ strcat (newname, linkbuf);
+ ret = elf_w (load_debuglink) (newname, ei, -1);
+
+ if (ret == -1)
+ {
+ strcpy (newname, basedir);
+ strcat (newname, "/.debug/");
+ strcat (newname, linkbuf);
+ ret = elf_w (load_debuglink) (newname, ei, -1);
+ }
+
+ if (ret == -1 && is_local == 1)
+ {
+ strcpy (newname, debugdir);
+ strcat (newname, basedir);
+ strcat (newname, "/");
+ strcat (newname, linkbuf);
+ ret = elf_w (load_debuglink) (newname, ei, -1);
+ }
+
+ if (ret == -1)
+ {
+ /* No debuglink file found even though .gnu_debuglink existed */
+ ei->image = prev_image;
+ ei->size = prev_size;
+
+ return 0;
+ }
+ else
+ {
+ munmap (prev_image, prev_size);
+ }
+
+ return ret;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/elfxx.h b/src/pal/src/libunwind/src/elfxx.h
new file mode 100644
index 0000000000..830432c2ed
--- /dev/null
+++ b/src/pal/src/libunwind/src/elfxx.h
@@ -0,0 +1,101 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003, 2005 Hewlett-Packard Co
+ Copyright (C) 2007 David Mosberger-Tang
+ Contributed by David Mosberger-Tang <dmosberger@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include "libunwind_i.h"
+
+#if ELF_CLASS == ELFCLASS32
+# define ELF_W(x) ELF32_##x
+# define Elf_W(x) Elf32_##x
+# define elf_w(x) _Uelf32_##x
+#else
+# define ELF_W(x) ELF64_##x
+# define Elf_W(x) Elf64_##x
+# define elf_w(x) _Uelf64_##x
+#endif
+
+extern int elf_w (get_proc_name) (unw_addr_space_t as,
+ pid_t pid, unw_word_t ip,
+ char *buf, size_t len,
+ unw_word_t *offp);
+
+extern int elf_w (get_proc_name_in_image) (unw_addr_space_t as,
+ struct elf_image *ei,
+ unsigned long segbase,
+ unsigned long mapoff,
+ unw_word_t ip,
+ char *buf, size_t buf_len, unw_word_t *offp);
+
+extern Elf_W (Shdr)* elf_w (find_section) (struct elf_image *ei, const char* secname);
+extern int elf_w (load_debuglink) (const char* file, struct elf_image *ei, int is_local);
+
+static inline int
+elf_w (valid_object) (struct elf_image *ei)
+{
+ if (ei->size <= EI_VERSION)
+ return 0;
+
+ return (memcmp (ei->image, ELFMAG, SELFMAG) == 0
+ && ((uint8_t *) ei->image)[EI_CLASS] == ELF_CLASS
+ && ((uint8_t *) ei->image)[EI_VERSION] != EV_NONE
+ && ((uint8_t *) ei->image)[EI_VERSION] <= EV_CURRENT);
+}
+
+static inline int
+elf_map_image (struct elf_image *ei, const char *path)
+{
+ struct stat stat;
+ int fd;
+
+ fd = open (path, O_RDONLY);
+ if (fd < 0)
+ return -1;
+
+ if (fstat (fd, &stat) < 0)
+ {
+ close (fd);
+ return -1;
+ }
+
+ ei->size = stat.st_size;
+ ei->image = mmap (NULL, ei->size, PROT_READ, MAP_PRIVATE, fd, 0);
+ close (fd);
+ if (ei->image == MAP_FAILED)
+ return -1;
+
+ if (!elf_w (valid_object) (ei))
+ {
+ munmap(ei->image, ei->size);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/hppa/Gapply_reg_state.c b/src/pal/src/libunwind/src/hppa/Gapply_reg_state.c
new file mode 100644
index 0000000000..82f056da67
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Gapply_reg_state.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+ void *reg_states_data)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
diff --git a/src/pal/src/libunwind/src/hppa/Gcreate_addr_space.c b/src/pal/src/libunwind/src/hppa/Gcreate_addr_space.c
new file mode 100644
index 0000000000..8a6cb8b4e6
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Gcreate_addr_space.c
@@ -0,0 +1,54 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+
+#include "unwind_i.h"
+
+unw_addr_space_t
+unw_create_addr_space (unw_accessors_t *a, int byte_order)
+{
+#ifdef UNW_LOCAL_ONLY
+ return NULL;
+#else
+ unw_addr_space_t as;
+
+ /*
+ * hppa supports only big-endian.
+ */
+ if (byte_order != 0 && byte_order != __BIG_ENDIAN)
+ return NULL;
+
+ as = malloc (sizeof (*as));
+ if (!as)
+ return NULL;
+
+ memset (as, 0, sizeof (*as));
+
+ as->acc = *a;
+
+ return as;
+#endif
+}
diff --git a/src/pal/src/libunwind/src/hppa/Gget_proc_info.c b/src/pal/src/libunwind/src/hppa/Gget_proc_info.c
new file mode 100644
index 0000000000..e10efcfca0
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Gget_proc_info.c
@@ -0,0 +1,46 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (dwarf_make_proc_info (&c->dwarf) < 0)
+ {
+ /* On hppa, some key routines such as _start() and _dl_start()
+ are missing DWARF unwind info. We don't want to fail in that
+ case, because those frames are uninteresting and just mark
+ the end of the frame-chain anyhow. */
+ memset (pi, 0, sizeof (*pi));
+ pi->start_ip = c->dwarf.ip;
+ pi->end_ip = c->dwarf.ip + 4;
+ return 0;
+ }
+ *pi = c->dwarf.pi;
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/hppa/Gget_save_loc.c b/src/pal/src/libunwind/src/hppa/Gget_save_loc.c
new file mode 100644
index 0000000000..02dfa3084f
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Gget_save_loc.c
@@ -0,0 +1,59 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
+{
+ /* struct cursor *c = (struct cursor *) cursor; */
+ dwarf_loc_t loc;
+
+ loc = DWARF_NULL_LOC; /* default to "not saved" */
+
+#warning FIX ME!
+
+ memset (sloc, 0, sizeof (*sloc));
+
+ if (DWARF_IS_NULL_LOC (loc))
+ {
+ sloc->type = UNW_SLT_NONE;
+ return 0;
+ }
+
+#if !defined(UNW_LOCAL_ONLY)
+ if (DWARF_IS_REG_LOC (loc))
+ {
+ sloc->type = UNW_SLT_REG;
+ sloc->u.regnum = DWARF_GET_LOC (loc);
+ }
+ else
+#endif
+ {
+ sloc->type = UNW_SLT_MEMORY;
+ sloc->u.addr = DWARF_GET_LOC (loc);
+ }
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/hppa/Gglobal.c b/src/pal/src/libunwind/src/hppa/Gglobal.c
new file mode 100644
index 0000000000..351a5015d6
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Gglobal.c
@@ -0,0 +1,55 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2004-2005 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+HIDDEN define_lock (hppa_lock);
+HIDDEN int tdep_init_done;
+
+HIDDEN void
+tdep_init (void)
+{
+ intrmask_t saved_mask;
+
+ sigfillset (&unwi_full_mask);
+
+ lock_acquire (&hppa_lock, saved_mask);
+ {
+ if (tdep_init_done)
+ /* another thread else beat us to it... */
+ goto out;
+
+ mi_init ();
+
+ dwarf_init ();
+
+#ifndef UNW_REMOTE_ONLY
+ hppa_local_addr_space_init ();
+#endif
+ tdep_init_done = 1; /* signal that we're initialized... */
+ }
+ out:
+ lock_release (&hppa_lock, saved_mask);
+}
diff --git a/src/pal/src/libunwind/src/hppa/Ginit.c b/src/pal/src/libunwind/src/hppa/Ginit.c
new file mode 100644
index 0000000000..461e4b93da
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Ginit.c
@@ -0,0 +1,194 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002, 2004 Hewlett-Packard Co
+ Copyright (C) 2007 David Mosberger-Tang
+ Contributed by David Mosberger-Tang <dmosberger@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "unwind_i.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+/* unw_local_addr_space is a NULL pointer in this case. */
+unw_addr_space_t unw_local_addr_space;
+
+#else /* !UNW_REMOTE_ONLY */
+
+static struct unw_addr_space local_addr_space;
+
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
+
+static inline void *
+uc_addr (ucontext_t *uc, int reg)
+{
+ void *addr;
+
+ if ((unsigned) (reg - UNW_HPPA_GR) < 32)
+ addr = &uc->uc_mcontext.sc_gr[reg - UNW_HPPA_GR];
+ else if ((unsigned) (reg - UNW_HPPA_FR) < 32)
+ addr = &uc->uc_mcontext.sc_fr[reg - UNW_HPPA_FR];
+ else
+ addr = NULL;
+ return addr;
+}
+
+# ifdef UNW_LOCAL_ONLY
+
+void *
+_Uhppa_uc_addr (ucontext_t *uc, int reg)
+{
+ return uc_addr (uc, reg);
+}
+
+# endif /* UNW_LOCAL_ONLY */
+
+HIDDEN unw_dyn_info_list_t _U_dyn_info_list;
+
+/* XXX fix me: there is currently no way to locate the dyn-info list
+ by a remote unwinder. On ia64, this is done via a special
+ unwind-table entry. Perhaps something similar can be done with
+ DWARF2 unwind info. */
+
+static void
+put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
+{
+ /* it's a no-op */
+}
+
+static int
+get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
+ void *arg)
+{
+ *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list;
+ return 0;
+}
+
+static int
+access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
+ void *arg)
+{
+ if (write)
+ {
+ Debug (12, "mem[%x] <- %x\n", addr, *val);
+ *(unw_word_t *) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_word_t *) addr;
+ Debug (12, "mem[%x] -> %x\n", addr, *val);
+ }
+ return 0;
+}
+
+static int
+access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
+ void *arg)
+{
+ unw_word_t *addr;
+ ucontext_t *uc = arg;
+
+ if ((unsigned int) (reg - UNW_HPPA_FR) < 32)
+ goto badreg;
+
+ addr = uc_addr (uc, reg);
+ if (!addr)
+ goto badreg;
+
+ if (write)
+ {
+ *(unw_word_t *) addr = *val;
+ Debug (12, "%s <- %x\n", unw_regname (reg), *val);
+ }
+ else
+ {
+ *val = *(unw_word_t *) addr;
+ Debug (12, "%s -> %x\n", unw_regname (reg), *val);
+ }
+ return 0;
+
+ badreg:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+}
+
+static int
+access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
+ int write, void *arg)
+{
+ ucontext_t *uc = arg;
+ unw_fpreg_t *addr;
+
+ if ((unsigned) (reg - UNW_HPPA_FR) > 32)
+ goto badreg;
+
+ addr = uc_addr (uc, reg);
+ if (!addr)
+ goto badreg;
+
+ if (write)
+ {
+ Debug (12, "%s <- %08x.%08x\n",
+ unw_regname (reg), val->raw.bits[1], val->raw.bits[0]);
+ *(unw_fpreg_t *) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_fpreg_t *) addr;
+ Debug (12, "%s -> %08x.%08x\n",
+ unw_regname (reg), val->raw.bits[1], val->raw.bits[0]);
+ }
+ return 0;
+
+ badreg:
+ Debug (1, "bad register number %u\n", reg);
+ /* attempt to access a non-preserved register */
+ return -UNW_EBADREG;
+}
+
+static int
+get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
+ char *buf, size_t buf_len, unw_word_t *offp,
+ void *arg)
+{
+ return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
+}
+
+HIDDEN void
+hppa_local_addr_space_init (void)
+{
+ memset (&local_addr_space, 0, sizeof (local_addr_space));
+ local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
+ local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
+ local_addr_space.acc.put_unwind_info = put_unwind_info;
+ local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
+ local_addr_space.acc.access_mem = access_mem;
+ local_addr_space.acc.access_reg = access_reg;
+ local_addr_space.acc.access_fpreg = access_fpreg;
+ local_addr_space.acc.resume = hppa_local_resume;
+ local_addr_space.acc.get_proc_name = get_static_proc_name;
+ unw_flush_cache (&local_addr_space, 0, 0);
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/hppa/Ginit_local.c b/src/pal/src/libunwind/src/hppa/Ginit_local.c
new file mode 100644
index 0000000000..1fdc7716fd
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Ginit_local.c
@@ -0,0 +1,77 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by ...
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "init.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+int
+unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+{
+ return -UNW_EINVAL;
+}
+
+#else /* !UNW_REMOTE_ONLY */
+
+static int
+unw_init_local_common (unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->dwarf.as = unw_local_addr_space;
+ c->dwarf.as_arg = uc;
+ return common_init (c, use_prev_instr);
+}
+
+int
+unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+{
+ return unw_init_local_common(cursor, uc, 1);
+}
+
+int
+unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
+{
+ if (!flag)
+ {
+ return unw_init_local_common(cursor, uc, 1);
+ }
+ else if (flag == UNW_INIT_SIGNAL_FRAME)
+ {
+ return unw_init_local_common(cursor, uc, 0);
+ }
+ else
+ {
+ return -UNW_EINVAL;
+ }
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/hppa/Ginit_remote.c b/src/pal/src/libunwind/src/hppa/Ginit_remote.c
new file mode 100644
index 0000000000..71096ce0e6
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Ginit_remote.c
@@ -0,0 +1,46 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2004 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "init.h"
+#include "unwind_i.h"
+
+int
+unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
+{
+#ifdef UNW_LOCAL_ONLY
+ return -UNW_EINVAL;
+#else /* !UNW_LOCAL_ONLY */
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->dwarf.as = as;
+ c->dwarf.as_arg = as_arg;
+ return common_init (c, 0);
+#endif /* !UNW_LOCAL_ONLY */
+}
diff --git a/src/pal/src/libunwind/src/hppa/Gis_signal_frame.c b/src/pal/src/libunwind/src/hppa/Gis_signal_frame.c
new file mode 100644
index 0000000000..addb551818
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Gis_signal_frame.c
@@ -0,0 +1,74 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+#ifdef __linux__
+ struct cursor *c = (struct cursor *) cursor;
+ unw_word_t w0, w1, w2, w3, ip;
+ unw_addr_space_t as;
+ unw_accessors_t *a;
+ void *arg;
+ int ret;
+
+ as = c->dwarf.as;
+ a = unw_get_accessors_int (as);
+ arg = c->dwarf.as_arg;
+
+ /* Check if IP points at sigreturn() sequence. On Linux, this normally is:
+
+ rt_sigreturn:
+ 0x34190000 ldi 0, %r25
+ 0x3414015a ldi __NR_rt_sigreturn,%r20
+ 0xe4008200 be,l 0x100(%sr2,%r0),%sr0,%r31
+ 0x08000240 nop
+
+ When a signal interrupts a system call, the first word is instead:
+
+ 0x34190002 ldi 1, %r25
+ */
+ ip = c->dwarf.ip;
+ if (!ip)
+ return 0;
+ if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0
+ || (ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0
+ || (ret = (*a->access_mem) (as, ip + 8, &w2, 0, arg)) < 0
+ || (ret = (*a->access_mem) (as, ip + 12, &w3, 0, arg)) < 0)
+ {
+ Debug (1, "failed to read sigreturn code (ret=%d)\n", ret);
+ return ret;
+ }
+ ret = ((w0 == 0x34190000 || w0 == 0x34190002)
+ && w1 == 0x3414015a && w2 == 0xe4008200 && w3 == 0x08000240);
+ Debug (1, "(cursor=%p, ip=0x%08lx) -> %d\n", c, (unsigned) ip, ret);
+ return ret;
+#else
+ printf ("%s: implement me\n", __FUNCTION__);
+#endif
+ return -UNW_ENOINFO;
+}
diff --git a/src/pal/src/libunwind/src/hppa/Greg_states_iterate.c b/src/pal/src/libunwind/src/hppa/Greg_states_iterate.c
new file mode 100644
index 0000000000..a17dc1b561
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Greg_states_iterate.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+ unw_reg_states_callback cb, void *token)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
diff --git a/src/pal/src/libunwind/src/hppa/Gregs.c b/src/pal/src/libunwind/src/hppa/Gregs.c
new file mode 100644
index 0000000000..da0542c81f
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Gregs.c
@@ -0,0 +1,87 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+HIDDEN int
+tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
+ int write)
+{
+ struct dwarf_loc loc;
+
+ switch (reg)
+ {
+ case UNW_HPPA_IP:
+ if (write)
+ c->dwarf.ip = *valp; /* update the IP cache */
+ if (c->dwarf.pi_valid && (*valp < c->dwarf.pi.start_ip
+ || *valp >= c->dwarf.pi.end_ip))
+ c->dwarf.pi_valid = 0; /* new IP outside of current proc */
+ break;
+
+ case UNW_HPPA_CFA:
+ case UNW_HPPA_SP:
+ if (write)
+ return -UNW_EREADONLYREG;
+ *valp = c->dwarf.cfa;
+ return 0;
+
+ /* Do the exception-handling register remapping: */
+ case UNW_HPPA_EH0: reg = UNW_HPPA_GR + 20; break;
+ case UNW_HPPA_EH1: reg = UNW_HPPA_GR + 21; break;
+ case UNW_HPPA_EH2: reg = UNW_HPPA_GR + 22; break;
+ case UNW_HPPA_EH3: reg = UNW_HPPA_GR + 31; break;
+
+ default:
+ break;
+ }
+
+ if ((unsigned) (reg - UNW_HPPA_GR) >= 32)
+ return -UNW_EBADREG;
+
+ loc = c->dwarf.loc[reg];
+
+ if (write)
+ return dwarf_put (&c->dwarf, loc, *valp);
+ else
+ return dwarf_get (&c->dwarf, loc, valp);
+}
+
+HIDDEN int
+tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
+ int write)
+{
+ struct dwarf_loc loc;
+
+ if ((unsigned) (reg - UNW_HPPA_FR) >= 32)
+ return -UNW_EBADREG;
+
+ loc = c->dwarf.loc[reg];
+
+ if (write)
+ return dwarf_putfp (&c->dwarf, loc, *valp);
+ else
+ return dwarf_getfp (&c->dwarf, loc, valp);
+}
diff --git a/src/pal/src/libunwind/src/hppa/Gresume.c b/src/pal/src/libunwind/src/hppa/Gresume.c
new file mode 100644
index 0000000000..6c11f14036
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Gresume.c
@@ -0,0 +1,145 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2004 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+
+#include "unwind_i.h"
+
+#ifndef UNW_REMOTE_ONLY
+
+#if defined(__linux)
+
+# include <sys/syscall.h>
+
+static NORETURN inline long
+my_rt_sigreturn (void *new_sp, int in_syscall)
+{
+ register unsigned long r25 __asm__ ("r25") = (in_syscall != 0);
+ register unsigned long r20 __asm__ ("r20") = SYS_rt_sigreturn;
+
+ __asm__ __volatile__ ("copy %0, %%sp\n"
+ "be,l 0x100(%%sr2,%%r0),%%sr0,%%r31\n"
+ "nop"
+ :
+ : "r"(new_sp), "r"(r20), "r"(r25)
+ : "memory");
+ abort ();
+}
+
+#endif /* __linux */
+
+HIDDEN inline int
+hppa_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
+{
+#if defined(__linux)
+ struct cursor *c = (struct cursor *) cursor;
+ ucontext_t *uc = c->dwarf.as_arg;
+
+ /* Ensure c->pi is up-to-date. On PA-RISC, it's relatively common to be
+ missing DWARF unwind info. We don't want to fail in that case,
+ because the frame-chain still would let us do a backtrace at
+ least. */
+ dwarf_make_proc_info (&c->dwarf);
+
+ if (unlikely (c->sigcontext_format != HPPA_SCF_NONE))
+ {
+ struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
+
+ Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc);
+ my_rt_sigreturn (sc, (sc->sc_flags & PARISC_SC_FLAG_IN_SYSCALL) != 0);
+ }
+ else
+ {
+ Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip);
+ setcontext (uc);
+ }
+#else
+# warning Implement me!
+#endif
+ return -UNW_EINVAL;
+}
+
+#endif /* !UNW_REMOTE_ONLY */
+
+/* This routine is responsible for copying the register values in
+ cursor C and establishing them as the current machine state. */
+
+static inline int
+establish_machine_state (struct cursor *c)
+{
+ int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *,
+ int write, void *);
+ int (*access_fpreg) (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *,
+ int write, void *);
+ unw_addr_space_t as = c->dwarf.as;
+ void *arg = c->dwarf.as_arg;
+ unw_fpreg_t fpval;
+ unw_word_t val;
+ int reg;
+
+ access_reg = as->acc.access_reg;
+ access_fpreg = as->acc.access_fpreg;
+
+ Debug (8, "copying out cursor state\n");
+
+ for (reg = 0; reg <= UNW_REG_LAST; ++reg)
+ {
+ Debug (16, "copying %s %d\n", unw_regname (reg), reg);
+ if (unw_is_fpreg (reg))
+ {
+ if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0)
+ (*access_fpreg) (as, reg, &fpval, 1, arg);
+ }
+ else
+ {
+ if (tdep_access_reg (c, reg, &val, 0) >= 0)
+ (*access_reg) (as, reg, &val, 1, arg);
+ }
+ }
+ return 0;
+}
+
+int
+unw_resume (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ if (!c->dwarf.ip)
+ {
+ /* This can happen easily when the frame-chain gets truncated
+ due to bad or missing unwind-info. */
+ Debug (1, "refusing to resume execution at address 0\n");
+ return -UNW_EINVAL;
+ }
+
+ if ((ret = establish_machine_state (c)) < 0)
+ return ret;
+
+ return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c,
+ c->dwarf.as_arg);
+}
diff --git a/src/pal/src/libunwind/src/hppa/Gstep.c b/src/pal/src/libunwind/src/hppa/Gstep.c
new file mode 100644
index 0000000000..4fc8a8776b
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Gstep.c
@@ -0,0 +1,95 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "offsets.h"
+
+int
+unw_step (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret, i;
+
+ Debug (1, "(cursor=%p, ip=0x%08x)\n", c, (unsigned) c->dwarf.ip);
+
+ /* Try DWARF-based unwinding... */
+ ret = dwarf_step (&c->dwarf);
+
+ if (ret < 0 && ret != -UNW_ENOINFO)
+ {
+ Debug (2, "returning %d\n", ret);
+ return ret;
+ }
+
+ if (unlikely (ret < 0))
+ {
+ /* DWARF failed, let's see if we can follow the frame-chain
+ or skip over the signal trampoline. */
+
+ Debug (13, "dwarf_step() failed (ret=%d), trying fallback\n", ret);
+
+ if (unw_is_signal_frame (cursor))
+ {
+#ifdef __linux__
+ /* Assume that the trampoline is at the beginning of the
+ sigframe. */
+ unw_word_t ip, sc_addr = c->dwarf.ip + LINUX_RT_SIGFRAME_UC_OFF;
+ dwarf_loc_t iaoq_loc = DWARF_LOC (sc_addr + LINUX_SC_IAOQ_OFF, 0);
+
+ c->sigcontext_format = HPPA_SCF_LINUX_RT_SIGFRAME;
+ c->sigcontext_addr = sc_addr;
+
+ if ((ret = dwarf_get (&c->dwarf, iaoq_loc, &ip)) < 0)
+ {
+ Debug (2, "failed to read IAOQ[1] (ret=%d)\n", ret);
+ return ret;
+ }
+ c->dwarf.ip = ip & ~0x3; /* mask out the privilege level */
+
+ for (i = 0; i < 32; ++i)
+ {
+ c->dwarf.loc[UNW_HPPA_GR + i]
+ = DWARF_LOC (sc_addr + LINUX_SC_GR_OFF + 4*i, 0);
+ c->dwarf.loc[UNW_HPPA_FR + i]
+ = DWARF_LOC (sc_addr + LINUX_SC_FR_OFF + 4*i, 0);
+ }
+
+ if ((ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_HPPA_SP],
+ &c->dwarf.cfa)) < 0)
+ {
+ Debug (2, "failed to read SP (ret=%d)\n", ret);
+ return ret;
+ }
+#else
+# error Implement me!
+#endif
+ }
+ else
+ c->dwarf.ip = 0;
+ }
+ ret = (c->dwarf.ip == 0) ? 0 : 1;
+ Debug (2, "returning %d\n", ret);
+ return ret;
+}
diff --git a/src/pal/src/libunwind/src/hppa/Lapply_reg_state.c b/src/pal/src/libunwind/src/hppa/Lapply_reg_state.c
new file mode 100644
index 0000000000..7ebada480e
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Lapply_reg_state.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/pal/src/libunwind/src/hppa/Lcreate_addr_space.c b/src/pal/src/libunwind/src/hppa/Lcreate_addr_space.c
new file mode 100644
index 0000000000..0f2dc6be90
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Lcreate_addr_space.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gcreate_addr_space.c"
+#endif
diff --git a/src/pal/src/libunwind/src/hppa/Lget_proc_info.c b/src/pal/src/libunwind/src/hppa/Lget_proc_info.c
new file mode 100644
index 0000000000..69028b019f
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Lget_proc_info.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_proc_info.c"
+#endif
diff --git a/src/pal/src/libunwind/src/hppa/Lget_save_loc.c b/src/pal/src/libunwind/src/hppa/Lget_save_loc.c
new file mode 100644
index 0000000000..9ea048a907
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Lget_save_loc.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_save_loc.c"
+#endif
diff --git a/src/pal/src/libunwind/src/hppa/Lglobal.c b/src/pal/src/libunwind/src/hppa/Lglobal.c
new file mode 100644
index 0000000000..6d7b489e14
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Lglobal.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gglobal.c"
+#endif
diff --git a/src/pal/src/libunwind/src/hppa/Linit.c b/src/pal/src/libunwind/src/hppa/Linit.c
new file mode 100644
index 0000000000..e9abfdd46a
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Linit.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit.c"
+#endif
diff --git a/src/pal/src/libunwind/src/hppa/Linit_local.c b/src/pal/src/libunwind/src/hppa/Linit_local.c
new file mode 100644
index 0000000000..68a1687e85
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Linit_local.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_local.c"
+#endif
diff --git a/src/pal/src/libunwind/src/hppa/Linit_remote.c b/src/pal/src/libunwind/src/hppa/Linit_remote.c
new file mode 100644
index 0000000000..58cb04ab7c
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Linit_remote.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_remote.c"
+#endif
diff --git a/src/pal/src/libunwind/src/hppa/Lis_signal_frame.c b/src/pal/src/libunwind/src/hppa/Lis_signal_frame.c
new file mode 100644
index 0000000000..b9a7c4f51a
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Lis_signal_frame.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gis_signal_frame.c"
+#endif
diff --git a/src/pal/src/libunwind/src/hppa/Lreg_states_iterate.c b/src/pal/src/libunwind/src/hppa/Lreg_states_iterate.c
new file mode 100644
index 0000000000..f1eb1e79dc
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Lreg_states_iterate.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
diff --git a/src/pal/src/libunwind/src/hppa/Lregs.c b/src/pal/src/libunwind/src/hppa/Lregs.c
new file mode 100644
index 0000000000..2c9c75cd7d
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Lregs.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gregs.c"
+#endif
diff --git a/src/pal/src/libunwind/src/hppa/Lresume.c b/src/pal/src/libunwind/src/hppa/Lresume.c
new file mode 100644
index 0000000000..41a8cf003d
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Lresume.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gresume.c"
+#endif
diff --git a/src/pal/src/libunwind/src/hppa/Lstep.c b/src/pal/src/libunwind/src/hppa/Lstep.c
new file mode 100644
index 0000000000..c1ac3c7547
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/Lstep.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gstep.c"
+#endif
diff --git a/src/pal/src/libunwind/src/hppa/get_accessors.c b/src/pal/src/libunwind/src/hppa/get_accessors.c
new file mode 100644
index 0000000000..24795801b2
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/get_accessors.c
@@ -0,0 +1,38 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by ...
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+HIDDEN ALIAS(unw_get_accessors) unw_accessors_t *
+unw_get_accessors_int (unw_addr_space_t as);
+
+unw_accessors_t *
+unw_get_accessors (unw_addr_space_t as)
+{
+ if (!tdep_init_done)
+ tdep_init ();
+
+ return &as->acc;
+}
diff --git a/src/pal/src/libunwind/src/hppa/getcontext.S b/src/pal/src/libunwind/src/hppa/getcontext.S
new file mode 100644
index 0000000000..ec7554a025
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/getcontext.S
@@ -0,0 +1,74 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#define SPILL(n) stw %r##n, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_GR_OFF+4*(n))(%r26)
+
+#include "offsets.h"
+
+ .align 4
+ .protected _Uhppa_getcontext
+ .global _Uhppa_getcontext
+ .proc
+ .callinfo
+_Uhppa_getcontext:
+ SPILL (2) /* return-pointer */
+ SPILL (3) /* frame pointer */
+ SPILL (4) /* 2nd-ary frame pointer */
+ SPILL (5) /* preserved register */
+ SPILL (6) /* preserved register */
+ SPILL (7) /* preserved register */
+ SPILL (8) /* preserved register */
+ SPILL (9) /* preserved register */
+ SPILL (10) /* preserved register */
+ SPILL (11) /* preserved register */
+ SPILL (12) /* preserved register */
+ SPILL (13) /* preserved register */
+ SPILL (14) /* preserved register */
+ SPILL (15) /* preserved register */
+ SPILL (16) /* preserved register */
+ SPILL (17) /* preserved register */
+ SPILL (18) /* preserved register */
+ SPILL (19) /* linkage-table register */
+ SPILL (27) /* global-data pointer */
+ SPILL (30) /* stack pointer */
+
+ ldo (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FR_OFF)(%r26), %r29
+ fstds,ma %fr12, 8(%r29)
+ fstds,ma %fr13, 8(%r29)
+ fstds,ma %fr14, 8(%r29)
+ fstds,ma %fr15, 8(%r29)
+ fstds,ma %fr16, 8(%r29)
+ fstds,ma %fr17, 8(%r29)
+ fstds,ma %fr18, 8(%r29)
+ fstds,ma %fr19, 8(%r29)
+ fstds,ma %fr20, 8(%r29)
+ fstds %fr21, 8(%r29)
+
+ bv,n %r0(%rp)
+ .procend
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/src/hppa/init.h b/src/pal/src/libunwind/src/hppa/init.h
new file mode 100644
index 0000000000..4e23b86132
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/init.h
@@ -0,0 +1,47 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by ...
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+static inline int
+common_init (struct cursor *c, unsigned use_prev_instr)
+{
+ int ret;
+
+ c->dwarf.loc[UNW_HPPA_IP] = DWARF_REG_LOC (&c->dwarf, UNW_HPPA_IP);
+ c->dwarf.loc[UNW_HPPA_SP] = DWARF_REG_LOC (&c->dwarf, UNW_HPPA_SP);
+
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_HPPA_IP], &c->dwarf.ip);
+ if (ret < 0)
+ return ret;
+
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_HPPA_SP], &c->dwarf.cfa);
+ if (ret < 0)
+ return ret;
+
+ c->dwarf.stash_frames = 0;
+ c->dwarf.use_prev_instr = use_prev_instr;
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/hppa/offsets.h b/src/pal/src/libunwind/src/hppa/offsets.h
new file mode 100644
index 0000000000..24e6453ac4
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/offsets.h
@@ -0,0 +1,17 @@
+#define LINUX_UC_FLAGS_OFF 0x000
+#define LINUX_UC_LINK_OFF 0x004
+#define LINUX_UC_STACK_OFF 0x008
+#define LINUX_UC_MCONTEXT_OFF 0x018
+#define LINUX_UC_SIGMASK_OFF 0x1b8
+
+#define LINUX_SC_FLAGS_OFF 0x000
+#define LINUX_SC_GR_OFF 0x004
+#define LINUX_SC_FR_OFF 0x088
+#define LINUX_SC_IASQ_OFF 0x188
+#define LINUX_SC_IAOQ_OFF 0x190
+#define LINUX_SC_SAR_OFF 0x198
+
+/* The signal frame contains 4 words of space for the sigreturn
+ trampoline, the siginfo structure, and then the sigcontext
+ structure. See include/asm-parisc/compat_rt_sigframe.h. */
+#define LINUX_RT_SIGFRAME_UC_OFF 0xac
diff --git a/src/pal/src/libunwind/src/hppa/regname.c b/src/pal/src/libunwind/src/hppa/regname.c
new file mode 100644
index 0000000000..5698a58ada
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/regname.c
@@ -0,0 +1,50 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2004-2005 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+static const char *regname[] =
+ {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+ "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7",
+ "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
+ "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23",
+ "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31",
+ "ip",
+ "eh0", "eh1", "eh2", "eh3",
+ "cfa"
+ };
+
+const char *
+unw_regname (unw_regnum_t reg)
+{
+ if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
+ return regname[reg];
+ else
+ return "???";
+}
diff --git a/src/pal/src/libunwind/src/hppa/setcontext.S b/src/pal/src/libunwind/src/hppa/setcontext.S
new file mode 100644
index 0000000000..a36ea35cc6
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/setcontext.S
@@ -0,0 +1,77 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* The setcontext() in glibc is a no-op (as of 4 Dec 2004), so we have
+ to implement something useful on our own here. */
+
+#define FILL(n) ldw (LINUX_UC_MCONTEXT_OFF+LINUX_SC_GR_OFF+4*(n))(%r26),%r##n
+
+#include "offsets.h"
+
+ .align 4
+ .global _Uhppa_setcontext
+ .protected _Uhppa_setcontext
+ .proc
+ .callinfo
+_Uhppa_setcontext:
+ FILL (2) /* return-pointer */
+ FILL (3) /* frame pointer */
+ FILL (4) /* 2nd-ary frame pointer */
+ FILL (5) /* preserved register */
+ FILL (6) /* preserved register */
+ FILL (7) /* preserved register */
+ FILL (8) /* preserved register */
+ FILL (9) /* preserved register */
+ FILL (10) /* preserved register */
+ FILL (11) /* preserved register */
+ FILL (12) /* preserved register */
+ FILL (13) /* preserved register */
+ FILL (14) /* preserved register */
+ FILL (15) /* preserved register */
+ FILL (16) /* preserved register */
+ FILL (17) /* preserved register */
+ FILL (18) /* preserved register */
+ FILL (19) /* linkage-table register */
+ FILL (27) /* global-data pointer */
+ FILL (30) /* stack pointer */
+
+ ldo (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FR_OFF)(%r26), %r29
+ fldds,ma 8(%r29), %fr12
+ fldds,ma 8(%r29), %fr13
+ fldds,ma 8(%r29), %fr14
+ fldds,ma 8(%r29), %fr15
+ fldds,ma 8(%r29), %fr16
+ fldds,ma 8(%r29), %fr17
+ fldds,ma 8(%r29), %fr18
+ fldds,ma 8(%r29), %fr19
+ fldds,ma 8(%r29), %fr20
+ fldds 8(%r29), %fr21
+
+ bv,n %r0(%rp)
+ .procend
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/src/hppa/siglongjmp.S b/src/pal/src/libunwind/src/hppa/siglongjmp.S
new file mode 100644
index 0000000000..34878dbe8f
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/siglongjmp.S
@@ -0,0 +1,16 @@
+ /* Dummy implementation for now. */
+
+ .globl _UI_siglongjmp_cont
+ .globl _UI_longjmp_cont
+
+_UI_siglongjmp_cont:
+_UI_longjmp_cont:
+ .proc
+ .callinfo
+#warning fix me
+ bv %r0(%rp)
+ .procend
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/src/hppa/tables.c b/src/pal/src/libunwind/src/hppa/tables.c
new file mode 100644
index 0000000000..5104d4d342
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/tables.c
@@ -0,0 +1,43 @@
+#include "unwind_i.h"
+
+static inline int
+is_local_addr_space (unw_addr_space_t as)
+{
+ extern unw_addr_space_t _ULhppa_local_addr_space;
+
+ return (as == _Uhppa_local_addr_space
+#ifndef UNW_REMOTE_ONLY
+ || as == _ULhppa_local_addr_space
+#endif
+ );
+}
+
+HIDDEN int
+tdep_find_proc_info (unw_addr_space_t as, unw_word_t ip,
+ unw_proc_info_t *pi, int need_unwind_info, void *arg)
+{
+ printf ("%s: begging to get implemented...\n", __FUNCTION__);
+ return 0;
+}
+
+HIDDEN int
+tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
+ unw_dyn_info_t *di,
+ unw_proc_info_t *pi, int need_unwind_info, void *arg)
+{
+ printf ("%s: the biggest beggar of them all...\n", __FUNCTION__);
+ return 0;
+}
+
+HIDDEN void
+tdep_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg)
+{
+ if (!pi->unwind_info)
+ return;
+
+ if (!is_local_addr_space (as))
+ {
+ free (pi->unwind_info);
+ pi->unwind_info = NULL;
+ }
+}
diff --git a/src/pal/src/libunwind/src/hppa/unwind_i.h b/src/pal/src/libunwind/src/hppa/unwind_i.h
new file mode 100644
index 0000000000..cafeab57b8
--- /dev/null
+++ b/src/pal/src/libunwind/src/hppa/unwind_i.h
@@ -0,0 +1,47 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef unwind_i_h
+#define unwind_i_h
+
+#include <stdint.h>
+
+#include <libunwind-hppa.h>
+
+#include "libunwind_i.h"
+
+#define hppa_lock UNW_OBJ(lock)
+#define hppa_local_resume UNW_OBJ(local_resume)
+#define hppa_local_addr_space_init UNW_OBJ(local_addr_space_init)
+#define hppa_scratch_loc UNW_OBJ(scratch_loc)
+#define setcontext UNW_ARCH_OBJ (setcontext)
+
+extern void hppa_local_addr_space_init (void);
+extern int hppa_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
+ void *arg);
+extern dwarf_loc_t hppa_scratch_loc (struct cursor *c, unw_regnum_t reg);
+extern int setcontext (const ucontext_t *ucp);
+
+#endif /* unwind_i_h */
diff --git a/src/pal/src/libunwind/src/ia64/Gapply_reg_state.c b/src/pal/src/libunwind/src/ia64/Gapply_reg_state.c
new file mode 100644
index 0000000000..b45d1b5d9c
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Gapply_reg_state.c
@@ -0,0 +1,39 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+ void *reg_states_data)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ // Needs dwarf support on ia64
+ // return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+ return -UNW_EINVAL;
+}
diff --git a/src/pal/src/libunwind/src/ia64/Gcreate_addr_space.c b/src/pal/src/libunwind/src/ia64/Gcreate_addr_space.c
new file mode 100644
index 0000000000..7ad29cbbd3
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Gcreate_addr_space.c
@@ -0,0 +1,63 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+
+#include "unwind_i.h"
+
+unw_addr_space_t
+unw_create_addr_space (unw_accessors_t *a, int byte_order)
+{
+#ifdef UNW_LOCAL_ONLY
+ return NULL;
+#else
+ unw_addr_space_t as;
+
+ /*
+ * IA-64 supports only big or little-endian, not weird stuff like
+ * PDP_ENDIAN.
+ */
+ if (byte_order != 0
+ && byte_order != __LITTLE_ENDIAN
+ && byte_order != __BIG_ENDIAN)
+ return NULL;
+
+ as = malloc (sizeof (*as));
+
+ if (!as)
+ return NULL;
+
+ memset (as, 0, sizeof (*as));
+
+ as->acc = *a;
+
+ if (byte_order == 0)
+ /* use host default: */
+ as->big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
+ else
+ as->big_endian = (byte_order == __BIG_ENDIAN);
+ return as;
+#endif
+}
diff --git a/src/pal/src/libunwind/src/ia64/Gfind_unwind_table.c b/src/pal/src/libunwind/src/ia64/Gfind_unwind_table.c
new file mode 100644
index 0000000000..9fd2707ace
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Gfind_unwind_table.c
@@ -0,0 +1,143 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+#include <elf.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+
+#include "libunwind_i.h"
+#include "elf64.h"
+
+static unw_word_t
+find_gp (struct elf_dyn_info *edi, Elf64_Phdr *pdyn, Elf64_Addr load_base)
+{
+ Elf64_Off soff, str_soff;
+ Elf64_Ehdr *ehdr = edi->ei.image;
+ Elf64_Shdr *shdr;
+ Elf64_Shdr *str_shdr;
+ Elf64_Addr gp = 0;
+ char *strtab;
+ int i;
+
+ if (pdyn)
+ {
+ /* If we have a PT_DYNAMIC program header, fetch the gp-value
+ from the DT_PLTGOT entry. */
+ Elf64_Dyn *dyn = (Elf64_Dyn *) (pdyn->p_offset + (char *) edi->ei.image);
+ for (; dyn->d_tag != DT_NULL; ++dyn)
+ if (dyn->d_tag == DT_PLTGOT)
+ {
+ gp = (Elf64_Addr) dyn->d_un.d_ptr + load_base;
+ goto done;
+ }
+ }
+
+ /* Without a PT_DYAMIC header, lets try to look for a non-empty .opd
+ section. If there is such a section, we know it's full of
+ function descriptors, and we can simply pick up the gp from the
+ second word of the first entry in this table. */
+
+ soff = ehdr->e_shoff;
+ str_soff = soff + (ehdr->e_shstrndx * ehdr->e_shentsize);
+
+ if (soff + ehdr->e_shnum * ehdr->e_shentsize > edi->ei.size)
+ {
+ Debug (1, "section table outside of image? (%lu > %lu)",
+ soff + ehdr->e_shnum * ehdr->e_shentsize,
+ edi->ei.size);
+ goto done;
+ }
+
+ shdr = (Elf64_Shdr *) ((char *) edi->ei.image + soff);
+ str_shdr = (Elf64_Shdr *) ((char *) edi->ei.image + str_soff);
+ strtab = (char *) edi->ei.image + str_shdr->sh_offset;
+ for (i = 0; i < ehdr->e_shnum; ++i)
+ {
+ if (strcmp (strtab + shdr->sh_name, ".opd") == 0
+ && shdr->sh_size >= 16)
+ {
+ gp = ((Elf64_Addr *) ((char *) edi->ei.image + shdr->sh_offset))[1];
+ goto done;
+ }
+ shdr = (Elf64_Shdr *) (((char *) shdr) + ehdr->e_shentsize);
+ }
+
+ done:
+ Debug (16, "image at %p, gp = %lx\n", edi->ei.image, gp);
+ return gp;
+}
+
+int
+ia64_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
+ char *path, unw_word_t segbase, unw_word_t mapoff,
+ unw_word_t ip)
+{
+ Elf64_Phdr *phdr, *ptxt = NULL, *punw = NULL, *pdyn = NULL;
+ Elf64_Ehdr *ehdr;
+ int i;
+
+ if (!_Uelf64_valid_object (&edi->ei))
+ return -UNW_ENOINFO;
+
+ ehdr = edi->ei.image;
+ phdr = (Elf64_Phdr *) ((char *) edi->ei.image + ehdr->e_phoff);
+
+ for (i = 0; i < ehdr->e_phnum; ++i)
+ {
+ switch (phdr[i].p_type)
+ {
+ case PT_LOAD:
+ if (phdr[i].p_offset == mapoff)
+ ptxt = phdr + i;
+ break;
+
+ case PT_IA_64_UNWIND:
+ punw = phdr + i;
+ break;
+
+ case PT_DYNAMIC:
+ pdyn = phdr + i;
+ break;
+
+ default:
+ break;
+ }
+ }
+ if (!ptxt || !punw)
+ return 0;
+
+ edi->di_cache.start_ip = segbase;
+ edi->di_cache.end_ip = edi->di_cache.start_ip + ptxt->p_memsz;
+ edi->di_cache.gp = find_gp (edi, pdyn, segbase - ptxt->p_vaddr);
+ edi->di_cache.format = UNW_INFO_FORMAT_TABLE;
+ edi->di_cache.u.ti.name_ptr = 0;
+ edi->di_cache.u.ti.segbase = segbase;
+ edi->di_cache.u.ti.table_len = punw->p_memsz / sizeof (unw_word_t);
+ edi->di_cache.u.ti.table_data = (unw_word_t *)
+ ((char *) edi->ei.image + (punw->p_vaddr - ptxt->p_vaddr));
+ return 1;
+}
diff --git a/src/pal/src/libunwind/src/ia64/Gget_proc_info.c b/src/pal/src/libunwind/src/ia64/Gget_proc_info.c
new file mode 100644
index 0000000000..3ec82b9f82
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Gget_proc_info.c
@@ -0,0 +1,38 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ if ((ret = ia64_make_proc_info (c)) < 0)
+ return ret;
+ *pi = c->pi;
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/ia64/Gget_save_loc.c b/src/pal/src/libunwind/src/ia64/Gget_save_loc.c
new file mode 100644
index 0000000000..34efe99a75
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Gget_save_loc.c
@@ -0,0 +1,168 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2003, 2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <assert.h>
+
+#include "rse.h"
+
+#include "offsets.h"
+#include "regs.h"
+
+int
+unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ ia64_loc_t loc, reg_loc;
+ uint8_t nat_bitnr;
+ int ret;
+
+ loc = IA64_NULL_LOC; /* default to "not saved" */
+
+ switch (reg)
+ {
+ /* frame registers */
+ case UNW_IA64_BSP:
+ case UNW_REG_SP:
+ default:
+ break;
+
+ case UNW_REG_IP:
+ loc = c->loc[IA64_REG_IP];
+ break;
+
+ /* preserved registers: */
+ case UNW_IA64_GR + 4 ... UNW_IA64_GR + 7:
+ loc = c->loc[IA64_REG_R4 + (reg - (UNW_IA64_GR + 4))];
+ break;
+
+ case UNW_IA64_NAT + 4 ... UNW_IA64_NAT + 7:
+ loc = c->loc[IA64_REG_NAT4 + (reg - (UNW_IA64_NAT + 4))];
+ reg_loc = c->loc[IA64_REG_R4 + (reg - (UNW_IA64_NAT + 4))];
+ nat_bitnr = c->nat_bitnr[reg - (UNW_IA64_NAT + 4)];
+ if (IA64_IS_FP_LOC (reg_loc))
+ /* NaT bit saved as a NaTVal. */
+ loc = reg_loc;
+ break;
+
+ case UNW_IA64_FR + 2: loc = c->loc[IA64_REG_F2]; break;
+ case UNW_IA64_FR + 3: loc = c->loc[IA64_REG_F3]; break;
+ case UNW_IA64_FR + 4: loc = c->loc[IA64_REG_F4]; break;
+ case UNW_IA64_FR + 5: loc = c->loc[IA64_REG_F5]; break;
+ case UNW_IA64_FR + 16 ... UNW_IA64_FR + 31:
+ loc = c->loc[IA64_REG_F16 + (reg - (UNW_IA64_FR + 16))];
+ break;
+
+ case UNW_IA64_AR_BSP: loc = c->loc[IA64_REG_BSP]; break;
+ case UNW_IA64_AR_BSPSTORE: loc = c->loc[IA64_REG_BSPSTORE]; break;
+ case UNW_IA64_AR_PFS: loc = c->loc[IA64_REG_PFS]; break;
+ case UNW_IA64_AR_RNAT: loc = c->loc[IA64_REG_RNAT]; break;
+ case UNW_IA64_AR_UNAT: loc = c->loc[IA64_REG_UNAT]; break;
+ case UNW_IA64_AR_LC: loc = c->loc[IA64_REG_LC]; break;
+ case UNW_IA64_AR_FPSR: loc = c->loc[IA64_REG_FPSR]; break;
+ case UNW_IA64_BR + 1: loc = c->loc[IA64_REG_B1]; break;
+ case UNW_IA64_BR + 2: loc = c->loc[IA64_REG_B2]; break;
+ case UNW_IA64_BR + 3: loc = c->loc[IA64_REG_B3]; break;
+ case UNW_IA64_BR + 4: loc = c->loc[IA64_REG_B4]; break;
+ case UNW_IA64_BR + 5: loc = c->loc[IA64_REG_B5]; break;
+ case UNW_IA64_CFM: loc = c->cfm_loc; break;
+ case UNW_IA64_PR: loc = c->loc[IA64_REG_PR]; break;
+
+ case UNW_IA64_GR + 32 ... UNW_IA64_GR + 127: /* stacked reg */
+ reg = rotate_gr (c, reg - UNW_IA64_GR);
+ ret = ia64_get_stacked (c, reg, &loc, NULL);
+ if (ret < 0)
+ return ret;
+ break;
+
+ case UNW_IA64_NAT + 32 ... UNW_IA64_NAT + 127: /* stacked reg */
+ reg = rotate_gr (c, reg - UNW_IA64_NAT);
+ ret = ia64_get_stacked (c, reg, NULL, &loc);
+ break;
+
+ case UNW_IA64_AR_EC:
+ loc = c->cfm_loc;
+ break;
+
+ /* scratch & special registers: */
+
+ case UNW_IA64_GR + 0:
+ case UNW_IA64_GR + 1: /* global pointer */
+ case UNW_IA64_NAT + 0:
+ case UNW_IA64_NAT + 1: /* global pointer */
+ case UNW_IA64_FR + 0:
+ case UNW_IA64_FR + 1:
+ break;
+
+ case UNW_IA64_NAT + 2 ... UNW_IA64_NAT + 3:
+ case UNW_IA64_NAT + 8 ... UNW_IA64_NAT + 31:
+ loc = ia64_scratch_loc (c, reg, &nat_bitnr);
+ break;
+
+ case UNW_IA64_GR + 2 ... UNW_IA64_GR + 3:
+ case UNW_IA64_GR + 8 ... UNW_IA64_GR + 31:
+ case UNW_IA64_BR + 0:
+ case UNW_IA64_BR + 6:
+ case UNW_IA64_BR + 7:
+ case UNW_IA64_AR_RSC:
+ case UNW_IA64_AR_CSD:
+ case UNW_IA64_AR_SSD:
+ case UNW_IA64_AR_CCV:
+ loc = ia64_scratch_loc (c, reg, NULL);
+ break;
+
+ case UNW_IA64_FR + 6 ... UNW_IA64_FR + 15:
+ loc = ia64_scratch_loc (c, reg, NULL);
+ break;
+
+ case UNW_IA64_FR + 32 ... UNW_IA64_FR + 127:
+ reg = rotate_fr (c, reg - UNW_IA64_FR) + UNW_IA64_FR;
+ loc = ia64_scratch_loc (c, reg, NULL);
+ break;
+ }
+
+ memset (sloc, 0, sizeof (*sloc));
+
+ if (IA64_IS_NULL_LOC (loc))
+ {
+ sloc->type = UNW_SLT_NONE;
+ return 0;
+ }
+
+#if !defined(UNW_LOCAL_ONLY)
+ if (IA64_IS_REG_LOC (loc))
+ {
+ sloc->type = UNW_SLT_REG;
+ sloc->u.regnum = IA64_GET_REG (loc);
+ sloc->extra.nat_bitnr = nat_bitnr;
+ }
+ else
+#endif
+ {
+ sloc->type = UNW_SLT_MEMORY;
+ sloc->u.addr = IA64_GET_ADDR (loc);
+ sloc->extra.nat_bitnr = nat_bitnr;
+ }
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/ia64/Gglobal.c b/src/pal/src/libunwind/src/ia64/Gglobal.c
new file mode 100644
index 0000000000..5c6156f0e2
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Gglobal.c
@@ -0,0 +1,122 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <assert.h>
+
+#include "unwind_i.h"
+
+HIDDEN struct ia64_global_unwind_state unw =
+ {
+ .lock = PTHREAD_MUTEX_INITIALIZER,
+ .save_order = {
+ IA64_REG_IP, IA64_REG_PFS, IA64_REG_PSP, IA64_REG_PR,
+ IA64_REG_UNAT, IA64_REG_LC, IA64_REG_FPSR, IA64_REG_PRI_UNAT_GR
+ },
+#if UNW_DEBUG
+ .preg_name = {
+ "pri_unat_gr", "pri_unat_mem", "psp", "bsp", "bspstore",
+ "ar.pfs", "ar.rnat", "rp",
+ "r4", "r5", "r6", "r7",
+ "nat4", "nat5", "nat6", "nat7",
+ "ar.unat", "pr", "ar.lc", "ar.fpsr",
+ "b1", "b2", "b3", "b4", "b5",
+ "f2", "f3", "f4", "f5",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
+ }
+#endif
+};
+
+HIDDEN void
+tdep_init (void)
+{
+ const uint8_t f1_bytes[16] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ const uint8_t nat_val_bytes[16] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ const uint8_t int_val_bytes[16] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ intrmask_t saved_mask;
+ uint8_t *lep, *bep;
+ long i;
+
+ sigfillset (&unwi_full_mask);
+
+ lock_acquire (&unw.lock, saved_mask);
+ {
+ if (tdep_init_done)
+ /* another thread else beat us to it... */
+ goto out;
+
+ mi_init ();
+
+ mempool_init (&unw.reg_state_pool, sizeof (struct ia64_reg_state), 0);
+ mempool_init (&unw.labeled_state_pool,
+ sizeof (struct ia64_labeled_state), 0);
+
+ unw.read_only.r0 = 0;
+ unw.read_only.f0.raw.bits[0] = 0;
+ unw.read_only.f0.raw.bits[1] = 0;
+
+ lep = (uint8_t *) &unw.read_only.f1_le + 16;
+ bep = (uint8_t *) &unw.read_only.f1_be;
+ for (i = 0; i < 16; ++i)
+ {
+ *--lep = f1_bytes[i];
+ *bep++ = f1_bytes[i];
+ }
+
+ lep = (uint8_t *) &unw.nat_val_le + 16;
+ bep = (uint8_t *) &unw.nat_val_be;
+ for (i = 0; i < 16; ++i)
+ {
+ *--lep = nat_val_bytes[i];
+ *bep++ = nat_val_bytes[i];
+ }
+
+ lep = (uint8_t *) &unw.int_val_le + 16;
+ bep = (uint8_t *) &unw.int_val_be;
+ for (i = 0; i < 16; ++i)
+ {
+ *--lep = int_val_bytes[i];
+ *bep++ = int_val_bytes[i];
+ }
+
+ assert (8*sizeof(unw_hash_index_t) >= IA64_LOG_UNW_HASH_SIZE);
+
+#ifndef UNW_REMOTE_ONLY
+ ia64_local_addr_space_init ();
+#endif
+ tdep_init_done = 1; /* signal that we're initialized... */
+ }
+ out:
+ lock_release (&unw.lock, saved_mask);
+}
diff --git a/src/pal/src/libunwind/src/ia64/Ginit.c b/src/pal/src/libunwind/src/ia64/Ginit.c
new file mode 100644
index 0000000000..b09a2ad57c
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Ginit.c
@@ -0,0 +1,505 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2005 Hewlett-Packard Co
+ Copyright (C) 2007 David Mosberger-Tang
+ Contributed by David Mosberger-Tang <dmosberger@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+#ifdef HAVE_SYS_UC_ACCESS_H
+# include <sys/uc_access.h>
+#endif
+
+#ifdef UNW_REMOTE_ONLY
+
+/* unw_local_addr_space is a NULL pointer in this case. */
+unw_addr_space_t unw_local_addr_space;
+
+#else /* !UNW_REMOTE_ONLY */
+
+static struct unw_addr_space local_addr_space;
+
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
+
+#ifdef HAVE_SYS_UC_ACCESS_H
+
+#else /* !HAVE_SYS_UC_ACCESS_H */
+
+HIDDEN void *
+tdep_uc_addr (ucontext_t *uc, int reg, uint8_t *nat_bitnr)
+{
+ return inlined_uc_addr (uc, reg, nat_bitnr);
+}
+
+#endif /* !HAVE_SYS_UC_ACCESS_H */
+
+static void
+put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
+{
+ /* it's a no-op */
+}
+
+static int
+get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
+ void *arg)
+{
+#ifndef UNW_LOCAL_ONLY
+# pragma weak _U_dyn_info_list_addr
+ if (!_U_dyn_info_list_addr)
+ return -UNW_ENOINFO;
+#endif
+ *dyn_info_list_addr = _U_dyn_info_list_addr ();
+ return 0;
+}
+
+static int
+access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
+ void *arg)
+{
+ if (write)
+ {
+ Debug (12, "mem[%lx] <- %lx\n", addr, *val);
+ *(unw_word_t *) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_word_t *) addr;
+ Debug (12, "mem[%lx] -> %lx\n", addr, *val);
+ }
+ return 0;
+}
+
+#ifdef HAVE_SYS_UC_ACCESS_H
+
+#define SYSCALL_CFM_SAVE_REG 11 /* on a syscall, ar.pfs is saved in r11 */
+#define REASON_SYSCALL 0
+
+static int
+access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
+ void *arg)
+{
+ ucontext_t *uc = arg;
+ unsigned int nat, mask;
+ uint64_t value;
+ uint16_t reason;
+ int ret;
+
+ __uc_get_reason (uc, &reason);
+
+ switch (reg)
+ {
+ case UNW_IA64_GR ... UNW_IA64_GR + 31:
+ if ((ret = __uc_get_grs (uc, (reg - UNW_IA64_GR), 1, &value, &nat)))
+ break;
+
+ if (write)
+ ret = __uc_set_grs (uc, (reg - UNW_IA64_GR), 1, val, nat);
+ else
+ *val = value;
+ break;
+
+ case UNW_IA64_NAT ... UNW_IA64_NAT + 31:
+ if ((ret = __uc_get_grs (uc, (reg - UNW_IA64_GR), 1, &value, &nat)))
+ break;
+
+ mask = 1 << (reg - UNW_IA64_GR);
+
+ if (write)
+ {
+ if (*val)
+ nat |= mask;
+ else
+ nat &= ~mask;
+ ret = __uc_set_grs (uc, (reg - UNW_IA64_GR), 1, &value, nat);
+ }
+ else
+ *val = (nat & mask) != 0;
+ break;
+
+ case UNW_IA64_AR ... UNW_IA64_AR + 127:
+ if (reg == UNW_IA64_AR_BSP)
+ {
+ if (write)
+ ret = __uc_set_ar (uc, (reg - UNW_IA64_AR), *val);
+ else
+ ret = __uc_get_ar (uc, (reg - UNW_IA64_AR), val);
+ }
+ else if (reg == UNW_IA64_AR_PFS && reason == REASON_SYSCALL)
+ {
+ /* As of HP-UX 11.22, getcontext() does not have unwind info
+ and because of that, we need to hack thins manually here.
+ Hopefully, this is OK because the HP-UX kernel also needs
+ to know where AR.PFS has been saved, so the use of
+ register r11 for this purpose is pretty much nailed
+ down. */
+ if (write)
+ ret = __uc_set_grs (uc, SYSCALL_CFM_SAVE_REG, 1, val, 0);
+ else
+ ret = __uc_get_grs (uc, SYSCALL_CFM_SAVE_REG, 1, val, &nat);
+ }
+ else
+ {
+ if (write)
+ ret = __uc_set_ar (uc, (reg - UNW_IA64_AR), *val);
+ else
+ ret = __uc_get_ar (uc, (reg - UNW_IA64_AR), val);
+ }
+ break;
+
+ case UNW_IA64_BR ... UNW_IA64_BR + 7:
+ if (write)
+ ret = __uc_set_brs (uc, (reg - UNW_IA64_BR), 1, val);
+ else
+ ret = __uc_get_brs (uc, (reg - UNW_IA64_BR), 1, val);
+ break;
+
+ case UNW_IA64_PR:
+ if (write)
+ ret = __uc_set_prs (uc, *val);
+ else
+ ret = __uc_get_prs (uc, val);
+ break;
+
+ case UNW_IA64_IP:
+ if (write)
+ ret = __uc_set_ip (uc, *val);
+ else
+ ret = __uc_get_ip (uc, val);
+ break;
+
+ case UNW_IA64_CFM:
+ if (write)
+ ret = __uc_set_cfm (uc, *val);
+ else
+ ret = __uc_get_cfm (uc, val);
+ break;
+
+ case UNW_IA64_FR ... UNW_IA64_FR + 127:
+ default:
+ ret = EINVAL;
+ break;
+ }
+
+ if (ret != 0)
+ {
+ Debug (1, "failed to %s %s (ret = %d)\n",
+ write ? "write" : "read", unw_regname (reg), ret);
+ return -UNW_EBADREG;
+ }
+
+ if (write)
+ Debug (12, "%s <- %lx\n", unw_regname (reg), *val);
+ else
+ Debug (12, "%s -> %lx\n", unw_regname (reg), *val);
+ return 0;
+}
+
+static int
+access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
+ int write, void *arg)
+{
+ ucontext_t *uc = arg;
+ fp_regval_t fp_regval;
+ int ret;
+
+ switch (reg)
+ {
+ case UNW_IA64_FR ... UNW_IA64_FR + 127:
+ if (write)
+ {
+ memcpy (&fp_regval, val, sizeof (fp_regval));
+ ret = __uc_set_frs (uc, (reg - UNW_IA64_FR), 1, &fp_regval);
+ }
+ else
+ {
+ ret = __uc_get_frs (uc, (reg - UNW_IA64_FR), 1, &fp_regval);
+ memcpy (val, &fp_regval, sizeof (*val));
+ }
+ break;
+
+ default:
+ ret = EINVAL;
+ break;
+ }
+ if (ret != 0)
+ return -UNW_EBADREG;
+
+ return 0;
+}
+
+#else /* !HAVE_SYS_UC_ACCESS_H */
+
+static int
+access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
+ void *arg)
+{
+ unw_word_t *addr, mask;
+ ucontext_t *uc = arg;
+
+ if (reg >= UNW_IA64_NAT + 4 && reg <= UNW_IA64_NAT + 7)
+ {
+ mask = ((unw_word_t) 1) << (reg - UNW_IA64_NAT);
+ if (write)
+ {
+ if (*val)
+ uc->uc_mcontext.sc_nat |= mask;
+ else
+ uc->uc_mcontext.sc_nat &= ~mask;
+ }
+ else
+ *val = (uc->uc_mcontext.sc_nat & mask) != 0;
+
+ if (write)
+ Debug (12, "%s <- %lx\n", unw_regname (reg), *val);
+ else
+ Debug (12, "%s -> %lx\n", unw_regname (reg), *val);
+ return 0;
+ }
+
+ addr = tdep_uc_addr (uc, reg, NULL);
+ if (!addr)
+ goto badreg;
+
+ if (write)
+ {
+ if (ia64_read_only_reg (addr))
+ {
+ Debug (16, "attempt to write read-only register\n");
+ return -UNW_EREADONLYREG;
+ }
+ *addr = *val;
+ Debug (12, "%s <- %lx\n", unw_regname (reg), *val);
+ }
+ else
+ {
+ *val = *(unw_word_t *) addr;
+ Debug (12, "%s -> %lx\n", unw_regname (reg), *val);
+ }
+ return 0;
+
+ badreg:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+}
+
+static int
+access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
+ int write, void *arg)
+{
+ ucontext_t *uc = arg;
+ unw_fpreg_t *addr;
+
+ if (reg < UNW_IA64_FR || reg >= UNW_IA64_FR + 128)
+ goto badreg;
+
+ addr = tdep_uc_addr (uc, reg, NULL);
+ if (!addr)
+ goto badreg;
+
+ if (write)
+ {
+ if (ia64_read_only_reg (addr))
+ {
+ Debug (16, "attempt to write read-only register\n");
+ return -UNW_EREADONLYREG;
+ }
+ *addr = *val;
+ Debug (12, "%s <- %016lx.%016lx\n",
+ unw_regname (reg), val->raw.bits[1], val->raw.bits[0]);
+ }
+ else
+ {
+ *val = *(unw_fpreg_t *) addr;
+ Debug (12, "%s -> %016lx.%016lx\n",
+ unw_regname (reg), val->raw.bits[1], val->raw.bits[0]);
+ }
+ return 0;
+
+ badreg:
+ Debug (1, "bad register number %u\n", reg);
+ /* attempt to access a non-preserved register */
+ return -UNW_EBADREG;
+}
+
+#endif /* !HAVE_SYS_UC_ACCESS_H */
+
+static int
+get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
+ char *buf, size_t buf_len, unw_word_t *offp,
+ void *arg)
+{
+ return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
+}
+
+HIDDEN void
+ia64_local_addr_space_init (void)
+{
+ memset (&local_addr_space, 0, sizeof (local_addr_space));
+ local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
+#if defined(__linux)
+ local_addr_space.abi = ABI_LINUX;
+#elif defined(__hpux)
+ local_addr_space.abi = ABI_HPUX;
+#endif
+ local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
+ local_addr_space.acc.find_proc_info = tdep_find_proc_info;
+ local_addr_space.acc.put_unwind_info = put_unwind_info;
+ local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
+ local_addr_space.acc.access_mem = access_mem;
+ local_addr_space.acc.access_reg = access_reg;
+ local_addr_space.acc.access_fpreg = access_fpreg;
+ local_addr_space.acc.resume = ia64_local_resume;
+ local_addr_space.acc.get_proc_name = get_static_proc_name;
+ unw_flush_cache (&local_addr_space, 0, 0);
+}
+
+#endif /* !UNW_REMOTE_ONLY */
+
+#ifndef UNW_LOCAL_ONLY
+
+HIDDEN int
+ia64_uc_access_reg (struct cursor *c, ia64_loc_t loc, unw_word_t *valp,
+ int write)
+{
+#ifdef HAVE_SYS_UC_ACCESS_H
+ unw_word_t uc_addr = IA64_GET_AUX_ADDR (loc);
+ ucontext_t *ucp;
+ int ret;
+
+ Debug (16, "%s location %s\n",
+ write ? "writing" : "reading", ia64_strloc (loc));
+
+ if (c->as == unw_local_addr_space)
+ ucp = (ucontext_t *) uc_addr;
+ else
+ {
+ unw_word_t *dst, src;
+
+ /* Need to copy-in ucontext_t first. */
+ ucp = alloca (sizeof (ucontext_t));
+ if (!ucp)
+ return -UNW_ENOMEM;
+
+ /* For now, there is no non-HP-UX implementation of the
+ uc_access(3) interface. Because of that, we cannot, e.g.,
+ unwind an HP-UX program from a Linux program. Should that
+ become possible at some point in the future, the
+ copy-in/copy-out needs to be adjusted to do byte-swapping if
+ necessary. */
+ assert (c->as->big_endian == (__BYTE_ORDER == __BIG_ENDIAN));
+
+ dst = (unw_word_t *) ucp;
+ for (src = uc_addr; src < uc_addr + sizeof (ucontext_t); src += 8)
+ if ((ret = (*c->as->acc.access_mem) (c->as, src, dst++, 0, c->as_arg))
+ < 0)
+ return ret;
+ }
+
+ if (IA64_IS_REG_LOC (loc))
+ ret = access_reg (unw_local_addr_space, IA64_GET_REG (loc), valp, write,
+ ucp);
+ else
+ {
+ /* Must be an access to the RSE backing store in ucontext_t. */
+ unw_word_t addr = IA64_GET_ADDR (loc);
+
+ if (write)
+ ret = __uc_set_rsebs (ucp, (uint64_t *) addr, 1, valp);
+ else
+ ret = __uc_get_rsebs (ucp, (uint64_t *) addr, 1, valp);
+ if (ret != 0)
+ ret = -UNW_EBADREG;
+ }
+ if (ret < 0)
+ return ret;
+
+ if (write && c->as != unw_local_addr_space)
+ {
+ /* need to copy-out ucontext_t: */
+ unw_word_t dst, *src = (unw_word_t *) ucp;
+ for (dst = uc_addr; dst < uc_addr + sizeof (ucontext_t); dst += 8)
+ if ((ret = (*c->as->acc.access_mem) (c->as, dst, src++, 1, c->as_arg))
+ < 0)
+ return ret;
+ }
+ return 0;
+#else /* !HAVE_SYS_UC_ACCESS_H */
+ return -UNW_EINVAL;
+#endif /* !HAVE_SYS_UC_ACCESS_H */
+}
+
+HIDDEN int
+ia64_uc_access_fpreg (struct cursor *c, ia64_loc_t loc, unw_fpreg_t *valp,
+ int write)
+{
+#ifdef HAVE_SYS_UC_ACCESS_H
+ unw_word_t uc_addr = IA64_GET_AUX_ADDR (loc);
+ ucontext_t *ucp;
+ int ret;
+
+ if (c->as == unw_local_addr_space)
+ ucp = (ucontext_t *) uc_addr;
+ else
+ {
+ unw_word_t *dst, src;
+
+ /* Need to copy-in ucontext_t first. */
+ ucp = alloca (sizeof (ucontext_t));
+ if (!ucp)
+ return -UNW_ENOMEM;
+
+ /* For now, there is no non-HP-UX implementation of the
+ uc_access(3) interface. Because of that, we cannot, e.g.,
+ unwind an HP-UX program from a Linux program. Should that
+ become possible at some point in the future, the
+ copy-in/copy-out needs to be adjusted to do byte-swapping if
+ necessary. */
+ assert (c->as->big_endian == (__BYTE_ORDER == __BIG_ENDIAN));
+
+ dst = (unw_word_t *) ucp;
+ for (src = uc_addr; src < uc_addr + sizeof (ucontext_t); src += 8)
+ if ((ret = (*c->as->acc.access_mem) (c->as, src, dst++, 0, c->as_arg))
+ < 0)
+ return ret;
+ }
+
+ if ((ret = access_fpreg (unw_local_addr_space, IA64_GET_REG (loc), valp,
+ write, ucp)) < 0)
+ return ret;
+
+ if (write && c->as != unw_local_addr_space)
+ {
+ /* need to copy-out ucontext_t: */
+ unw_word_t dst, *src = (unw_word_t *) ucp;
+ for (dst = uc_addr; dst < uc_addr + sizeof (ucontext_t); dst += 8)
+ if ((ret = (*c->as->acc.access_mem) (c->as, dst, src++, 1, c->as_arg))
+ < 0)
+ return ret;
+ }
+ return 0;
+#else /* !HAVE_SYS_UC_ACCESS_H */
+ return -UNW_EINVAL;
+#endif /* !HAVE_SYS_UC_ACCESS_H */
+}
+
+#endif /* UNW_LOCAL_ONLY */
diff --git a/src/pal/src/libunwind/src/ia64/Ginit_local.c b/src/pal/src/libunwind/src/ia64/Ginit_local.c
new file mode 100644
index 0000000000..8fe1c679b2
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Ginit_local.c
@@ -0,0 +1,110 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2003, 2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "init.h"
+#include "unwind_i.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+int
+unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
+{
+ return -UNW_EINVAL;
+}
+
+#else /* !UNW_REMOTE_ONLY */
+
+static inline void
+set_as_arg (struct cursor *c, unw_context_t *uc)
+{
+#if defined(__linux) && defined(__KERNEL__)
+ c->task = current;
+ c->as_arg = &uc->sw;
+#else
+ c->as_arg = uc;
+#endif
+}
+
+static inline int
+get_initial_stack_pointers (struct cursor *c, unw_context_t *uc,
+ unw_word_t *sp, unw_word_t *bsp)
+{
+#if defined(__linux)
+ unw_word_t sol, bspstore;
+
+#ifdef __KERNEL__
+ sol = (uc->sw.ar_pfs >> 7) & 0x7f;
+ bspstore = uc->sw.ar_bspstore;
+ *sp = uc->ksp;
+# else
+ sol = (uc->uc_mcontext.sc_ar_pfs >> 7) & 0x7f;
+ bspstore = uc->uc_mcontext.sc_ar_bsp;
+ *sp = uc->uc_mcontext.sc_gr[12];
+# endif
+ *bsp = rse_skip_regs (bspstore, -sol);
+#elif defined(__hpux)
+ int ret;
+
+ if ((ret = ia64_get (c, IA64_REG_LOC (c, UNW_IA64_GR + 12), sp)) < 0
+ || (ret = ia64_get (c, IA64_REG_LOC (c, UNW_IA64_AR_BSP), bsp)) < 0)
+ return ret;
+#else
+# error Fix me.
+#endif
+ return 0;
+}
+
+int
+unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ unw_word_t sp, bsp;
+ int ret;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->as = unw_local_addr_space;
+ set_as_arg (c, uc);
+
+ if ((ret = get_initial_stack_pointers (c, uc, &sp, &bsp)) < 0)
+ return ret;
+
+ Debug (4, "initial bsp=%lx, sp=%lx\n", bsp, sp);
+
+ if ((ret = common_init (c, sp, bsp)) < 0)
+ return ret;
+
+#ifdef __hpux
+ /* On HP-UX, the context created by getcontext() points to the
+ getcontext() system call stub. Step over it: */
+ ret = unw_step (cursor);
+#endif
+ return ret;
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/ia64/Ginit_remote.c b/src/pal/src/libunwind/src/ia64/Ginit_remote.c
new file mode 100644
index 0000000000..b570c7eab3
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Ginit_remote.c
@@ -0,0 +1,61 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2002, 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "init.h"
+#include "unwind_i.h"
+
+int
+unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
+{
+#ifdef UNW_LOCAL_ONLY
+ return -UNW_EINVAL;
+#else /* !UNW_LOCAL_ONLY */
+ struct cursor *c = (struct cursor *) cursor;
+ unw_word_t sp, bsp;
+ int ret;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ if (as == unw_local_addr_space)
+ /* This special-casing is unfortunate and shouldn't be needed;
+ however, both Linux and HP-UX need to adjust the context a bit
+ before it's usable. Try to think of a cleaner way of doing
+ this. Not sure it's possible though, as long as we want to be
+ able to use the context returned by getcontext() et al. */
+ return unw_init_local (cursor, as_arg);
+
+ c->as = as;
+ c->as_arg = as_arg;
+
+ if ((ret = ia64_get (c, IA64_REG_LOC (c, UNW_IA64_GR + 12), &sp)) < 0
+ || (ret = ia64_get (c, IA64_REG_LOC (c, UNW_IA64_AR_BSP), &bsp)) < 0)
+ return ret;
+
+ return common_init (c, sp, bsp);
+#endif /* !UNW_LOCAL_ONLY */
+}
diff --git a/src/pal/src/libunwind/src/ia64/Ginstall_cursor.S b/src/pal/src/libunwind/src/ia64/Ginstall_cursor.S
new file mode 100644
index 0000000000..6fb4401faa
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Ginstall_cursor.S
@@ -0,0 +1,348 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "ucontext_i.h"
+
+#ifdef UNW_LOCAL_ONLY
+# include "Lcursor_i.h"
+# define ia64_install_cursor _ULia64_install_cursor
+#else
+# include "Gcursor_i.h"
+# define ia64_install_cursor _Uia64_install_cursor
+#endif
+
+#define SYS_sigreturn 1181
+
+#ifndef UNW_REMOTE_ONLY
+
+/* ia64_install_cursor (const cursor *c, long pri_unat, long *extra,
+ long bspstore, long dirty_size, long *dirty_partition,
+ long dirty_rnat)
+
+ Restores the machine-state represented by C and thereby resumes execution
+ in that frame. If the frame or one of its descendants was interrupted
+ by a signal, all registers are restored (including the signal mask).
+ Otherwise, only the preserved registers, the global-pointer (r1), and
+ the exception-arguments (r15-r18) are restored. */
+
+#define pRet p6
+#define pSig p7
+
+ .align 32
+ .hidden ia64_install_cursor
+ .global ia64_install_cursor
+ .proc ia64_install_cursor
+ia64_install_cursor:
+ alloc r3 = ar.pfs, 7, 0, 0, 0
+ invala
+ add r2 = FR_LOC_OFF, in0
+ ;;
+
+ ld8 r16 = [r2], LOC_SIZE // r16 = loc[IA64_REG_FR16]
+ mov.m r10 = ar.rsc // (ar.rsc: ~ 12 cycle latency)
+ add r3 = FR_LOC_OFF + 16, in0
+ ;;
+
+ ld8 r17 = [r2], 2*LOC_SIZE // r17 = loc[IA64_REG_FR17]
+ ld8 r18 = [r3], 2*LOC_SIZE // r18 = loc[IA64_REG_FR18]
+ and r16 = -4, r16
+ ;;
+
+ ld8 r19 = [r2], 2*LOC_SIZE // r19 = loc[IA64_REG_FR19]
+ ld8 r20 = [r3], 2*LOC_SIZE // r20 = loc[IA64_REG_FR20]
+ and r17 = -4, r17
+ ;;
+
+ ldf.fill f16 = [r16] // f16 restored (don't touch no more)
+ ldf.fill f17 = [r17] // f17 restored (don't touch no more)
+ and r18 = -4, r18
+
+ ld8 r21 = [r2], 2*LOC_SIZE // r21 = loc[IA64_REG_FR21]
+ ld8 r22 = [r3], 2*LOC_SIZE // r22 = loc[IA64_REG_FR22]
+ and r19 = -4, r19
+ ;;
+
+ ldf.fill f18 = [r18] // f18 restored (don't touch no more)
+ ldf.fill f19 = [r19] // f19 restored (don't touch no more)
+ and r20 = -4, r20
+
+ ld8 r23 = [r2], 2*LOC_SIZE // r23 = loc[IA64_REG_FR23]
+ ld8 r24 = [r3], 2*LOC_SIZE // r24 = loc[IA64_REG_FR24]
+ and r21 = -4, r21
+ ;;
+
+ ldf.fill f20 = [r20] // f20 restored (don't touch no more)
+ ldf.fill f21 = [r21] // f21 restored (don't touch no more)
+ and r22 = -4, r22
+
+ ld8 r25 = [r2], 2*LOC_SIZE // r25 = loc[IA64_REG_FR25]
+ ld8 r26 = [r3], 2*LOC_SIZE // r26 = loc[IA64_REG_FR26]
+ and r23 = -4, r23
+ ;;
+
+ ldf.fill f22 = [r22] // f22 restored (don't touch no more)
+ ldf.fill f23 = [r23] // f23 restored (don't touch no more)
+ and r24 = -4, r24
+
+ ld8 r27 = [r2], 2*LOC_SIZE // r27 = loc[IA64_REG_FR27]
+ ld8 r28 = [r3], 2*LOC_SIZE // r28 = loc[IA64_REG_FR28]
+ and r25 = -4, r25
+ ;;
+
+ ldf.fill f24 = [r24] // f24 restored (don't touch no more)
+ ldf.fill f25 = [r25] // f25 restored (don't touch no more)
+ and r26 = -4, r26
+
+ ld8 r29 = [r2], 2*LOC_SIZE // r29 = loc[IA64_REG_FR29]
+ ld8 r30 = [r3], 2*LOC_SIZE // r30 = loc[IA64_REG_FR30]
+ and r27 = -4, r27
+ ;;
+
+ ldf.fill f26 = [r26] // f26 restored (don't touch no more)
+ ldf.fill f27 = [r27] // f27 restored (don't touch no more)
+ and r28 = -4, r28
+
+ ld8 r31 = [r2] // r31 = loc[IA64_REG_FR31]
+ mov.m ar.unat = in1
+ and r29 = -4, r29
+ ;;
+
+ ldf.fill f28 = [r28] // f28 restored (don't touch no more)
+ ldf.fill f29 = [r29] // f29 restored (don't touch no more)
+ and r30 = -4, r30
+
+ ld8 r1 = [in2], 8 // gp restored (don't touch no more)
+ add r8 = SIGCONTEXT_ADDR_OFF, in0
+ and r31 = -4, r31
+ ;;
+
+ ld8 r8 = [r8] // r8 = sigcontext_addr
+ and r11 = 0x1c, r10 // clear all but rsc.be and rsc.pl
+ add r2 = PFS_LOC_OFF, in0
+
+ ldf.fill f30 = [r30] // f30 restored (don't touch no more)
+ ldf.fill f31 = [r31] // f31 restored (don't touch no more)
+ add r3 = 8, in2
+ ;;
+
+ ld8.fill r4 = [in2], 16 // r4 restored (don't touch no more)
+ ld8.fill r5 = [r3], 16 // r5 restored (don't touch no more)
+ cmp.eq pRet, pSig = r0, r8 // sigcontext_addr == NULL?
+ ;;
+ ld8.fill r6 = [in2], 16 // r6 restored (don't touch no more)
+ ld8.fill r7 = [r3] // r7 restored (don't touch no more)
+ add r3 = IP_OFF, in0
+ ;;
+
+ ld8 r14 = [r2], (B1_LOC_OFF - PFS_LOC_OFF) // r14 = pfs_loc
+ ld8 r15 = [r3] // r15 = ip
+ add r3 = (B2_LOC_OFF - IP_OFF), r3
+ ;;
+
+ ld8 r16 = [r2], (B3_LOC_OFF - B1_LOC_OFF) // r16 = b1_loc
+ ld8 r17= [r3], (B4_LOC_OFF - B2_LOC_OFF) // r17 = b2_loc
+ and r14 = -4, r14
+ ;;
+
+ ld8 r18 = [r2], (B5_LOC_OFF - B3_LOC_OFF) // r18 = b3_loc
+ ld8 r19 = [r3], (F2_LOC_OFF - B4_LOC_OFF) // r19 = b4_loc
+ and r16 = -4, r16
+ ;;
+
+ ld8 r20 = [r2], (F3_LOC_OFF - B5_LOC_OFF) // r20 = b5_loc
+ ld8 r21 = [r3], (F4_LOC_OFF - F2_LOC_OFF) // r21 = f2_loc
+ and r17 = -4, r17
+ ;;
+
+ ld8 r16 = [r16] // r16 = *b1_loc
+ ld8 r17 = [r17] // r17 = *b2_loc
+ and r18 = -4, r18
+
+ ld8 r22 = [r2], (F5_LOC_OFF - F3_LOC_OFF) // r21 = f3_loc
+ ld8 r23 = [r3], (UNAT_LOC_OFF - F4_LOC_OFF) // r22 = f4_loc
+ and r19 = -4, r19
+ ;;
+
+ ld8 r18 = [r18] // r18 = *b3_loc
+ ld8 r19 = [r19] // r19 = *b4_loc
+ and r20 = -4, r20
+
+ ld8 r24 = [r2], (LC_LOC_OFF - F5_LOC_OFF) // r24 = f5_loc
+ ld8 r25 = [r3], (FPSR_LOC_OFF - UNAT_LOC_OFF) // r25 = unat_loc
+ and r21 = -4, r21
+ ;;
+
+ and r22 = -4, r22
+ and r23 = -4, r23
+ and r24 = -4, r24
+
+ ld8 r20 = [r20] // r20 = *b5_loc
+ ldf.fill f2 = [r21] // f2 restored (don't touch no more)
+ mov b1 = r16 // b1 restored (don't touch no more)
+ ;;
+
+ ldf.fill f3 = [r22] // f3 restored (don't touch no more)
+ ldf.fill f4 = [r23] // f4 restored (don't touch no more)
+ mov b2 = r17 // b2 restored (don't touch no more)
+
+ ld8 r26 = [r2], (RNAT_LOC_OFF - LC_LOC_OFF) // r26 = lc_loc
+ ld8 r27 = [r3] // r27 = fpsr_loc
+ and r25 = -4, r25
+
+ add r3 = (PSP_OFF - FPSR_LOC_OFF), r3
+ nop 0
+ nop 0
+ ;;
+
+ ldf.fill f5 = [r24] // f5 restored (don't touch no more)
+(pRet) ld8 r25 = [r25] // r25 = *unat_loc
+ mov b3 = r18 // b3 restored (don't touch no more)
+
+ ld8 r28 = [r2], (BSP_OFF - RNAT_LOC_OFF) // r28 = rnat_loc
+ ld8 r29 = [r3], (PR_OFF - PSP_OFF) // r29 = sp
+ mov b4 = r19 // b4 restored (don't touch no more)
+
+ and r26 = -4, r26
+ and r27 = -4, r27
+ mov b5 = r20 // b5 restored (don't touch no more)
+ ;;
+
+ ld8 r26 = [r26] // r26 = *lc_loc
+ ld8 r27 = [r27] // r27 = *fpsr_loc
+ and r28 = -4, r28
+
+ mov r30 = in3 // make backup-copy of new bsp
+ ld8 r31 = [r3] // r31 = pr
+ mov rp = r15
+ ;;
+
+ ld8 r28 = [r28] // r28 = rnat
+ mov.m ar.rsc = r11 // put RSE into enforced lazy mode
+ mov.i ar.lc = r26 // lc restored (don't touch no more)
+ ;;
+
+ loadrs // drop dirty partition
+ mov r9 = in2 // make backup-copy of &extra[r16]
+ cmp.eq p8, p0 = in4, r0 // dirty-size == 0?
+(p8) br.cond.dpnt.many .skip_load_dirty
+
+ mov r2 = in4 // make backup-copy of dirty_size
+ mov r15 = in5 // make backup-copy of dirty_partition
+ mov r16 = in6 // make backup-copy of dirty_rnat
+ ;;
+
+ alloc r3 = ar.pfs, 0, 0, 0, 0 // drop register frame
+ dep r11 = r2, r11, 16, 16
+ ;;
+ mov.m ar.bspstore = r15
+ ;;
+ mov.m ar.rnat = r16
+ mov.m ar.rsc = r11 // 14 cycles latency to loadrs
+ ;;
+ loadrs // loadup new dirty partition
+ ;;
+
+.skip_load_dirty:
+ mov.m ar.bspstore = r30 // restore register backing-store
+ add r3 = 8, r9 // r3 = &extra[r16]
+ ;;
+
+(pRet) mov.m ar.fpsr = r27 // fpsr restored (don't touch no more)
+ mov.m ar.rnat = r28
+(pSig) br.cond.dpnt.many .next
+
+/****** Return via br.ret: */
+
+ ld8 r14 = [r14] // r14 = *pfs_loc
+ ld8 r15 = [r9], 16 // r15 restored (don't touch no more)
+ mov pr = r31, -1 // pr restored (don't touch no more)
+ ;;
+
+ ld8 r16 = [r3], 16 // r16 restored (don't touch no more)
+ ld8 r17 = [r9] // r17 restored (don't touch no more)
+ nop.i 0
+ ;;
+
+ ld8 r18 = [r3] // r18 restored (don't touch no more)
+ mov.m ar.rsc = r10 // restore original ar.rsc
+ mov sp = r29
+
+ mov.m ar.unat = r25 // unat restored (don't touch no more)
+ mov.i ar.pfs = r14
+ br.ret.sptk.many rp
+ ;;
+
+/****** Return via sigreturn(): */
+
+.next: mov.m ar.rsc = r10 // restore original ar.rsc
+ add r2 = (SC_FR + 6*16), r8
+ add r3 = (SC_FR + 7*16), r8
+ ;;
+
+ ldf.fill f6 = [r2], 32
+ ldf.fill f7 = [r3], 32
+ nop 0
+ ;;
+
+ ldf.fill f8 = [r2], 32
+ ldf.fill f9 = [r3], 32
+ nop 0
+ ;;
+
+ ldf.fill f10 = [r2], 32
+ ldf.fill f11 = [r3], 32
+ nop 0
+ ;;
+
+ ldf.fill f12 = [r2], 32
+ ldf.fill f13 = [r3], 32
+ nop 0
+ ;;
+
+ ldf.fill f14 = [r2], 32
+ ldf.fill f15 = [r3], 32
+ mov sp = r29
+ ;;
+
+#if NEW_SYSCALL
+ add r2 = 8, tp;;
+ ld8 r2 = [r2]
+ mov r15 = SYS_sigreturn
+ mov b7 = r2
+ br.call.sptk.many b6 = b7
+ ;;
+#else
+ mov r15 = SYS_sigreturn
+ break 0x100000
+#endif
+ break 0 // bug out if sigreturn() returns
+
+ .endp ia64_install_cursor
+
+#endif /* !UNW_REMOTE_ONLY */
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Gis_signal_frame.c b/src/pal/src/libunwind/src/ia64/Gis_signal_frame.c
new file mode 100644
index 0000000000..e268a06299
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Gis_signal_frame.c
@@ -0,0 +1,54 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2002 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ struct ia64_state_record sr;
+ int ret;
+
+ /* Crude and slow, but we need to peek ahead into the unwind
+ descriptors to find out if the current IP is inside the signal
+ trampoline. */
+ ret = ia64_fetch_proc_info (c, c->ip, 1);
+ if (ret < 0)
+ return ret;
+
+ ret = ia64_create_state_record (c, &sr);
+ if (ret < 0)
+ return ret;
+
+ /* For now, we assume that any non-zero abi marker implies a signal frame.
+ This should get us pretty far. */
+ ret = (sr.abi_marker != 0);
+
+ ia64_free_state_record (&sr);
+
+ Debug (1, "(cursor=%p, ip=0x%016lx) -> %d\n", c, c->ip, ret);
+ return ret;
+}
diff --git a/src/pal/src/libunwind/src/ia64/Gparser.c b/src/pal/src/libunwind/src/ia64/Gparser.c
new file mode 100644
index 0000000000..b1f0f4a118
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Gparser.c
@@ -0,0 +1,1131 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+/* forward declaration: */
+static int create_state_record_for (struct cursor *c,
+ struct ia64_state_record *sr,
+ unw_word_t ip);
+
+typedef unsigned long unw_word;
+
+#define alloc_reg_state() (mempool_alloc (&unw.reg_state_pool))
+#define free_reg_state(rs) (mempool_free (&unw.reg_state_pool, rs))
+#define alloc_labeled_state() (mempool_alloc (&unw.labeled_state_pool))
+#define free_labeled_state(s) (mempool_free (&unw.labeled_state_pool, s))
+
+/* Routines to manipulate the state stack. */
+
+static inline void
+push (struct ia64_state_record *sr)
+{
+ struct ia64_reg_state *rs;
+
+ rs = alloc_reg_state ();
+ if (!rs)
+ {
+ print_error ("libunwind: cannot stack reg state!\n");
+ return;
+ }
+ memcpy (rs, &sr->curr, sizeof (*rs));
+ sr->curr.next = rs;
+}
+
+static void
+pop (struct ia64_state_record *sr)
+{
+ struct ia64_reg_state *rs = sr->curr.next;
+
+ if (!rs)
+ {
+ print_error ("libunwind: stack underflow!\n");
+ return;
+ }
+ memcpy (&sr->curr, rs, sizeof (*rs));
+ free_reg_state (rs);
+}
+
+/* Make a copy of the state stack. Non-recursive to avoid stack overflows. */
+static struct ia64_reg_state *
+dup_state_stack (struct ia64_reg_state *rs)
+{
+ struct ia64_reg_state *copy, *prev = NULL, *first = NULL;
+
+ while (rs)
+ {
+ copy = alloc_reg_state ();
+ if (!copy)
+ {
+ print_error ("unwind.dup_state_stack: out of memory\n");
+ return NULL;
+ }
+ memcpy (copy, rs, sizeof (*copy));
+ if (first)
+ prev->next = copy;
+ else
+ first = copy;
+ rs = rs->next;
+ prev = copy;
+ }
+ return first;
+}
+
+/* Free all stacked register states (but not RS itself). */
+static void
+free_state_stack (struct ia64_reg_state *rs)
+{
+ struct ia64_reg_state *p, *next;
+
+ for (p = rs->next; p != NULL; p = next)
+ {
+ next = p->next;
+ free_reg_state (p);
+ }
+ rs->next = NULL;
+}
+
+/* Unwind decoder routines */
+
+static enum ia64_pregnum CONST_ATTR
+decode_abreg (unsigned char abreg, int memory)
+{
+ switch (abreg)
+ {
+ case 0x04 ... 0x07:
+ return IA64_REG_R4 + (abreg - 0x04);
+ case 0x22 ... 0x25:
+ return IA64_REG_F2 + (abreg - 0x22);
+ case 0x30 ... 0x3f:
+ return IA64_REG_F16 + (abreg - 0x30);
+ case 0x41 ... 0x45:
+ return IA64_REG_B1 + (abreg - 0x41);
+ case 0x60:
+ return IA64_REG_PR;
+ case 0x61:
+ return IA64_REG_PSP;
+ case 0x62:
+ return memory ? IA64_REG_PRI_UNAT_MEM : IA64_REG_PRI_UNAT_GR;
+ case 0x63:
+ return IA64_REG_IP;
+ case 0x64:
+ return IA64_REG_BSP;
+ case 0x65:
+ return IA64_REG_BSPSTORE;
+ case 0x66:
+ return IA64_REG_RNAT;
+ case 0x67:
+ return IA64_REG_UNAT;
+ case 0x68:
+ return IA64_REG_FPSR;
+ case 0x69:
+ return IA64_REG_PFS;
+ case 0x6a:
+ return IA64_REG_LC;
+ default:
+ break;
+ }
+ Dprintf ("libunwind: bad abreg=0x%x\n", abreg);
+ return IA64_REG_LC;
+}
+
+static void
+set_reg (struct ia64_reg_info *reg, enum ia64_where where, int when,
+ unsigned long val)
+{
+ reg->val = val;
+ reg->where = where;
+ if (reg->when == IA64_WHEN_NEVER)
+ reg->when = when;
+}
+
+static void
+alloc_spill_area (unsigned long *offp, unsigned long regsize,
+ struct ia64_reg_info *lo, struct ia64_reg_info *hi)
+{
+ struct ia64_reg_info *reg;
+
+ for (reg = hi; reg >= lo; --reg)
+ {
+ if (reg->where == IA64_WHERE_SPILL_HOME)
+ {
+ reg->where = IA64_WHERE_PSPREL;
+ *offp -= regsize;
+ reg->val = *offp;
+ }
+ }
+}
+
+static inline void
+spill_next_when (struct ia64_reg_info **regp, struct ia64_reg_info *lim,
+ unw_word t)
+{
+ struct ia64_reg_info *reg;
+
+ for (reg = *regp; reg <= lim; ++reg)
+ {
+ if (reg->where == IA64_WHERE_SPILL_HOME)
+ {
+ reg->when = t;
+ *regp = reg + 1;
+ return;
+ }
+ }
+ Dprintf ("libunwind: excess spill!\n");
+}
+
+static inline void
+finish_prologue (struct ia64_state_record *sr)
+{
+ struct ia64_reg_info *reg;
+ unsigned long off;
+ int i;
+
+ /* First, resolve implicit register save locations (see Section
+ "11.4.2.3 Rules for Using Unwind Descriptors", rule 3). */
+ for (i = 0; i < (int) ARRAY_SIZE (unw.save_order); ++i)
+ {
+ reg = sr->curr.reg + unw.save_order[i];
+ if (reg->where == IA64_WHERE_GR_SAVE)
+ {
+ reg->where = IA64_WHERE_GR;
+ reg->val = sr->gr_save_loc++;
+ }
+ }
+
+ /* Next, compute when the fp, general, and branch registers get
+ saved. This must come before alloc_spill_area() because we need
+ to know which registers are spilled to their home locations. */
+
+ if (sr->imask)
+ {
+ unsigned char kind, mask = 0, *cp = sr->imask;
+ unsigned long t;
+ static const unsigned char limit[3] =
+ {
+ IA64_REG_F31, IA64_REG_R7, IA64_REG_B5
+ };
+ struct ia64_reg_info *(regs[3]);
+
+ regs[0] = sr->curr.reg + IA64_REG_F2;
+ regs[1] = sr->curr.reg + IA64_REG_R4;
+ regs[2] = sr->curr.reg + IA64_REG_B1;
+
+ for (t = 0; (int) t < sr->region_len; ++t)
+ {
+ if ((t & 3) == 0)
+ mask = *cp++;
+ kind = (mask >> 2 * (3 - (t & 3))) & 3;
+ if (kind > 0)
+ spill_next_when (&regs[kind - 1], sr->curr.reg + limit[kind - 1],
+ sr->region_start + t);
+ }
+ }
+
+ /* Next, lay out the memory stack spill area. */
+
+ if (sr->any_spills)
+ {
+ off = sr->spill_offset;
+ alloc_spill_area (&off, 16, sr->curr.reg + IA64_REG_F2,
+ sr->curr.reg + IA64_REG_F31);
+ alloc_spill_area (&off, 8, sr->curr.reg + IA64_REG_B1,
+ sr->curr.reg + IA64_REG_B5);
+ alloc_spill_area (&off, 8, sr->curr.reg + IA64_REG_R4,
+ sr->curr.reg + IA64_REG_R7);
+ }
+}
+
+/* Region header descriptors. */
+
+static void
+desc_prologue (int body, unw_word rlen, unsigned char mask,
+ unsigned char grsave, struct ia64_state_record *sr)
+{
+ int i, region_start;
+
+ if (!(sr->in_body || sr->first_region))
+ finish_prologue (sr);
+ sr->first_region = 0;
+
+ /* check if we're done: */
+ if (sr->when_target < sr->region_start + sr->region_len)
+ {
+ sr->done = 1;
+ return;
+ }
+
+ region_start = sr->region_start + sr->region_len;
+
+ for (i = 0; i < sr->epilogue_count; ++i)
+ pop (sr);
+ sr->epilogue_count = 0;
+ sr->when_sp_restored = IA64_WHEN_NEVER;
+
+ sr->region_start = region_start;
+ sr->region_len = rlen;
+ sr->in_body = body;
+
+ if (!body)
+ {
+ push (sr);
+
+ if (mask)
+ for (i = 0; i < 4; ++i)
+ {
+ if (mask & 0x8)
+ set_reg (sr->curr.reg + unw.save_order[i], IA64_WHERE_GR,
+ sr->region_start + sr->region_len - 1, grsave++);
+ mask <<= 1;
+ }
+ sr->gr_save_loc = grsave;
+ sr->any_spills = 0;
+ sr->imask = 0;
+ sr->spill_offset = 0x10; /* default to psp+16 */
+ }
+}
+
+/* Prologue descriptors. */
+
+static inline void
+desc_abi (unsigned char abi, unsigned char context,
+ struct ia64_state_record *sr)
+{
+ sr->abi_marker = (abi << 8) | context;
+}
+
+static inline void
+desc_br_gr (unsigned char brmask, unsigned char gr,
+ struct ia64_state_record *sr)
+{
+ int i;
+
+ for (i = 0; i < 5; ++i)
+ {
+ if (brmask & 1)
+ set_reg (sr->curr.reg + IA64_REG_B1 + i, IA64_WHERE_GR,
+ sr->region_start + sr->region_len - 1, gr++);
+ brmask >>= 1;
+ }
+}
+
+static inline void
+desc_br_mem (unsigned char brmask, struct ia64_state_record *sr)
+{
+ int i;
+
+ for (i = 0; i < 5; ++i)
+ {
+ if (brmask & 1)
+ {
+ set_reg (sr->curr.reg + IA64_REG_B1 + i, IA64_WHERE_SPILL_HOME,
+ sr->region_start + sr->region_len - 1, 0);
+ sr->any_spills = 1;
+ }
+ brmask >>= 1;
+ }
+}
+
+static inline void
+desc_frgr_mem (unsigned char grmask, unw_word frmask,
+ struct ia64_state_record *sr)
+{
+ int i;
+
+ for (i = 0; i < 4; ++i)
+ {
+ if ((grmask & 1) != 0)
+ {
+ set_reg (sr->curr.reg + IA64_REG_R4 + i, IA64_WHERE_SPILL_HOME,
+ sr->region_start + sr->region_len - 1, 0);
+ sr->any_spills = 1;
+ }
+ grmask >>= 1;
+ }
+ for (i = 0; i < 20; ++i)
+ {
+ if ((frmask & 1) != 0)
+ {
+ int base = (i < 4) ? IA64_REG_F2 : IA64_REG_F16 - 4;
+ set_reg (sr->curr.reg + base + i, IA64_WHERE_SPILL_HOME,
+ sr->region_start + sr->region_len - 1, 0);
+ sr->any_spills = 1;
+ }
+ frmask >>= 1;
+ }
+}
+
+static inline void
+desc_fr_mem (unsigned char frmask, struct ia64_state_record *sr)
+{
+ int i;
+
+ for (i = 0; i < 4; ++i)
+ {
+ if ((frmask & 1) != 0)
+ {
+ set_reg (sr->curr.reg + IA64_REG_F2 + i, IA64_WHERE_SPILL_HOME,
+ sr->region_start + sr->region_len - 1, 0);
+ sr->any_spills = 1;
+ }
+ frmask >>= 1;
+ }
+}
+
+static inline void
+desc_gr_gr (unsigned char grmask, unsigned char gr,
+ struct ia64_state_record *sr)
+{
+ int i;
+
+ for (i = 0; i < 4; ++i)
+ {
+ if ((grmask & 1) != 0)
+ set_reg (sr->curr.reg + IA64_REG_R4 + i, IA64_WHERE_GR,
+ sr->region_start + sr->region_len - 1, gr++);
+ grmask >>= 1;
+ }
+}
+
+static inline void
+desc_gr_mem (unsigned char grmask, struct ia64_state_record *sr)
+{
+ int i;
+
+ for (i = 0; i < 4; ++i)
+ {
+ if ((grmask & 1) != 0)
+ {
+ set_reg (sr->curr.reg + IA64_REG_R4 + i, IA64_WHERE_SPILL_HOME,
+ sr->region_start + sr->region_len - 1, 0);
+ sr->any_spills = 1;
+ }
+ grmask >>= 1;
+ }
+}
+
+static inline void
+desc_mem_stack_f (unw_word t, unw_word size, struct ia64_state_record *sr)
+{
+ set_reg (sr->curr.reg + IA64_REG_PSP, IA64_WHERE_NONE,
+ sr->region_start + MIN ((int) t, sr->region_len - 1), 16 * size);
+}
+
+static inline void
+desc_mem_stack_v (unw_word t, struct ia64_state_record *sr)
+{
+ sr->curr.reg[IA64_REG_PSP].when =
+ sr->region_start + MIN ((int) t, sr->region_len - 1);
+}
+
+static inline void
+desc_reg_gr (unsigned char reg, unsigned char dst,
+ struct ia64_state_record *sr)
+{
+ set_reg (sr->curr.reg + reg, IA64_WHERE_GR,
+ sr->region_start + sr->region_len - 1, dst);
+}
+
+static inline void
+desc_reg_psprel (unsigned char reg, unw_word pspoff,
+ struct ia64_state_record *sr)
+{
+ set_reg (sr->curr.reg + reg, IA64_WHERE_PSPREL,
+ sr->region_start + sr->region_len - 1, 0x10 - 4 * pspoff);
+}
+
+static inline void
+desc_reg_sprel (unsigned char reg, unw_word spoff,
+ struct ia64_state_record *sr)
+{
+ set_reg (sr->curr.reg + reg, IA64_WHERE_SPREL,
+ sr->region_start + sr->region_len - 1, 4 * spoff);
+}
+
+static inline void
+desc_rp_br (unsigned char dst, struct ia64_state_record *sr)
+{
+ sr->return_link_reg = dst;
+}
+
+static inline void
+desc_reg_when (unsigned char regnum, unw_word t, struct ia64_state_record *sr)
+{
+ struct ia64_reg_info *reg = sr->curr.reg + regnum;
+
+ if (reg->where == IA64_WHERE_NONE)
+ reg->where = IA64_WHERE_GR_SAVE;
+ reg->when = sr->region_start + MIN ((int) t, sr->region_len - 1);
+}
+
+static inline void
+desc_spill_base (unw_word pspoff, struct ia64_state_record *sr)
+{
+ sr->spill_offset = 0x10 - 4 * pspoff;
+}
+
+static inline unsigned char *
+desc_spill_mask (unsigned char *imaskp, struct ia64_state_record *sr)
+{
+ sr->imask = imaskp;
+ return imaskp + (2 * sr->region_len + 7) / 8;
+}
+
+/* Body descriptors. */
+
+static inline void
+desc_epilogue (unw_word t, unw_word ecount, struct ia64_state_record *sr)
+{
+ sr->when_sp_restored = sr->region_start + sr->region_len - 1 - t;
+ sr->epilogue_count = ecount + 1;
+}
+
+static inline void
+desc_copy_state (unw_word label, struct ia64_state_record *sr)
+{
+ struct ia64_labeled_state *ls;
+
+ for (ls = sr->labeled_states; ls; ls = ls->next)
+ {
+ if (ls->label == label)
+ {
+ free_state_stack (&sr->curr);
+ memcpy (&sr->curr, &ls->saved_state, sizeof (sr->curr));
+ sr->curr.next = dup_state_stack (ls->saved_state.next);
+ return;
+ }
+ }
+ print_error ("libunwind: failed to find labeled state\n");
+}
+
+static inline void
+desc_label_state (unw_word label, struct ia64_state_record *sr)
+{
+ struct ia64_labeled_state *ls;
+
+ ls = alloc_labeled_state ();
+ if (!ls)
+ {
+ print_error ("unwind.desc_label_state(): out of memory\n");
+ return;
+ }
+ ls->label = label;
+ memcpy (&ls->saved_state, &sr->curr, sizeof (ls->saved_state));
+ ls->saved_state.next = dup_state_stack (sr->curr.next);
+
+ /* insert into list of labeled states: */
+ ls->next = sr->labeled_states;
+ sr->labeled_states = ls;
+}
+
+/* General descriptors. */
+
+static inline int
+desc_is_active (unsigned char qp, unw_word t, struct ia64_state_record *sr)
+{
+ if (sr->when_target <= sr->region_start + MIN ((int) t, sr->region_len - 1))
+ return 0;
+ if (qp > 0)
+ {
+ if ((sr->pr_val & ((unw_word_t) 1 << qp)) == 0)
+ return 0;
+ sr->pr_mask |= ((unw_word_t) 1 << qp);
+ }
+ return 1;
+}
+
+static inline void
+desc_restore_p (unsigned char qp, unw_word t, unsigned char abreg,
+ struct ia64_state_record *sr)
+{
+ struct ia64_reg_info *r;
+
+ if (!desc_is_active (qp, t, sr))
+ return;
+
+ r = sr->curr.reg + decode_abreg (abreg, 0);
+ r->where = IA64_WHERE_NONE;
+ r->when = IA64_WHEN_NEVER;
+ r->val = 0;
+}
+
+static inline void
+desc_spill_reg_p (unsigned char qp, unw_word t, unsigned char abreg,
+ unsigned char x, unsigned char ytreg,
+ struct ia64_state_record *sr)
+{
+ enum ia64_where where = IA64_WHERE_GR;
+ struct ia64_reg_info *r;
+
+ if (!desc_is_active (qp, t, sr))
+ return;
+
+ if (x)
+ where = IA64_WHERE_BR;
+ else if (ytreg & 0x80)
+ where = IA64_WHERE_FR;
+
+ r = sr->curr.reg + decode_abreg (abreg, 0);
+ r->where = where;
+ r->when = sr->region_start + MIN ((int) t, sr->region_len - 1);
+ r->val = (ytreg & 0x7f);
+}
+
+static inline void
+desc_spill_psprel_p (unsigned char qp, unw_word t, unsigned char abreg,
+ unw_word pspoff, struct ia64_state_record *sr)
+{
+ struct ia64_reg_info *r;
+
+ if (!desc_is_active (qp, t, sr))
+ return;
+
+ r = sr->curr.reg + decode_abreg (abreg, 1);
+ r->where = IA64_WHERE_PSPREL;
+ r->when = sr->region_start + MIN ((int) t, sr->region_len - 1);
+ r->val = 0x10 - 4 * pspoff;
+}
+
+static inline void
+desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg,
+ unw_word spoff, struct ia64_state_record *sr)
+{
+ struct ia64_reg_info *r;
+
+ if (!desc_is_active (qp, t, sr))
+ return;
+
+ r = sr->curr.reg + decode_abreg (abreg, 1);
+ r->where = IA64_WHERE_SPREL;
+ r->when = sr->region_start + MIN ((int) t, sr->region_len - 1);
+ r->val = 4 * spoff;
+}
+
+#define UNW_DEC_BAD_CODE(code) \
+ print_error ("libunwind: unknown code encountered\n")
+
+/* Register names. */
+#define UNW_REG_BSP IA64_REG_BSP
+#define UNW_REG_BSPSTORE IA64_REG_BSPSTORE
+#define UNW_REG_FPSR IA64_REG_FPSR
+#define UNW_REG_LC IA64_REG_LC
+#define UNW_REG_PFS IA64_REG_PFS
+#define UNW_REG_PR IA64_REG_PR
+#define UNW_REG_RNAT IA64_REG_RNAT
+#define UNW_REG_PSP IA64_REG_PSP
+#define UNW_REG_RP IA64_REG_IP
+#define UNW_REG_UNAT IA64_REG_UNAT
+
+/* Region headers. */
+#define UNW_DEC_PROLOGUE_GR(fmt,r,m,gr,arg) desc_prologue(0,r,m,gr,arg)
+#define UNW_DEC_PROLOGUE(fmt,b,r,arg) desc_prologue(b,r,0,32,arg)
+
+/* Prologue descriptors. */
+#define UNW_DEC_ABI(fmt,a,c,arg) desc_abi(a,c,arg)
+#define UNW_DEC_BR_GR(fmt,b,g,arg) desc_br_gr(b,g,arg)
+#define UNW_DEC_BR_MEM(fmt,b,arg) desc_br_mem(b,arg)
+#define UNW_DEC_FRGR_MEM(fmt,g,f,arg) desc_frgr_mem(g,f,arg)
+#define UNW_DEC_FR_MEM(fmt,f,arg) desc_fr_mem(f,arg)
+#define UNW_DEC_GR_GR(fmt,m,g,arg) desc_gr_gr(m,g,arg)
+#define UNW_DEC_GR_MEM(fmt,m,arg) desc_gr_mem(m,arg)
+#define UNW_DEC_MEM_STACK_F(fmt,t,s,arg) desc_mem_stack_f(t,s,arg)
+#define UNW_DEC_MEM_STACK_V(fmt,t,arg) desc_mem_stack_v(t,arg)
+#define UNW_DEC_REG_GR(fmt,r,d,arg) desc_reg_gr(r,d,arg)
+#define UNW_DEC_REG_PSPREL(fmt,r,o,arg) desc_reg_psprel(r,o,arg)
+#define UNW_DEC_REG_SPREL(fmt,r,o,arg) desc_reg_sprel(r,o,arg)
+#define UNW_DEC_REG_WHEN(fmt,r,t,arg) desc_reg_when(r,t,arg)
+#define UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg) \
+ desc_reg_when(IA64_REG_PRI_UNAT_GR,t,arg)
+#define UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg) \
+ desc_reg_when(IA64_REG_PRI_UNAT_MEM,t,arg)
+#define UNW_DEC_PRIUNAT_GR(fmt,r,arg) \
+ desc_reg_gr(IA64_REG_PRI_UNAT_GR,r,arg)
+#define UNW_DEC_PRIUNAT_PSPREL(fmt,o,arg) \
+ desc_reg_psprel(IA64_REG_PRI_UNAT_MEM,o,arg)
+#define UNW_DEC_PRIUNAT_SPREL(fmt,o,arg) \
+ desc_reg_sprel(IA64_REG_PRI_UNAT_MEM,o,arg)
+#define UNW_DEC_RP_BR(fmt,d,arg) desc_rp_br(d,arg)
+#define UNW_DEC_SPILL_BASE(fmt,o,arg) desc_spill_base(o,arg)
+#define UNW_DEC_SPILL_MASK(fmt,m,arg) (m = desc_spill_mask(m,arg))
+
+/* Body descriptors. */
+#define UNW_DEC_EPILOGUE(fmt,t,c,arg) desc_epilogue(t,c,arg)
+#define UNW_DEC_COPY_STATE(fmt,l,arg) desc_copy_state(l,arg)
+#define UNW_DEC_LABEL_STATE(fmt,l,arg) desc_label_state(l,arg)
+
+/* General unwind descriptors. */
+#define UNW_DEC_SPILL_REG_P(f,p,t,a,x,y,arg) desc_spill_reg_p(p,t,a,x,y,arg)
+#define UNW_DEC_SPILL_REG(f,t,a,x,y,arg) desc_spill_reg_p(0,t,a,x,y,arg)
+#define UNW_DEC_SPILL_PSPREL_P(f,p,t,a,o,arg) \
+ desc_spill_psprel_p(p,t,a,o,arg)
+#define UNW_DEC_SPILL_PSPREL(f,t,a,o,arg) \
+ desc_spill_psprel_p(0,t,a,o,arg)
+#define UNW_DEC_SPILL_SPREL_P(f,p,t,a,o,arg) desc_spill_sprel_p(p,t,a,o,arg)
+#define UNW_DEC_SPILL_SPREL(f,t,a,o,arg) desc_spill_sprel_p(0,t,a,o,arg)
+#define UNW_DEC_RESTORE_P(f,p,t,a,arg) desc_restore_p(p,t,a,arg)
+#define UNW_DEC_RESTORE(f,t,a,arg) desc_restore_p(0,t,a,arg)
+
+#include "unwind_decoder.h"
+
+#ifdef _U_dyn_op
+
+/* parse dynamic unwind info */
+
+static struct ia64_reg_info *
+lookup_preg (int regnum, int memory, struct ia64_state_record *sr)
+{
+ int preg;
+
+ switch (regnum)
+ {
+ case UNW_IA64_AR_BSP: preg = IA64_REG_BSP; break;
+ case UNW_IA64_AR_BSPSTORE: preg = IA64_REG_BSPSTORE; break;
+ case UNW_IA64_AR_FPSR: preg = IA64_REG_FPSR; break;
+ case UNW_IA64_AR_LC: preg = IA64_REG_LC; break;
+ case UNW_IA64_AR_PFS: preg = IA64_REG_PFS; break;
+ case UNW_IA64_AR_RNAT: preg = IA64_REG_RNAT; break;
+ case UNW_IA64_AR_UNAT: preg = IA64_REG_UNAT; break;
+ case UNW_IA64_BR + 0: preg = IA64_REG_IP; break;
+ case UNW_IA64_PR: preg = IA64_REG_PR; break;
+ case UNW_IA64_SP: preg = IA64_REG_PSP; break;
+
+ case UNW_IA64_NAT:
+ if (memory)
+ preg = IA64_REG_PRI_UNAT_MEM;
+ else
+ preg = IA64_REG_PRI_UNAT_GR;
+ break;
+
+ case UNW_IA64_GR + 4 ... UNW_IA64_GR + 7:
+ preg = IA64_REG_R4 + (regnum - (UNW_IA64_GR + 4));
+ break;
+
+ case UNW_IA64_BR + 1 ... UNW_IA64_BR + 5:
+ preg = IA64_REG_B1 + (regnum - UNW_IA64_BR);
+ break;
+
+ case UNW_IA64_FR + 2 ... UNW_IA64_FR + 5:
+ preg = IA64_REG_F2 + (regnum - (UNW_IA64_FR + 2));
+ break;
+
+ case UNW_IA64_FR + 16 ... UNW_IA64_FR + 31:
+ preg = IA64_REG_F16 + (regnum - (UNW_IA64_FR + 16));
+ break;
+
+ default:
+ Dprintf ("%s: invalid register number %d\n", __FUNCTION__, regnum);
+ return NULL;
+ }
+ return sr->curr.reg + preg;
+}
+
+/* An alias directive inside a region of length RLEN is interpreted to
+ mean that the region behaves exactly like the first RLEN
+ instructions at the aliased IP. RLEN=0 implies that the current
+ state matches exactly that of before the instruction at the aliased
+ IP is executed. */
+
+static int
+desc_alias (unw_dyn_op_t *op, struct cursor *c, struct ia64_state_record *sr)
+{
+ struct ia64_state_record orig_sr = *sr;
+ int i, ret, when, rlen = sr->region_len;
+ unw_word_t new_ip;
+
+ when = MIN (sr->when_target, rlen);
+ new_ip = op->val + ((when / 3) * 16 + (when % 3));
+
+ if ((ret = ia64_fetch_proc_info (c, new_ip, 1)) < 0)
+ return ret;
+
+ if ((ret = create_state_record_for (c, sr, new_ip)) < 0)
+ return ret;
+
+ sr->first_region = orig_sr.first_region;
+ sr->done = 0;
+ sr->any_spills |= orig_sr.any_spills;
+ sr->in_body = orig_sr.in_body;
+ sr->region_start = orig_sr.region_start;
+ sr->region_len = orig_sr.region_len;
+ if (sr->when_sp_restored != IA64_WHEN_NEVER)
+ sr->when_sp_restored = op->when + MIN (orig_sr.when_sp_restored, rlen);
+ sr->epilogue_count = orig_sr.epilogue_count;
+ sr->when_target = orig_sr.when_target;
+
+ for (i = 0; i < IA64_NUM_PREGS; ++i)
+ if (sr->curr.reg[i].when != IA64_WHEN_NEVER)
+ sr->curr.reg[i].when = op->when + MIN (sr->curr.reg[i].when, rlen);
+
+ ia64_free_state_record (sr);
+ sr->labeled_states = orig_sr.labeled_states;
+ sr->curr.next = orig_sr.curr.next;
+ return 0;
+}
+
+static inline int
+parse_dynamic (struct cursor *c, struct ia64_state_record *sr)
+{
+ unw_dyn_info_t *di = c->pi.unwind_info;
+ unw_dyn_proc_info_t *proc = &di->u.pi;
+ unw_dyn_region_info_t *r;
+ struct ia64_reg_info *ri;
+ enum ia64_where where;
+ int32_t when, len;
+ unw_dyn_op_t *op;
+ unw_word_t val;
+ int memory, ret;
+ int8_t qp;
+
+ for (r = proc->regions; r; r = r->next)
+ {
+ len = r->insn_count;
+ if (len < 0)
+ {
+ if (r->next)
+ {
+ Debug (1, "negative region length allowed in last region only!");
+ return -UNW_EINVAL;
+ }
+ len = -len;
+ /* hack old region info to set the start where we need it: */
+ sr->region_start = (di->end_ip - di->start_ip) / 0x10 * 3 - len;
+ sr->region_len = 0;
+ }
+ /* all regions are treated as prologue regions: */
+ desc_prologue (0, len, 0, 0, sr);
+
+ if (sr->done)
+ return 0;
+
+ for (op = r->op; op < r->op + r->op_count; ++op)
+ {
+ when = op->when;
+ val = op->val;
+ qp = op->qp;
+
+ if (!desc_is_active (qp, when, sr))
+ continue;
+
+ when = sr->region_start + MIN ((int) when, sr->region_len - 1);
+
+ switch (op->tag)
+ {
+ case UNW_DYN_SAVE_REG:
+ memory = 0;
+ if ((unsigned) (val - UNW_IA64_GR) < 128)
+ where = IA64_WHERE_GR;
+ else if ((unsigned) (val - UNW_IA64_FR) < 128)
+ where = IA64_WHERE_FR;
+ else if ((unsigned) (val - UNW_IA64_BR) < 8)
+ where = IA64_WHERE_BR;
+ else
+ {
+ Dprintf ("%s: can't save to register number %d\n",
+ __FUNCTION__, (int) op->reg);
+ return -UNW_EBADREG;
+ }
+ /* fall through */
+ update_reg_info:
+ ri = lookup_preg (op->reg, memory, sr);
+ if (!ri)
+ return -UNW_EBADREG;
+ ri->where = where;
+ ri->when = when;
+ ri->val = val;
+ break;
+
+ case UNW_DYN_SPILL_FP_REL:
+ memory = 1;
+ where = IA64_WHERE_PSPREL;
+ val = 0x10 - val;
+ goto update_reg_info;
+
+ case UNW_DYN_SPILL_SP_REL:
+ memory = 1;
+ where = IA64_WHERE_SPREL;
+ goto update_reg_info;
+
+ case UNW_DYN_ADD:
+ if (op->reg == UNW_IA64_SP)
+ {
+ if (val & 0xf)
+ {
+ Dprintf ("%s: frame-size %ld not an integer "
+ "multiple of 16\n",
+ __FUNCTION__, (long) op->val);
+ return -UNW_EINVAL;
+ }
+ desc_mem_stack_f (when, -((int64_t) val / 16), sr);
+ }
+ else
+ {
+ Dprintf ("%s: can only ADD to stack-pointer\n",
+ __FUNCTION__);
+ return -UNW_EBADREG;
+ }
+ break;
+
+ case UNW_DYN_POP_FRAMES:
+ sr->when_sp_restored = when;
+ sr->epilogue_count = op->val;
+ break;
+
+ case UNW_DYN_LABEL_STATE:
+ desc_label_state (op->val, sr);
+ break;
+
+ case UNW_DYN_COPY_STATE:
+ desc_copy_state (op->val, sr);
+ break;
+
+ case UNW_DYN_ALIAS:
+ if ((ret = desc_alias (op, c, sr)) < 0)
+ return ret;
+
+ case UNW_DYN_STOP:
+ goto end_of_ops;
+ }
+ }
+ end_of_ops:
+ ;
+ }
+ return 0;
+}
+#else
+# define parse_dynamic(c,sr) (-UNW_EINVAL)
+#endif /* _U_dyn_op */
+
+
+HIDDEN int
+ia64_fetch_proc_info (struct cursor *c, unw_word_t ip, int need_unwind_info)
+{
+ int ret, dynamic = 1;
+
+ if (c->pi_valid && !need_unwind_info)
+ return 0;
+
+ /* check dynamic info first --- it overrides everything else */
+ ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, need_unwind_info,
+ c->as_arg);
+ if (ret == -UNW_ENOINFO)
+ {
+ dynamic = 0;
+ ret = ia64_find_proc_info (c, ip, need_unwind_info);
+ }
+
+ c->pi_valid = 1;
+ c->pi_is_dynamic = dynamic;
+ return ret;
+}
+
+static inline void
+put_unwind_info (struct cursor *c, unw_proc_info_t *pi)
+{
+ if (!c->pi_valid)
+ return;
+
+ if (c->pi_is_dynamic)
+ unwi_put_dynamic_unwind_info (c->as, pi, c->as_arg);
+ else
+ ia64_put_unwind_info (c, pi);
+}
+
+static int
+create_state_record_for (struct cursor *c, struct ia64_state_record *sr,
+ unw_word_t ip)
+{
+ unw_word_t predicates = c->pr;
+ struct ia64_reg_info *r;
+ uint8_t *dp, *desc_end;
+ int ret;
+
+ assert (c->pi_valid);
+
+ /* build state record */
+ memset (sr, 0, sizeof (*sr));
+ for (r = sr->curr.reg; r < sr->curr.reg + IA64_NUM_PREGS; ++r)
+ r->when = IA64_WHEN_NEVER;
+ sr->pr_val = predicates;
+ sr->first_region = 1;
+
+ if (!c->pi.unwind_info)
+ {
+ /* No info, return default unwinder (leaf proc, no mem stack, no
+ saved regs), rp in b0, pfs in ar.pfs. */
+ Debug (1, "no unwind info for ip=0x%lx (gp=%lx)\n",
+ (long) ip, (long) c->pi.gp);
+ sr->curr.reg[IA64_REG_IP].where = IA64_WHERE_BR;
+ sr->curr.reg[IA64_REG_IP].when = -1;
+ sr->curr.reg[IA64_REG_IP].val = 0;
+ goto out;
+ }
+
+ sr->when_target = (3 * ((ip & ~(unw_word_t) 0xf) - c->pi.start_ip) / 16
+ + (ip & 0xf));
+
+ switch (c->pi.format)
+ {
+ case UNW_INFO_FORMAT_TABLE:
+ case UNW_INFO_FORMAT_REMOTE_TABLE:
+ dp = c->pi.unwind_info;
+ desc_end = dp + c->pi.unwind_info_size;
+ while (!sr->done && dp < desc_end)
+ dp = unw_decode (dp, sr->in_body, sr);
+ ret = 0;
+ break;
+
+ case UNW_INFO_FORMAT_DYNAMIC:
+ ret = parse_dynamic (c, sr);
+ break;
+
+ default:
+ ret = -UNW_EINVAL;
+ }
+
+ put_unwind_info (c, &c->pi);
+
+ if (ret < 0)
+ return ret;
+
+ if (sr->when_target > sr->when_sp_restored)
+ {
+ /* sp has been restored and all values on the memory stack below
+ psp also have been restored. */
+ sr->curr.reg[IA64_REG_PSP].val = 0;
+ sr->curr.reg[IA64_REG_PSP].where = IA64_WHERE_NONE;
+ sr->curr.reg[IA64_REG_PSP].when = IA64_WHEN_NEVER;
+ for (r = sr->curr.reg; r < sr->curr.reg + IA64_NUM_PREGS; ++r)
+ if ((r->where == IA64_WHERE_PSPREL && r->val <= 0x10)
+ || r->where == IA64_WHERE_SPREL)
+ {
+ r->val = 0;
+ r->where = IA64_WHERE_NONE;
+ r->when = IA64_WHEN_NEVER;
+ }
+ }
+
+ /* If RP did't get saved, generate entry for the return link
+ register. */
+ if (sr->curr.reg[IA64_REG_IP].when >= sr->when_target)
+ {
+ sr->curr.reg[IA64_REG_IP].where = IA64_WHERE_BR;
+ sr->curr.reg[IA64_REG_IP].when = -1;
+ sr->curr.reg[IA64_REG_IP].val = sr->return_link_reg;
+ }
+
+ if (sr->when_target > sr->curr.reg[IA64_REG_BSP].when
+ && sr->when_target > sr->curr.reg[IA64_REG_BSPSTORE].when
+ && sr->when_target > sr->curr.reg[IA64_REG_RNAT].when)
+ {
+ Debug (8, "func 0x%lx may switch the register-backing-store\n",
+ c->pi.start_ip);
+ c->pi.flags |= UNW_PI_FLAG_IA64_RBS_SWITCH;
+ }
+ out:
+#if UNW_DEBUG
+ if (unwi_debug_level > 2)
+ {
+ Dprintf ("%s: state record for func 0x%lx, t=%u (flags=0x%lx):\n",
+ __FUNCTION__,
+ (long) c->pi.start_ip, sr->when_target, (long) c->pi.flags);
+ for (r = sr->curr.reg; r < sr->curr.reg + IA64_NUM_PREGS; ++r)
+ {
+ if (r->where != IA64_WHERE_NONE || r->when != IA64_WHEN_NEVER)
+ {
+ Dprintf (" %s <- ", unw.preg_name[r - sr->curr.reg]);
+ switch (r->where)
+ {
+ case IA64_WHERE_GR:
+ Dprintf ("r%lu", (long) r->val);
+ break;
+ case IA64_WHERE_FR:
+ Dprintf ("f%lu", (long) r->val);
+ break;
+ case IA64_WHERE_BR:
+ Dprintf ("b%lu", (long) r->val);
+ break;
+ case IA64_WHERE_SPREL:
+ Dprintf ("[sp+0x%lx]", (long) r->val);
+ break;
+ case IA64_WHERE_PSPREL:
+ Dprintf ("[psp+0x%lx]", (long) r->val);
+ break;
+ case IA64_WHERE_NONE:
+ Dprintf ("%s+0x%lx",
+ unw.preg_name[r - sr->curr.reg], (long) r->val);
+ break;
+ default:
+ Dprintf ("BADWHERE(%d)", r->where);
+ break;
+ }
+ Dprintf ("\t\t%d\n", r->when);
+ }
+ }
+ }
+#endif
+ return 0;
+}
+
+/* The proc-info must be valid for IP before this routine can be
+ called. */
+HIDDEN int
+ia64_create_state_record (struct cursor *c, struct ia64_state_record *sr)
+{
+ return create_state_record_for (c, sr, c->ip);
+}
+
+HIDDEN int
+ia64_free_state_record (struct ia64_state_record *sr)
+{
+ struct ia64_labeled_state *ls, *next;
+
+ /* free labeled register states & stack: */
+
+ for (ls = sr->labeled_states; ls; ls = next)
+ {
+ next = ls->next;
+ free_state_stack (&ls->saved_state);
+ free_labeled_state (ls);
+ }
+ free_state_stack (&sr->curr);
+
+ return 0;
+}
+
+HIDDEN int
+ia64_make_proc_info (struct cursor *c)
+{
+ int ret, caching = c->as->caching_policy != UNW_CACHE_NONE;
+
+ if (!caching || ia64_get_cached_proc_info (c) < 0)
+ {
+ /* Lookup it up the slow way... */
+ if ((ret = ia64_fetch_proc_info (c, c->ip, 0)) < 0)
+ return ret;
+ if (caching)
+ ia64_cache_proc_info (c);
+ }
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/ia64/Grbs.c b/src/pal/src/libunwind/src/ia64/Grbs.c
new file mode 100644
index 0000000000..e7c01fe219
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Grbs.c
@@ -0,0 +1,319 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Logically, we like to think of the stack as a contiguous region of
+memory. Unfortunately, this logical view doesn't work for the
+register backing store, because the RSE is an asynchronous engine and
+because UNIX/Linux allow for stack-switching via sigaltstack(2).
+Specifically, this means that any given stacked register may or may
+not be backed up by memory in the current stack. If not, then the
+backing memory may be found in any of the "more inner" (younger)
+stacks. The routines in this file help manage the discontiguous
+nature of the register backing store. The routines are completely
+independent of UNIX/Linux, but each stack frame that switches the
+backing store is expected to reserve 4 words for use by libunwind. For
+example, in the Linux sigcontext, sc_fr[0] and sc_fr[1] serve this
+purpose. */
+
+#include "unwind_i.h"
+
+#if UNW_DEBUG
+
+HIDDEN const char *
+ia64_strloc (ia64_loc_t loc)
+{
+ static char buf[128];
+
+ if (IA64_IS_NULL_LOC (loc))
+ return "<null>";
+
+ buf[0] = '\0';
+
+ if (IA64_IS_MEMSTK_NAT (loc))
+ strcat (buf, "memstk_nat(");
+ if (IA64_IS_UC_LOC (loc))
+ strcat (buf, "uc(");
+ if (IA64_IS_FP_LOC (loc))
+ strcat (buf, "fp(");
+
+ if (IA64_IS_REG_LOC (loc))
+ sprintf (buf + strlen (buf), "%s", unw_regname (IA64_GET_REG (loc)));
+ else
+ sprintf (buf + strlen (buf), "0x%llx",
+ (unsigned long long) IA64_GET_ADDR (loc));
+
+ if (IA64_IS_FP_LOC (loc))
+ strcat (buf, ")");
+ if (IA64_IS_UC_LOC (loc))
+ strcat (buf, ")");
+ if (IA64_IS_MEMSTK_NAT (loc))
+ strcat (buf, ")");
+
+ return buf;
+}
+
+#endif /* UNW_DEBUG */
+
+HIDDEN int
+rbs_switch (struct cursor *c,
+ unw_word_t saved_bsp, unw_word_t saved_bspstore,
+ ia64_loc_t saved_rnat_loc)
+{
+ struct rbs_area *rbs = &c->rbs_area[c->rbs_curr];
+ unw_word_t lo, ndirty, rbs_base;
+ int ret;
+
+ Debug (10, "(left=%u, curr=%u)\n", c->rbs_left_edge, c->rbs_curr);
+
+ /* Calculate address "lo" at which the backing store starts: */
+ ndirty = rse_num_regs (saved_bspstore, saved_bsp);
+ lo = rse_skip_regs (c->bsp, -ndirty);
+
+ rbs->size = (rbs->end - lo);
+
+ /* If the previously-recorded rbs-area is empty we don't need to
+ track it and we can simply overwrite it... */
+ if (rbs->size)
+ {
+ Debug (10, "inner=[0x%lx-0x%lx)\n",
+ (long) (rbs->end - rbs->size), (long) rbs->end);
+
+ c->rbs_curr = (c->rbs_curr + 1) % ARRAY_SIZE (c->rbs_area);
+ rbs = c->rbs_area + c->rbs_curr;
+
+ if (c->rbs_curr == c->rbs_left_edge)
+ c->rbs_left_edge = (c->rbs_left_edge + 1) % ARRAY_SIZE (c->rbs_area);
+ }
+
+ if ((ret = rbs_get_base (c, saved_bspstore, &rbs_base)) < 0)
+ return ret;
+
+ rbs->end = saved_bspstore;
+ rbs->size = saved_bspstore - rbs_base;
+ rbs->rnat_loc = saved_rnat_loc;
+
+ c->bsp = saved_bsp;
+
+ Debug (10, "outer=[0x%llx-0x%llx), rnat@%s\n", (long long) rbs_base,
+ (long long) rbs->end, ia64_strloc (rbs->rnat_loc));
+ return 0;
+}
+
+HIDDEN int
+rbs_find_stacked (struct cursor *c, unw_word_t regs_to_skip,
+ ia64_loc_t *locp, ia64_loc_t *rnat_locp)
+{
+ unw_word_t nregs, bsp = c->bsp, curr = c->rbs_curr, n;
+ unw_word_t left_edge = c->rbs_left_edge;
+#if UNW_DEBUG
+ int reg = 32 + regs_to_skip;
+#endif
+
+ while (!rbs_contains (&c->rbs_area[curr], bsp))
+ {
+ if (curr == left_edge)
+ {
+ Debug (1, "could not find register r%d!\n", reg);
+ return -UNW_EBADREG;
+ }
+
+ n = rse_num_regs (c->rbs_area[curr].end, bsp);
+ curr = (curr + ARRAY_SIZE (c->rbs_area) - 1) % ARRAY_SIZE (c->rbs_area);
+ bsp = rse_skip_regs (c->rbs_area[curr].end - c->rbs_area[curr].size, n);
+ }
+
+ while (1)
+ {
+ nregs = rse_num_regs (bsp, c->rbs_area[curr].end);
+
+ if (regs_to_skip < nregs)
+ {
+ /* found it: */
+ unw_word_t addr;
+
+ addr = rse_skip_regs (bsp, regs_to_skip);
+ if (locp)
+ *locp = rbs_loc (c->rbs_area + curr, addr);
+ if (rnat_locp)
+ *rnat_locp = rbs_get_rnat_loc (c->rbs_area + curr, addr);
+ return 0;
+ }
+
+ if (curr == left_edge)
+ {
+ Debug (1, "could not find register r%d!\n", reg);
+ return -UNW_EBADREG;
+ }
+
+ regs_to_skip -= nregs;
+
+ curr = (curr + ARRAY_SIZE (c->rbs_area) - 1) % ARRAY_SIZE (c->rbs_area);
+ bsp = c->rbs_area[curr].end - c->rbs_area[curr].size;
+ }
+}
+
+#ifdef NEED_RBS_COVER_AND_FLUSH
+
+static inline int
+get_rnat (struct cursor *c, struct rbs_area *rbs, unw_word_t bsp,
+ unw_word_t *__restrict rnatp)
+{
+ ia64_loc_t rnat_locp = rbs_get_rnat_loc (rbs, bsp);
+
+ return ia64_get (c, rnat_locp, rnatp);
+}
+
+/* Simulate the effect of "cover" followed by a "flushrs" for the
+ target-frame. However, since the target-frame's backing store
+ may not have space for the registers that got spilled onto other
+ rbs-areas, we save those registers to DIRTY_PARTITION where
+ we can then load them via a single "loadrs".
+
+ This function returns the size of the dirty-partition that was
+ created or a negative error-code in case of error.
+
+ Note: This does not modify the rbs_area[] structure in any way. */
+HIDDEN int
+rbs_cover_and_flush (struct cursor *c, unw_word_t nregs,
+ unw_word_t *dirty_partition, unw_word_t *dirty_rnat,
+ unw_word_t *bspstore)
+{
+ unw_word_t n, src_mask, dst_mask, bsp, *dst, src_rnat, dst_rnat = 0;
+ unw_word_t curr = c->rbs_curr, left_edge = c->rbs_left_edge;
+ struct rbs_area *rbs = c->rbs_area + curr;
+ int ret;
+
+ bsp = c->bsp;
+ c->bsp = rse_skip_regs (bsp, nregs);
+
+ if (likely (rbs_contains (rbs, bsp)))
+ {
+ /* at least _some_ registers are on rbs... */
+ n = rse_num_regs (bsp, rbs->end);
+ if (likely (n >= nregs))
+ {
+ /* common case #1: all registers are on current rbs... */
+ /* got lucky: _all_ registers are on rbs... */
+ ia64_loc_t rnat_loc = rbs_get_rnat_loc (rbs, c->bsp);
+
+ *bspstore = c->bsp;
+
+ if (IA64_IS_REG_LOC (rnat_loc))
+ {
+ unw_word_t rnat_addr = (unw_word_t)
+ tdep_uc_addr (c->as_arg, UNW_IA64_AR_RNAT, NULL);
+ rnat_loc = IA64_LOC_ADDR (rnat_addr, 0);
+ }
+ c->loc[IA64_REG_RNAT] = rnat_loc;
+ return 0; /* all done */
+ }
+ nregs -= n; /* account for registers already on the rbs */
+
+ assert (rse_skip_regs (c->bsp, -nregs) == rse_skip_regs (rbs->end, 0));
+ }
+ else
+ /* Earlier frames also didn't get spilled; need to "loadrs" those,
+ too... */
+ nregs += rse_num_regs (rbs->end, bsp);
+
+ /* OK, we need to copy NREGS registers to the dirty partition. */
+
+ *bspstore = bsp = rbs->end;
+ c->loc[IA64_REG_RNAT] = rbs->rnat_loc;
+ assert (!IA64_IS_REG_LOC (rbs->rnat_loc));
+
+ dst = dirty_partition;
+
+ while (nregs > 0)
+ {
+ if (unlikely (!rbs_contains (rbs, bsp)))
+ {
+ /* switch to next non-empty rbs-area: */
+ do
+ {
+ if (curr == left_edge)
+ {
+ Debug (0, "rbs-underflow while flushing %lu regs, "
+ "bsp=0x%lx, dst=0x%p\n", (unsigned long) nregs,
+ (unsigned long) bsp, dst);
+ return -UNW_EBADREG;
+ }
+
+ assert (rse_num_regs (rbs->end, bsp) == 0);
+
+ curr = (curr + ARRAY_SIZE (c->rbs_area) - 1)
+ % ARRAY_SIZE (c->rbs_area);
+ rbs = c->rbs_area + curr;
+ bsp = rbs->end - rbs->size;
+ }
+ while (rbs->size == 0);
+
+ if ((ret = get_rnat (c, rbs, bsp, &src_rnat)) < 0)
+ return ret;
+ }
+
+ if (unlikely (rse_is_rnat_slot (bsp)))
+ {
+ bsp += 8;
+ if ((ret = get_rnat (c, rbs, bsp, &src_rnat)) < 0)
+ return ret;
+ }
+ if (unlikely (rse_is_rnat_slot ((unw_word_t) dst)))
+ {
+ *dst++ = dst_rnat;
+ dst_rnat = 0;
+ }
+
+ src_mask = ((unw_word_t) 1) << rse_slot_num (bsp);
+ dst_mask = ((unw_word_t) 1) << rse_slot_num ((unw_word_t) dst);
+
+ if (src_rnat & src_mask)
+ dst_rnat |= dst_mask;
+ else
+ dst_rnat &= ~dst_mask;
+
+ /* copy one slot: */
+ if ((ret = ia64_get (c, rbs_loc (rbs, bsp), dst)) < 0)
+ return ret;
+
+ /* advance to next slot: */
+ --nregs;
+ bsp += 8;
+ ++dst;
+ }
+ if (unlikely (rse_is_rnat_slot ((unw_word_t) dst)))
+ {
+ /* The LOADRS instruction loads "the N bytes below the current
+ BSP" but BSP can never point to an RNaT slot so if the last
+ destination word happens to be an RNaT slot, we need to write
+ that slot now. */
+ *dst++ = dst_rnat;
+ dst_rnat = 0;
+ }
+ *dirty_rnat = dst_rnat;
+ return (char *) dst - (char *) dirty_partition;
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/ia64/Greg_states_iterate.c b/src/pal/src/libunwind/src/ia64/Greg_states_iterate.c
new file mode 100644
index 0000000000..3570740af1
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Greg_states_iterate.c
@@ -0,0 +1,39 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+ unw_reg_states_callback cb, void *token)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ // Needs dwarf support on ia64
+ // return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+ return -UNW_EINVAL;
+}
diff --git a/src/pal/src/libunwind/src/ia64/Gregs.c b/src/pal/src/libunwind/src/ia64/Gregs.c
new file mode 100644
index 0000000000..ac6f738a6c
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Gregs.c
@@ -0,0 +1,612 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "offsets.h"
+#include "regs.h"
+#include "unwind_i.h"
+
+static inline ia64_loc_t
+linux_scratch_loc (struct cursor *c, unw_regnum_t reg, uint8_t *nat_bitnr)
+{
+#if !defined(UNW_LOCAL_ONLY) || defined(__linux)
+ unw_word_t addr = c->sigcontext_addr, flags, tmp_addr;
+ int i;
+
+ if (ia64_get_abi_marker (c) == ABI_MARKER_LINUX_SIGTRAMP
+ || ia64_get_abi_marker (c) == ABI_MARKER_OLD_LINUX_SIGTRAMP)
+ {
+ switch (reg)
+ {
+ case UNW_IA64_NAT + 2 ... UNW_IA64_NAT + 3:
+ case UNW_IA64_NAT + 8 ... UNW_IA64_NAT + 31:
+ /* Linux sigcontext contains the NaT bit of scratch register
+ N in bit position N of the sc_nat member. */
+ *nat_bitnr = (reg - UNW_IA64_NAT);
+ addr += LINUX_SC_NAT_OFF;
+ break;
+
+ case UNW_IA64_GR + 2 ... UNW_IA64_GR + 3:
+ case UNW_IA64_GR + 8 ... UNW_IA64_GR + 31:
+ addr += LINUX_SC_GR_OFF + 8 * (reg - UNW_IA64_GR);
+ break;
+
+ case UNW_IA64_FR + 6 ... UNW_IA64_FR + 15:
+ addr += LINUX_SC_FR_OFF + 16 * (reg - UNW_IA64_FR);
+ return IA64_LOC_ADDR (addr, IA64_LOC_TYPE_FP);
+
+ case UNW_IA64_FR + 32 ... UNW_IA64_FR + 127:
+ if (ia64_get (c, IA64_LOC_ADDR (addr + LINUX_SC_FLAGS_OFF, 0),
+ &flags) < 0)
+ return IA64_NULL_LOC;
+
+ if (!(flags & IA64_SC_FLAG_FPH_VALID))
+ {
+ /* initialize fph partition: */
+ tmp_addr = addr + LINUX_SC_FR_OFF + 32*16;
+ for (i = 32; i < 128; ++i, tmp_addr += 16)
+ if (ia64_putfp (c, IA64_LOC_ADDR (tmp_addr, 0),
+ unw.read_only.f0) < 0)
+ return IA64_NULL_LOC;
+ /* mark fph partition as valid: */
+ if (ia64_put (c, IA64_LOC_ADDR (addr + LINUX_SC_FLAGS_OFF, 0),
+ flags | IA64_SC_FLAG_FPH_VALID) < 0)
+ return IA64_NULL_LOC;
+ }
+
+ addr += LINUX_SC_FR_OFF + 16 * (reg - UNW_IA64_FR);
+ return IA64_LOC_ADDR (addr, IA64_LOC_TYPE_FP);
+
+ case UNW_IA64_BR + 0: addr += LINUX_SC_BR_OFF + 0; break;
+ case UNW_IA64_BR + 6: addr += LINUX_SC_BR_OFF + 6*8; break;
+ case UNW_IA64_BR + 7: addr += LINUX_SC_BR_OFF + 7*8; break;
+ case UNW_IA64_AR_RSC: addr += LINUX_SC_AR_RSC_OFF; break;
+ case UNW_IA64_AR_CSD: addr += LINUX_SC_AR_CSD_OFF; break;
+ case UNW_IA64_AR_SSD: addr += LINUX_SC_AR_SSD_OFF; break;
+ case UNW_IA64_AR_CCV: addr += LINUX_SC_AR_CCV; break;
+
+ default:
+ if (unw_is_fpreg (reg))
+ return IA64_FPREG_LOC (c, reg);
+ else
+ return IA64_REG_LOC (c, reg);
+ }
+ return IA64_LOC_ADDR (addr, 0);
+ }
+ else
+ {
+ int is_nat = 0;
+
+ if ((unsigned) (reg - UNW_IA64_NAT) < 128)
+ {
+ is_nat = 1;
+ reg -= (UNW_IA64_NAT - UNW_IA64_GR);
+ }
+ if (ia64_get_abi_marker (c) == ABI_MARKER_LINUX_INTERRUPT)
+ {
+ switch (reg)
+ {
+ case UNW_IA64_BR + 6 ... UNW_IA64_BR + 7:
+ addr += LINUX_PT_B6_OFF + 8 * (reg - (UNW_IA64_BR + 6));
+ break;
+
+ case UNW_IA64_AR_CSD: addr += LINUX_PT_CSD_OFF; break;
+ case UNW_IA64_AR_SSD: addr += LINUX_PT_SSD_OFF; break;
+
+ case UNW_IA64_GR + 8 ... UNW_IA64_GR + 11:
+ addr += LINUX_PT_R8_OFF + 8 * (reg - (UNW_IA64_GR + 8));
+ break;
+
+ case UNW_IA64_IP: addr += LINUX_PT_IIP_OFF; break;
+ case UNW_IA64_CFM: addr += LINUX_PT_IFS_OFF; break;
+ case UNW_IA64_AR_UNAT: addr += LINUX_PT_UNAT_OFF; break;
+ case UNW_IA64_AR_PFS: addr += LINUX_PT_PFS_OFF; break;
+ case UNW_IA64_AR_RSC: addr += LINUX_PT_RSC_OFF; break;
+ case UNW_IA64_AR_RNAT: addr += LINUX_PT_RNAT_OFF; break;
+ case UNW_IA64_AR_BSPSTORE: addr += LINUX_PT_BSPSTORE_OFF; break;
+ case UNW_IA64_PR: addr += LINUX_PT_PR_OFF; break;
+ case UNW_IA64_BR + 0: addr += LINUX_PT_B0_OFF; break;
+
+ case UNW_IA64_GR + 1:
+ /* The saved r1 value is valid only in the frame in which
+ it was saved; for everything else we need to look up
+ the appropriate gp value. */
+ if (c->sigcontext_addr != c->sp + 0x10)
+ return IA64_NULL_LOC;
+ addr += LINUX_PT_R1_OFF;
+ break;
+
+ case UNW_IA64_GR + 12: addr += LINUX_PT_R12_OFF; break;
+ case UNW_IA64_GR + 13: addr += LINUX_PT_R13_OFF; break;
+ case UNW_IA64_AR_FPSR: addr += LINUX_PT_FPSR_OFF; break;
+ case UNW_IA64_GR + 15: addr += LINUX_PT_R15_OFF; break;
+ case UNW_IA64_GR + 14: addr += LINUX_PT_R14_OFF; break;
+ case UNW_IA64_GR + 2: addr += LINUX_PT_R2_OFF; break;
+ case UNW_IA64_GR + 3: addr += LINUX_PT_R3_OFF; break;
+
+ case UNW_IA64_GR + 16 ... UNW_IA64_GR + 31:
+ addr += LINUX_PT_R16_OFF + 8 * (reg - (UNW_IA64_GR + 16));
+ break;
+
+ case UNW_IA64_AR_CCV: addr += LINUX_PT_CCV_OFF; break;
+
+ case UNW_IA64_FR + 6 ... UNW_IA64_FR + 11:
+ addr += LINUX_PT_F6_OFF + 16 * (reg - (UNW_IA64_FR + 6));
+ return IA64_LOC_ADDR (addr, IA64_LOC_TYPE_FP);
+
+ default:
+ if (unw_is_fpreg (reg))
+ return IA64_FPREG_LOC (c, reg);
+ else
+ return IA64_REG_LOC (c, reg);
+ }
+ }
+ else if (ia64_get_abi_marker (c) == ABI_MARKER_OLD_LINUX_INTERRUPT)
+ {
+ switch (reg)
+ {
+ case UNW_IA64_GR + 1:
+ /* The saved r1 value is valid only in the frame in which
+ it was saved; for everything else we need to look up
+ the appropriate gp value. */
+ if (c->sigcontext_addr != c->sp + 0x10)
+ return IA64_NULL_LOC;
+ addr += LINUX_OLD_PT_R1_OFF;
+ break;
+
+ case UNW_IA64_GR + 2 ... UNW_IA64_GR + 3:
+ addr += LINUX_OLD_PT_R2_OFF + 8 * (reg - (UNW_IA64_GR + 2));
+ break;
+
+ case UNW_IA64_GR + 8 ... UNW_IA64_GR + 11:
+ addr += LINUX_OLD_PT_R8_OFF + 8 * (reg - (UNW_IA64_GR + 8));
+ break;
+
+ case UNW_IA64_GR + 16 ... UNW_IA64_GR + 31:
+ addr += LINUX_OLD_PT_R16_OFF + 8 * (reg - (UNW_IA64_GR + 16));
+ break;
+
+ case UNW_IA64_FR + 6 ... UNW_IA64_FR + 9:
+ addr += LINUX_OLD_PT_F6_OFF + 16 * (reg - (UNW_IA64_FR + 6));
+ return IA64_LOC_ADDR (addr, IA64_LOC_TYPE_FP);
+
+ case UNW_IA64_BR + 0: addr += LINUX_OLD_PT_B0_OFF; break;
+ case UNW_IA64_BR + 6: addr += LINUX_OLD_PT_B6_OFF; break;
+ case UNW_IA64_BR + 7: addr += LINUX_OLD_PT_B7_OFF; break;
+
+ case UNW_IA64_AR_RSC: addr += LINUX_OLD_PT_RSC_OFF; break;
+ case UNW_IA64_AR_CCV: addr += LINUX_OLD_PT_CCV_OFF; break;
+
+ default:
+ if (unw_is_fpreg (reg))
+ return IA64_FPREG_LOC (c, reg);
+ else
+ return IA64_REG_LOC (c, reg);
+ }
+ }
+ if (is_nat)
+ {
+ /* For Linux pt-regs structure, bit number is determined by
+ the UNaT slot number (as determined by st8.spill) and the
+ bits are saved wherever the (primary) UNaT was saved. */
+ *nat_bitnr = ia64_unat_slot_num (addr);
+ return c->loc[IA64_REG_PRI_UNAT_MEM];
+ }
+ return IA64_LOC_ADDR (addr, 0);
+ }
+#endif
+ return IA64_NULL_LOC;
+}
+
+static inline ia64_loc_t
+hpux_scratch_loc (struct cursor *c, unw_regnum_t reg, uint8_t *nat_bitnr)
+{
+#if !defined(UNW_LOCAL_ONLY) || defined(__hpux)
+ return IA64_LOC_UC_REG (reg, c->sigcontext_addr);
+#else
+ return IA64_NULL_LOC;
+#endif
+}
+
+HIDDEN ia64_loc_t
+ia64_scratch_loc (struct cursor *c, unw_regnum_t reg, uint8_t *nat_bitnr)
+{
+ if (c->sigcontext_addr)
+ {
+ if (ia64_get_abi (c) == ABI_LINUX)
+ return linux_scratch_loc (c, reg, nat_bitnr);
+ else if (ia64_get_abi (c) == ABI_HPUX)
+ return hpux_scratch_loc (c, reg, nat_bitnr);
+ else
+ return IA64_NULL_LOC;
+ }
+ else
+ return IA64_REG_LOC (c, reg);
+}
+
+static inline int
+update_nat (struct cursor *c, ia64_loc_t nat_loc, unw_word_t mask,
+ unw_word_t *valp, int write)
+{
+ unw_word_t nat_word;
+ int ret;
+
+ ret = ia64_get (c, nat_loc, &nat_word);
+ if (ret < 0)
+ return ret;
+
+ if (write)
+ {
+ if (*valp)
+ nat_word |= mask;
+ else
+ nat_word &= ~mask;
+ ret = ia64_put (c, nat_loc, nat_word);
+ }
+ else
+ *valp = (nat_word & mask) != 0;
+ return ret;
+}
+
+static int
+access_nat (struct cursor *c,
+ ia64_loc_t nat_loc, ia64_loc_t reg_loc, uint8_t nat_bitnr,
+ unw_word_t *valp, int write)
+{
+ unw_word_t mask = 0;
+ unw_fpreg_t tmp;
+ int ret;
+
+ if (IA64_IS_FP_LOC (reg_loc))
+ {
+ /* NaT bit is saved as a NaTVal. This happens when a general
+ register is saved to a floating-point register. */
+ if (write)
+ {
+ if (*valp)
+ {
+ if (ia64_is_big_endian (c))
+ ret = ia64_putfp (c, reg_loc, unw.nat_val_be);
+ else
+ ret = ia64_putfp (c, reg_loc, unw.nat_val_le);
+ }
+ else
+ {
+ unw_word_t *src, *dst;
+ unw_fpreg_t tmp;
+
+ ret = ia64_getfp (c, reg_loc, &tmp);
+ if (ret < 0)
+ return ret;
+
+ /* Reset the exponent to 0x1003e so that the significand
+ will be interpreted as an integer value. */
+ src = (unw_word_t *) &unw.int_val_be;
+ dst = (unw_word_t *) &tmp;
+ if (!ia64_is_big_endian (c))
+ ++src, ++dst;
+ *dst = *src;
+
+ ret = ia64_putfp (c, reg_loc, tmp);
+ }
+ }
+ else
+ {
+ ret = ia64_getfp (c, reg_loc, &tmp);
+ if (ret < 0)
+ return ret;
+
+ if (ia64_is_big_endian (c))
+ *valp = (memcmp (&tmp, &unw.nat_val_be, sizeof (tmp)) == 0);
+ else
+ *valp = (memcmp (&tmp, &unw.nat_val_le, sizeof (tmp)) == 0);
+ }
+ return ret;
+ }
+
+ if ((IA64_IS_REG_LOC (nat_loc)
+ && (unsigned) (IA64_GET_REG (nat_loc) - UNW_IA64_NAT) < 128)
+ || IA64_IS_UC_LOC (reg_loc))
+ {
+ if (write)
+ return ia64_put (c, nat_loc, *valp);
+ else
+ return ia64_get (c, nat_loc, valp);
+ }
+
+ if (IA64_IS_NULL_LOC (nat_loc))
+ {
+ /* NaT bit is not saved. This happens if a general register is
+ saved to a branch register. Since the NaT bit gets lost, we
+ need to drop it here, too. Note that if the NaT bit had been
+ set when the save occurred, it would have caused a NaT
+ consumption fault. */
+ if (write)
+ {
+ if (*valp)
+ return -UNW_EBADREG; /* can't set NaT bit */
+ }
+ else
+ *valp = 0;
+ return 0;
+ }
+
+ mask = (unw_word_t) 1 << nat_bitnr;
+ return update_nat (c, nat_loc, mask, valp, write);
+}
+
+HIDDEN int
+tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
+ int write)
+{
+ ia64_loc_t loc, reg_loc, nat_loc;
+ unw_word_t mask, val;
+ uint8_t nat_bitnr;
+ int ret;
+
+ switch (reg)
+ {
+ /* frame registers: */
+
+ case UNW_IA64_BSP:
+ if (write)
+ c->bsp = *valp;
+ else
+ *valp = c->bsp;
+ return 0;
+
+ case UNW_REG_SP:
+ if (write)
+ c->sp = *valp;
+ else
+ *valp = c->sp;
+ return 0;
+
+ case UNW_REG_IP:
+ if (write)
+ {
+ c->ip = *valp; /* also update the IP cache */
+ if (c->pi_valid && (*valp < c->pi.start_ip || *valp >= c->pi.end_ip))
+ c->pi_valid = 0; /* new IP outside of current proc */
+ }
+ loc = c->loc[IA64_REG_IP];
+ break;
+
+ /* preserved registers: */
+
+ case UNW_IA64_GR + 4 ... UNW_IA64_GR + 7:
+ loc = c->loc[IA64_REG_R4 + (reg - (UNW_IA64_GR + 4))];
+ break;
+
+ case UNW_IA64_NAT + 4 ... UNW_IA64_NAT + 7:
+ loc = c->loc[IA64_REG_NAT4 + (reg - (UNW_IA64_NAT + 4))];
+ reg_loc = c->loc[IA64_REG_R4 + (reg - (UNW_IA64_NAT + 4))];
+ nat_bitnr = c->nat_bitnr[reg - (UNW_IA64_NAT + 4)];
+ return access_nat (c, loc, reg_loc, nat_bitnr, valp, write);
+
+ case UNW_IA64_AR_BSP: loc = c->loc[IA64_REG_BSP]; break;
+ case UNW_IA64_AR_BSPSTORE: loc = c->loc[IA64_REG_BSPSTORE]; break;
+ case UNW_IA64_AR_PFS: loc = c->loc[IA64_REG_PFS]; break;
+ case UNW_IA64_AR_RNAT: loc = c->loc[IA64_REG_RNAT]; break;
+ case UNW_IA64_AR_UNAT: loc = c->loc[IA64_REG_UNAT]; break;
+ case UNW_IA64_AR_LC: loc = c->loc[IA64_REG_LC]; break;
+ case UNW_IA64_AR_FPSR: loc = c->loc[IA64_REG_FPSR]; break;
+ case UNW_IA64_BR + 1: loc = c->loc[IA64_REG_B1]; break;
+ case UNW_IA64_BR + 2: loc = c->loc[IA64_REG_B2]; break;
+ case UNW_IA64_BR + 3: loc = c->loc[IA64_REG_B3]; break;
+ case UNW_IA64_BR + 4: loc = c->loc[IA64_REG_B4]; break;
+ case UNW_IA64_BR + 5: loc = c->loc[IA64_REG_B5]; break;
+
+ case UNW_IA64_CFM:
+ if (write)
+ c->cfm = *valp; /* also update the CFM cache */
+ loc = c->cfm_loc;
+ break;
+
+ case UNW_IA64_PR:
+ /*
+ * Note: broad-side access to the predicates is NOT rotated
+ * (i.e., it is done as if CFM.rrb.pr == 0.
+ */
+ if (write)
+ {
+ c->pr = *valp; /* update the predicate cache */
+ return ia64_put (c, c->loc[IA64_REG_PR], *valp);
+ }
+ else
+ return ia64_get (c, c->loc[IA64_REG_PR], valp);
+
+ case UNW_IA64_GR + 32 ... UNW_IA64_GR + 127: /* stacked reg */
+ reg = rotate_gr (c, reg - UNW_IA64_GR);
+ if (reg < 0)
+ return -UNW_EBADREG;
+ ret = ia64_get_stacked (c, reg, &loc, NULL);
+ if (ret < 0)
+ return ret;
+ break;
+
+ case UNW_IA64_NAT + 32 ... UNW_IA64_NAT + 127: /* stacked reg */
+ reg = rotate_gr (c, reg - UNW_IA64_NAT);
+ if (reg < 0)
+ return -UNW_EBADREG;
+ ret = ia64_get_stacked (c, reg, &loc, &nat_loc);
+ if (ret < 0)
+ return ret;
+ assert (!IA64_IS_REG_LOC (loc));
+ mask = (unw_word_t) 1 << rse_slot_num (IA64_GET_ADDR (loc));
+ return update_nat (c, nat_loc, mask, valp, write);
+
+ case UNW_IA64_AR_EC:
+ if ((ret = ia64_get (c, c->ec_loc, &val)) < 0)
+ return ret;
+
+ if (write)
+ {
+ val = ((val & ~((unw_word_t) 0x3f << 52)) | ((*valp & 0x3f) << 52));
+ return ia64_put (c, c->ec_loc, val);
+ }
+ else
+ {
+ *valp = (val >> 52) & 0x3f;
+ return 0;
+ }
+
+ /* scratch & special registers: */
+
+ case UNW_IA64_GR + 0:
+ if (write)
+ return -UNW_EREADONLYREG;
+ *valp = 0;
+ return 0;
+
+ case UNW_IA64_NAT + 0:
+ if (write)
+ return -UNW_EREADONLYREG;
+ *valp = 0;
+ return 0;
+
+ case UNW_IA64_NAT + 1:
+ case UNW_IA64_NAT + 2 ... UNW_IA64_NAT + 3:
+ case UNW_IA64_NAT + 8 ... UNW_IA64_NAT + 31:
+ loc = ia64_scratch_loc (c, reg, &nat_bitnr);
+ if (IA64_IS_NULL_LOC (loc) && reg == UNW_IA64_NAT + 1)
+ {
+ /* access to GP */
+ if (write)
+ return -UNW_EREADONLYREG;
+ *valp = 0;
+ return 0;
+ }
+ if (!(IA64_IS_REG_LOC (loc) || IA64_IS_UC_LOC (loc)
+ || IA64_IS_FP_LOC (loc)))
+ /* We're dealing with a NaT bit stored in memory. */
+ return update_nat(c, loc, (unw_word_t) 1 << nat_bitnr, valp, write);
+ break;
+
+ case UNW_IA64_GR + 15 ... UNW_IA64_GR + 18:
+ mask = 1 << (reg - (UNW_IA64_GR + 15));
+ if (write)
+ {
+ c->eh_args[reg - (UNW_IA64_GR + 15)] = *valp;
+ c->eh_valid_mask |= mask;
+ return 0;
+ }
+ else if ((c->eh_valid_mask & mask) != 0)
+ {
+ *valp = c->eh_args[reg - (UNW_IA64_GR + 15)];
+ return 0;
+ }
+ else
+ loc = ia64_scratch_loc (c, reg, NULL);
+ break;
+
+ case UNW_IA64_GR + 1: /* global pointer */
+ case UNW_IA64_GR + 2 ... UNW_IA64_GR + 3:
+ case UNW_IA64_GR + 8 ... UNW_IA64_GR + 14:
+ case UNW_IA64_GR + 19 ... UNW_IA64_GR + 31:
+ case UNW_IA64_BR + 0:
+ case UNW_IA64_BR + 6:
+ case UNW_IA64_BR + 7:
+ case UNW_IA64_AR_RSC:
+ case UNW_IA64_AR_CSD:
+ case UNW_IA64_AR_SSD:
+ case UNW_IA64_AR_CCV:
+ loc = ia64_scratch_loc (c, reg, NULL);
+ if (IA64_IS_NULL_LOC (loc) && reg == UNW_IA64_GR + 1)
+ {
+ /* access to GP */
+ if (write)
+ return -UNW_EREADONLYREG;
+
+ /* ensure c->pi is up-to-date: */
+ if ((ret = ia64_make_proc_info (c)) < 0)
+ return ret;
+ *valp = c->pi.gp;
+ return 0;
+ }
+ break;
+
+ default:
+ Debug (1, "bad register number %d\n", reg);
+ return -UNW_EBADREG;
+ }
+
+ if (write)
+ return ia64_put (c, loc, *valp);
+ else
+ return ia64_get (c, loc, valp);
+}
+
+HIDDEN int
+tdep_access_fpreg (struct cursor *c, int reg, unw_fpreg_t *valp,
+ int write)
+{
+ ia64_loc_t loc;
+
+ switch (reg)
+ {
+ case UNW_IA64_FR + 0:
+ if (write)
+ return -UNW_EREADONLYREG;
+ *valp = unw.read_only.f0;
+ return 0;
+
+ case UNW_IA64_FR + 1:
+ if (write)
+ return -UNW_EREADONLYREG;
+
+ if (ia64_is_big_endian (c))
+ *valp = unw.read_only.f1_be;
+ else
+ *valp = unw.read_only.f1_le;
+ return 0;
+
+ case UNW_IA64_FR + 2: loc = c->loc[IA64_REG_F2]; break;
+ case UNW_IA64_FR + 3: loc = c->loc[IA64_REG_F3]; break;
+ case UNW_IA64_FR + 4: loc = c->loc[IA64_REG_F4]; break;
+ case UNW_IA64_FR + 5: loc = c->loc[IA64_REG_F5]; break;
+
+ case UNW_IA64_FR + 16 ... UNW_IA64_FR + 31:
+ loc = c->loc[IA64_REG_F16 + (reg - (UNW_IA64_FR + 16))];
+ break;
+
+ case UNW_IA64_FR + 6 ... UNW_IA64_FR + 15:
+ loc = ia64_scratch_loc (c, reg, NULL);
+ break;
+
+ case UNW_IA64_FR + 32 ... UNW_IA64_FR + 127:
+ reg = rotate_fr (c, reg - UNW_IA64_FR) + UNW_IA64_FR;
+ loc = ia64_scratch_loc (c, reg, NULL);
+ break;
+
+ default:
+ Debug (1, "bad register number %d\n", reg);
+ return -UNW_EBADREG;
+ }
+
+ if (write)
+ return ia64_putfp (c, loc, *valp);
+ else
+ return ia64_getfp (c, loc, valp);
+}
diff --git a/src/pal/src/libunwind/src/ia64/Gresume.c b/src/pal/src/libunwind/src/ia64/Gresume.c
new file mode 100644
index 0000000000..68fe8a659e
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Gresume.c
@@ -0,0 +1,274 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+
+#include "unwind_i.h"
+#include "offsets.h"
+
+#ifndef UNW_REMOTE_ONLY
+
+static inline int
+local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
+{
+#if defined(__linux)
+ unw_word_t dirty_partition[2048]; /* AR.RSC.LOADRS is a 14-bit field */
+ unw_word_t val, sol, sof, pri_unat, n, pfs, bspstore, dirty_rnat;
+ struct cursor *c = (struct cursor *) cursor;
+ struct
+ {
+ unw_word_t r1;
+ unw_word_t r4;
+ unw_word_t r5;
+ unw_word_t r6;
+ unw_word_t r7;
+ unw_word_t r15;
+ unw_word_t r16;
+ unw_word_t r17;
+ unw_word_t r18;
+ }
+ extra;
+ int ret, dirty_size;
+# define GET_NAT(n) \
+ do \
+ { \
+ ret = tdep_access_reg (c, UNW_IA64_NAT + (n), &val, 0); \
+ if (ret < 0) \
+ return ret; \
+ if (val) \
+ pri_unat |= (unw_word_t) 1 << n; \
+ } \
+ while (0)
+
+ /* ensure c->pi is up-to-date: */
+ if ((ret = ia64_make_proc_info (c)) < 0)
+ return ret;
+
+ /* Copy contents of r4-r7 into "extra", so that their values end up
+ contiguous, so we can use a single (primary-) UNaT value. */
+ if ((ret = ia64_get (c, c->loc[IA64_REG_R4], &extra.r4)) < 0
+ || (ret = ia64_get (c, c->loc[IA64_REG_R5], &extra.r5)) < 0
+ || (ret = ia64_get (c, c->loc[IA64_REG_R6], &extra.r6)) < 0
+ || (ret = ia64_get (c, c->loc[IA64_REG_R7], &extra.r7)) < 0)
+ return ret;
+
+ /* Form the primary UNaT value: */
+ pri_unat = 0;
+ GET_NAT (4); GET_NAT(5);
+ GET_NAT (6); GET_NAT(7);
+ n = (((uintptr_t) &extra.r4) / 8 - 4) % 64;
+ pri_unat = (pri_unat << n) | (pri_unat >> (64 - n));
+
+ if (unlikely (c->sigcontext_addr))
+ {
+ struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
+# define PR_SCRATCH 0xffc0 /* p6-p15 are scratch */
+# define PR_PRESERVED (~(PR_SCRATCH | 1))
+
+ /* We're returning to a frame that was (either directly or
+ indirectly) interrupted by a signal. We have to restore
+ _both_ "preserved" and "scratch" registers. That doesn't
+ leave us any registers to work with, and the only way we can
+ achieve this is by doing a sigreturn().
+
+ Note: it might be tempting to think that we don't have to
+ restore the scratch registers when returning to a frame that
+ was indirectly interrupted by a signal. However, that is not
+ safe because that frame and its descendants could have been
+ using a special convention that stores "preserved" state in
+ scratch registers. For example, the Linux fsyscall
+ convention does this with r11 (to save ar.pfs) and b6 (to
+ save "rp"). */
+
+ sc->sc_gr[12] = c->psp;
+ c->psp = c->sigcontext_addr - c->sigcontext_off;
+
+ sof = (c->cfm & 0x7f);
+ if ((dirty_size = rbs_cover_and_flush (c, sof, dirty_partition,
+ &dirty_rnat, &bspstore)) < 0)
+ return dirty_size;
+
+ /* Clear the "in-syscall" flag, because in general we won't be
+ returning to the interruption-point and we need all registers
+ restored. */
+ sc->sc_flags &= ~IA64_SC_FLAG_IN_SYSCALL;
+ sc->sc_ip = c->ip;
+ sc->sc_cfm = c->cfm & (((unw_word_t) 1 << 38) - 1);
+ sc->sc_pr = (c->pr & ~PR_SCRATCH) | (sc->sc_pr & ~PR_PRESERVED);
+ if ((ret = ia64_get (c, c->loc[IA64_REG_PFS], &sc->sc_ar_pfs)) < 0
+ || (ret = ia64_get (c, c->loc[IA64_REG_FPSR], &sc->sc_ar_fpsr)) < 0
+ || (ret = ia64_get (c, c->loc[IA64_REG_UNAT], &sc->sc_ar_unat)) < 0)
+ return ret;
+
+ sc->sc_gr[1] = c->pi.gp;
+ if (c->eh_valid_mask & 0x1) sc->sc_gr[15] = c->eh_args[0];
+ if (c->eh_valid_mask & 0x2) sc->sc_gr[16] = c->eh_args[1];
+ if (c->eh_valid_mask & 0x4) sc->sc_gr[17] = c->eh_args[2];
+ if (c->eh_valid_mask & 0x8) sc->sc_gr[18] = c->eh_args[3];
+ Debug (9, "sc: r15=%lx,r16=%lx,r17=%lx,r18=%lx\n",
+ (long) sc->sc_gr[15], (long) sc->sc_gr[16],
+ (long) sc->sc_gr[17], (long) sc->sc_gr[18]);
+ }
+ else
+ {
+ /* Account for the fact that _Uia64_install_context() will
+ return via br.ret, which will decrement bsp by size-of-locals. */
+ if ((ret = ia64_get (c, c->loc[IA64_REG_PFS], &pfs)) < 0)
+ return ret;
+ sol = (pfs >> 7) & 0x7f;
+ if ((dirty_size = rbs_cover_and_flush (c, sol, dirty_partition,
+ &dirty_rnat, &bspstore)) < 0)
+ return dirty_size;
+
+ extra.r1 = c->pi.gp;
+ extra.r15 = c->eh_args[0];
+ extra.r16 = c->eh_args[1];
+ extra.r17 = c->eh_args[2];
+ extra.r18 = c->eh_args[3];
+ Debug (9, "extra: r15=%lx,r16=%lx,r17=%lx,r18=%lx\n",
+ (long) extra.r15, (long) extra.r16,
+ (long) extra.r17, (long) extra.r18);
+ }
+ Debug (8, "resuming at ip=%lx\n", (long) c->ip);
+ ia64_install_cursor (c, pri_unat, (unw_word_t *) &extra,
+ bspstore, dirty_size, dirty_partition + dirty_size/8,
+ dirty_rnat);
+#elif defined(__hpux)
+ struct cursor *c = (struct cursor *) cursor;
+
+ setcontext (c->as_arg); /* should not return */
+#endif
+ return -UNW_EINVAL;
+}
+
+HIDDEN int
+ia64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
+{
+ return local_resume (as, cursor, arg);
+}
+
+#endif /* !UNW_REMOTE_ONLY */
+
+#ifndef UNW_LOCAL_ONLY
+
+static inline int
+remote_install_cursor (struct cursor *c)
+{
+ int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *,
+ int write, void *);
+ int (*access_fpreg) (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *,
+ int write, void *);
+ unw_fpreg_t fpval;
+ unw_word_t val;
+ int reg;
+
+#if defined(__linux) && !defined(UNW_REMOTE_ONLY)
+ if (c->as == unw_local_addr_space)
+ {
+ /* Take a short-cut: we directly resume out of the cursor and
+ all we need to do is make sure that all locations point to
+ memory, not registers. Furthermore, R4-R7 and NAT4-NAT7 are
+ taken care of by ia64_local_resume() so they don't need to be
+ handled here. */
+# define MEMIFY(preg, reg) \
+ do { \
+ if (IA64_IS_REG_LOC (c->loc[(preg)])) \
+ c->loc[(preg)] = IA64_LOC_ADDR ((unw_word_t) \
+ tdep_uc_addr(c->as_arg, (reg), \
+ NULL), 0); \
+ } while (0)
+ MEMIFY (IA64_REG_PR, UNW_IA64_PR);
+ MEMIFY (IA64_REG_PFS, UNW_IA64_AR_PFS);
+ MEMIFY (IA64_REG_RNAT, UNW_IA64_AR_RNAT);
+ MEMIFY (IA64_REG_UNAT, UNW_IA64_AR_UNAT);
+ MEMIFY (IA64_REG_LC, UNW_IA64_AR_LC);
+ MEMIFY (IA64_REG_FPSR, UNW_IA64_AR_FPSR);
+ MEMIFY (IA64_REG_IP, UNW_IA64_BR + 0);
+ MEMIFY (IA64_REG_B1, UNW_IA64_BR + 1);
+ MEMIFY (IA64_REG_B2, UNW_IA64_BR + 2);
+ MEMIFY (IA64_REG_B3, UNW_IA64_BR + 3);
+ MEMIFY (IA64_REG_B4, UNW_IA64_BR + 4);
+ MEMIFY (IA64_REG_B5, UNW_IA64_BR + 5);
+ MEMIFY (IA64_REG_F2, UNW_IA64_FR + 2);
+ MEMIFY (IA64_REG_F3, UNW_IA64_FR + 3);
+ MEMIFY (IA64_REG_F4, UNW_IA64_FR + 4);
+ MEMIFY (IA64_REG_F5, UNW_IA64_FR + 5);
+ MEMIFY (IA64_REG_F16, UNW_IA64_FR + 16);
+ MEMIFY (IA64_REG_F17, UNW_IA64_FR + 17);
+ MEMIFY (IA64_REG_F18, UNW_IA64_FR + 18);
+ MEMIFY (IA64_REG_F19, UNW_IA64_FR + 19);
+ MEMIFY (IA64_REG_F20, UNW_IA64_FR + 20);
+ MEMIFY (IA64_REG_F21, UNW_IA64_FR + 21);
+ MEMIFY (IA64_REG_F22, UNW_IA64_FR + 22);
+ MEMIFY (IA64_REG_F23, UNW_IA64_FR + 23);
+ MEMIFY (IA64_REG_F24, UNW_IA64_FR + 24);
+ MEMIFY (IA64_REG_F25, UNW_IA64_FR + 25);
+ MEMIFY (IA64_REG_F26, UNW_IA64_FR + 26);
+ MEMIFY (IA64_REG_F27, UNW_IA64_FR + 27);
+ MEMIFY (IA64_REG_F28, UNW_IA64_FR + 28);
+ MEMIFY (IA64_REG_F29, UNW_IA64_FR + 29);
+ MEMIFY (IA64_REG_F30, UNW_IA64_FR + 30);
+ MEMIFY (IA64_REG_F31, UNW_IA64_FR + 31);
+ }
+ else
+#endif /* __linux && !UNW_REMOTE_ONLY */
+ {
+ access_reg = c->as->acc.access_reg;
+ access_fpreg = c->as->acc.access_fpreg;
+
+ Debug (8, "copying out cursor state\n");
+
+ for (reg = 0; reg <= UNW_REG_LAST; ++reg)
+ {
+ if (unw_is_fpreg (reg))
+ {
+ if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0)
+ (*access_fpreg) (c->as, reg, &fpval, 1, c->as_arg);
+ }
+ else
+ {
+ if (tdep_access_reg (c, reg, &val, 0) >= 0)
+ (*access_reg) (c->as, reg, &val, 1, c->as_arg);
+ }
+ }
+ }
+ return (*c->as->acc.resume) (c->as, (unw_cursor_t *) c, c->as_arg);
+}
+
+#endif /* !UNW_LOCAL_ONLY */
+
+int
+unw_resume (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ Debug (1, "(cursor=%p, ip=0x%016lx)\n", c, (unsigned long) c->ip);
+
+#ifdef UNW_LOCAL_ONLY
+ return local_resume (c->as, cursor, c->as_arg);
+#else
+ return remote_install_cursor (c);
+#endif
+}
diff --git a/src/pal/src/libunwind/src/ia64/Gscript.c b/src/pal/src/libunwind/src/ia64/Gscript.c
new file mode 100644
index 0000000000..526aeaf299
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Gscript.c
@@ -0,0 +1,765 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "offsets.h"
+#include "regs.h"
+#include "unwind_i.h"
+
+enum ia64_script_insn_opcode
+ {
+ IA64_INSN_INC_PSP, /* psp += val */
+ IA64_INSN_LOAD_PSP, /* psp = *psp_loc */
+ IA64_INSN_ADD_PSP, /* s[dst] = (s.psp + val) */
+ IA64_INSN_ADD_PSP_NAT, /* like above, but with NaT info */
+ IA64_INSN_ADD_SP, /* s[dst] = (s.sp + val) */
+ IA64_INSN_ADD_SP_NAT, /* like above, but with NaT info */
+ IA64_INSN_MOVE, /* s[dst] = s[val] */
+ IA64_INSN_MOVE_NAT, /* like above, but with NaT info */
+ IA64_INSN_MOVE_NO_NAT, /* like above, but clear NaT info */
+ IA64_INSN_MOVE_STACKED, /* s[dst] = rse_skip(*s.bsp_loc, val) */
+ IA64_INSN_MOVE_STACKED_NAT, /* like above, but with NaT info */
+ IA64_INSN_MOVE_SCRATCH, /* s[dst] = scratch reg "val" */
+ IA64_INSN_MOVE_SCRATCH_NAT, /* like above, but with NaT info */
+ IA64_INSN_MOVE_SCRATCH_NO_NAT /* like above, but clear NaT info */
+ };
+
+#if defined(HAVE___THREAD) && HAVE___THREAD
+static __thread struct ia64_script_cache ia64_per_thread_cache =
+ {
+#ifdef HAVE_ATOMIC_OPS_H
+ .busy = AO_TS_INITIALIZER
+#else
+ .lock = PTHREAD_MUTEX_INITIALIZER
+#endif
+ };
+#endif
+
+static inline unw_hash_index_t CONST_ATTR
+hash (unw_word_t ip)
+{
+ /* based on (sqrt(5)/2-1)*2^64 */
+# define magic ((unw_word_t) 0x9e3779b97f4a7c16ULL)
+
+ return (ip >> 4) * magic >> (64 - IA64_LOG_UNW_HASH_SIZE);
+}
+
+static inline long
+cache_match (struct ia64_script *script, unw_word_t ip, unw_word_t pr)
+{
+ if (ip == script->ip && ((pr ^ script->pr_val) & script->pr_mask) == 0)
+ return 1;
+ return 0;
+}
+
+static inline void
+flush_script_cache (struct ia64_script_cache *cache)
+{
+ int i;
+
+ cache->lru_head = IA64_UNW_CACHE_SIZE - 1;
+ cache->lru_tail = 0;
+
+ for (i = 0; i < IA64_UNW_CACHE_SIZE; ++i)
+ {
+ if (i > 0)
+ cache->buckets[i].lru_chain = (i - 1);
+ cache->buckets[i].coll_chain = -1;
+ cache->buckets[i].ip = 0;
+ }
+ for (i = 0; i<IA64_UNW_HASH_SIZE; ++i)
+ cache->hash[i] = -1;
+}
+
+static inline struct ia64_script_cache *
+get_script_cache (unw_addr_space_t as, intrmask_t *saved_maskp)
+{
+ struct ia64_script_cache *cache = &as->global_cache;
+ unw_caching_policy_t caching = as->caching_policy;
+
+ if (caching == UNW_CACHE_NONE)
+ return NULL;
+
+#ifdef HAVE_ATOMIC_H
+ if (!spin_trylock_irqsave (&cache->busy, *saved_maskp))
+ return NULL;
+#else
+# if defined(HAVE___THREAD) && HAVE___THREAD
+ if (as->caching_policy == UNW_CACHE_PER_THREAD)
+ cache = &ia64_per_thread_cache;
+# endif
+# ifdef HAVE_ATOMIC_OPS_H
+ if (AO_test_and_set (&cache->busy) == AO_TS_SET)
+ return NULL;
+# else
+ if (likely (caching == UNW_CACHE_GLOBAL))
+ {
+ Debug (16, "acquiring lock\n");
+ lock_acquire (&cache->lock, *saved_maskp);
+ }
+# endif
+#endif
+
+ if (atomic_read (&as->cache_generation) != atomic_read (&cache->generation))
+ {
+ flush_script_cache (cache);
+ cache->generation = as->cache_generation;
+ }
+ return cache;
+}
+
+static inline void
+put_script_cache (unw_addr_space_t as, struct ia64_script_cache *cache,
+ intrmask_t *saved_maskp)
+{
+ assert (as->caching_policy != UNW_CACHE_NONE);
+
+ Debug (16, "unmasking signals/interrupts and releasing lock\n");
+#ifdef HAVE_ATOMIC_H
+ spin_unlock_irqrestore (&cache->busy, *saved_maskp);
+#else
+# ifdef HAVE_ATOMIC_OPS_H
+ AO_CLEAR (&cache->busy);
+# else
+ if (likely (as->caching_policy == UNW_CACHE_GLOBAL))
+ lock_release (&cache->lock, *saved_maskp);
+# endif
+#endif
+}
+
+static struct ia64_script *
+script_lookup (struct ia64_script_cache *cache, struct cursor *c)
+{
+ struct ia64_script *script = cache->buckets + c->hint;
+ unsigned short index;
+ unw_word_t ip, pr;
+
+ ip = c->ip;
+ pr = c->pr;
+
+ if (cache_match (script, ip, pr))
+ return script;
+
+ index = cache->hash[hash (ip)];
+ if (index >= IA64_UNW_CACHE_SIZE)
+ return 0;
+
+ script = cache->buckets + index;
+ while (1)
+ {
+ if (cache_match (script, ip, pr))
+ {
+ /* update hint; no locking needed: single-word writes are atomic */
+ c->hint = cache->buckets[c->prev_script].hint =
+ (script - cache->buckets);
+ return script;
+ }
+ if (script->coll_chain >= IA64_UNW_HASH_SIZE)
+ return 0;
+ script = cache->buckets + script->coll_chain;
+ }
+}
+
+static inline void
+script_init (struct ia64_script *script, unw_word_t ip)
+{
+ script->ip = ip;
+ script->hint = 0;
+ script->count = 0;
+ script->abi_marker = 0;
+}
+
+static inline struct ia64_script *
+script_new (struct ia64_script_cache *cache, unw_word_t ip)
+{
+ struct ia64_script *script, *prev, *tmp;
+ unw_hash_index_t index;
+ unsigned short head;
+
+ head = cache->lru_head;
+ script = cache->buckets + head;
+ cache->lru_head = script->lru_chain;
+
+ /* re-insert script at the tail of the LRU chain: */
+ cache->buckets[cache->lru_tail].lru_chain = head;
+ cache->lru_tail = head;
+
+ /* remove the old script from the hash table (if it's there): */
+ if (script->ip)
+ {
+ index = hash (script->ip);
+ tmp = cache->buckets + cache->hash[index];
+ prev = 0;
+ while (1)
+ {
+ if (tmp == script)
+ {
+ if (prev)
+ prev->coll_chain = tmp->coll_chain;
+ else
+ cache->hash[index] = tmp->coll_chain;
+ break;
+ }
+ else
+ prev = tmp;
+ if (tmp->coll_chain >= IA64_UNW_CACHE_SIZE)
+ /* old script wasn't in the hash-table */
+ break;
+ tmp = cache->buckets + tmp->coll_chain;
+ }
+ }
+
+ /* enter new script in the hash table */
+ index = hash (ip);
+ script->coll_chain = cache->hash[index];
+ cache->hash[index] = script - cache->buckets;
+
+ script_init (script, ip);
+ return script;
+}
+
+static inline void
+script_finalize (struct ia64_script *script, struct cursor *c,
+ struct ia64_state_record *sr)
+{
+ script->pr_mask = sr->pr_mask;
+ script->pr_val = sr->pr_val;
+ script->pi = c->pi;
+}
+
+static inline void
+script_emit (struct ia64_script *script, struct ia64_script_insn insn)
+{
+ if (script->count >= IA64_MAX_SCRIPT_LEN)
+ {
+ Dprintf ("%s: script exceeds maximum size of %u instructions!\n",
+ __FUNCTION__, IA64_MAX_SCRIPT_LEN);
+ return;
+ }
+ script->insn[script->count++] = insn;
+}
+
+static void
+compile_reg (struct ia64_state_record *sr, int i, struct ia64_reg_info *r,
+ struct ia64_script *script)
+{
+ enum ia64_script_insn_opcode opc;
+ unsigned long val, rval;
+ struct ia64_script_insn insn;
+ long is_preserved_gr;
+
+ if (r->where == IA64_WHERE_NONE || r->when >= sr->when_target)
+ return;
+
+ opc = IA64_INSN_MOVE;
+ val = rval = r->val;
+ is_preserved_gr = (i >= IA64_REG_R4 && i <= IA64_REG_R7);
+
+ if (r->where == IA64_WHERE_GR)
+ {
+ /* Handle most common case first... */
+ if (rval >= 32)
+ {
+ /* register got spilled to a stacked register */
+ if (is_preserved_gr)
+ opc = IA64_INSN_MOVE_STACKED_NAT;
+ else
+ opc = IA64_INSN_MOVE_STACKED;
+ val = rval;
+ }
+ else if (rval >= 4 && rval <= 7)
+ {
+ /* register got spilled to a preserved register */
+ val = IA64_REG_R4 + (rval - 4);
+ if (is_preserved_gr)
+ opc = IA64_INSN_MOVE_NAT;
+ }
+ else
+ {
+ /* register got spilled to a scratch register */
+ if (is_preserved_gr)
+ opc = IA64_INSN_MOVE_SCRATCH_NAT;
+ else
+ opc = IA64_INSN_MOVE_SCRATCH;
+ val = UNW_IA64_GR + rval;
+ }
+ }
+ else
+ {
+ switch (r->where)
+ {
+ case IA64_WHERE_FR:
+ /* Note: There is no need to handle NaT-bit info here
+ (indepent of is_preserved_gr), because for floating-point
+ NaTs are represented as NaTVal, so the NaT-info never
+ needs to be consulated. */
+ if (rval >= 2 && rval <= 5)
+ val = IA64_REG_F2 + (rval - 2);
+ else if (rval >= 16 && rval <= 31)
+ val = IA64_REG_F16 + (rval - 16);
+ else
+ {
+ opc = IA64_INSN_MOVE_SCRATCH;
+ val = UNW_IA64_FR + rval;
+ }
+ break;
+
+ case IA64_WHERE_BR:
+ if (rval >= 1 && rval <= 5)
+ {
+ val = IA64_REG_B1 + (rval - 1);
+ if (is_preserved_gr)
+ opc = IA64_INSN_MOVE_NO_NAT;
+ }
+ else
+ {
+ opc = IA64_INSN_MOVE_SCRATCH;
+ if (is_preserved_gr)
+ opc = IA64_INSN_MOVE_SCRATCH_NO_NAT;
+ val = UNW_IA64_BR + rval;
+ }
+ break;
+
+ case IA64_WHERE_SPREL:
+ if (is_preserved_gr)
+ opc = IA64_INSN_ADD_SP_NAT;
+ else
+ {
+ opc = IA64_INSN_ADD_SP;
+ if (i >= IA64_REG_F2 && i <= IA64_REG_F31)
+ val |= IA64_LOC_TYPE_FP;
+ }
+ break;
+
+ case IA64_WHERE_PSPREL:
+ if (is_preserved_gr)
+ opc = IA64_INSN_ADD_PSP_NAT;
+ else
+ {
+ opc = IA64_INSN_ADD_PSP;
+ if (i >= IA64_REG_F2 && i <= IA64_REG_F31)
+ val |= IA64_LOC_TYPE_FP;
+ }
+ break;
+
+ default:
+ Dprintf ("%s: register %u has unexpected `where' value of %u\n",
+ __FUNCTION__, i, r->where);
+ break;
+ }
+ }
+ insn.opc = opc;
+ insn.dst = i;
+ insn.val = val;
+ script_emit (script, insn);
+
+ if (i == IA64_REG_PSP)
+ {
+ /* c->psp must contain the _value_ of the previous sp, not it's
+ save-location. We get this by dereferencing the value we
+ just stored in loc[IA64_REG_PSP]: */
+ insn.opc = IA64_INSN_LOAD_PSP;
+ script_emit (script, insn);
+ }
+}
+
+/* Sort the registers which got saved in decreasing order of WHEN
+ value. This is needed to ensure that the save-locations are
+ updated in the proper order. For example, suppose r4 gets spilled
+ to memory and then r5 gets saved in r4. In this case, we need to
+ update the save location of r5 before the one of r4. */
+
+static inline int
+sort_regs (struct ia64_state_record *sr, int regorder[])
+{
+ int r, i, j, max, max_reg, max_when, num_regs = 0;
+
+ assert (IA64_REG_BSP == 3);
+
+ for (r = IA64_REG_BSP; r < IA64_NUM_PREGS; ++r)
+ {
+ if (sr->curr.reg[r].where == IA64_WHERE_NONE
+ || sr->curr.reg[r].when >= sr->when_target)
+ continue;
+
+ regorder[num_regs++] = r;
+ }
+
+ /* Simple insertion-sort. Involves about N^2/2 comparisons and N
+ exchanges. N is often small (say, 2-5) so a fancier sorting
+ algorithm may not be worthwhile. */
+
+ for (i = max = 0; i < num_regs - 1; ++i)
+ {
+ max_reg = regorder[max];
+ max_when = sr->curr.reg[max_reg].when;
+
+ for (j = i + 1; j < num_regs; ++j)
+ if (sr->curr.reg[regorder[j]].when > max_when)
+ {
+ max = j;
+ max_reg = regorder[j];
+ max_when = sr->curr.reg[max_reg].when;
+ }
+ if (i != max)
+ {
+ regorder[max] = regorder[i];
+ regorder[i] = max_reg;
+ }
+ }
+ return num_regs;
+}
+
+/* Build an unwind script that unwinds from state OLD_STATE to the
+ entrypoint of the function that called OLD_STATE. */
+
+static inline int
+build_script (struct cursor *c, struct ia64_script *script)
+{
+ int num_regs, i, ret, regorder[IA64_NUM_PREGS - 3];
+ struct ia64_reg_info *pri_unat;
+ struct ia64_state_record sr;
+ struct ia64_script_insn insn;
+
+ ret = ia64_create_state_record (c, &sr);
+ if (ret < 0)
+ return ret;
+
+ /* First, compile the update for IA64_REG_PSP. This is important
+ because later save-locations may depend on it's correct (updated)
+ value. Fixed-size frames are handled specially and variable-size
+ frames get handled via the normal compile_reg(). */
+
+ if (sr.when_target > sr.curr.reg[IA64_REG_PSP].when
+ && (sr.curr.reg[IA64_REG_PSP].where == IA64_WHERE_NONE)
+ && sr.curr.reg[IA64_REG_PSP].val != 0)
+ {
+ /* new psp is psp plus frame size */
+ insn.opc = IA64_INSN_INC_PSP;
+ insn.val = sr.curr.reg[IA64_REG_PSP].val; /* frame size */
+ script_emit (script, insn);
+ }
+ else
+ compile_reg (&sr, IA64_REG_PSP, sr.curr.reg + IA64_REG_PSP, script);
+
+ /* Second, compile the update for the primary UNaT, if any: */
+
+ if (sr.when_target >= sr.curr.reg[IA64_REG_PRI_UNAT_GR].when
+ || sr.when_target >= sr.curr.reg[IA64_REG_PRI_UNAT_MEM].when)
+ {
+ if (sr.when_target < sr.curr.reg[IA64_REG_PRI_UNAT_GR].when)
+ /* (primary) NaT bits were saved to memory only */
+ pri_unat = sr.curr.reg + IA64_REG_PRI_UNAT_MEM;
+ else if (sr.when_target < sr.curr.reg[IA64_REG_PRI_UNAT_MEM].when)
+ /* (primary) NaT bits were saved to a register only */
+ pri_unat = sr.curr.reg + IA64_REG_PRI_UNAT_GR;
+ else if (sr.curr.reg[IA64_REG_PRI_UNAT_MEM].when >
+ sr.curr.reg[IA64_REG_PRI_UNAT_GR].when)
+ /* (primary) NaT bits were last saved to memory */
+ pri_unat = sr.curr.reg + IA64_REG_PRI_UNAT_MEM;
+ else
+ /* (primary) NaT bits were last saved to a register */
+ pri_unat = sr.curr.reg + IA64_REG_PRI_UNAT_GR;
+
+ /* Note: we always store the final primary-UNaT location in UNAT_MEM. */
+ compile_reg (&sr, IA64_REG_PRI_UNAT_MEM, pri_unat, script);
+ }
+
+ /* Third, compile the other register in decreasing order of WHEN values. */
+
+ num_regs = sort_regs (&sr, regorder);
+ for (i = 0; i < num_regs; ++i)
+ compile_reg (&sr, regorder[i], sr.curr.reg + regorder[i], script);
+
+ script->abi_marker = sr.abi_marker;
+ script_finalize (script, c, &sr);
+
+ ia64_free_state_record (&sr);
+ return 0;
+}
+
+static inline void
+set_nat_info (struct cursor *c, unsigned long dst,
+ ia64_loc_t nat_loc, uint8_t bitnr)
+{
+ assert (dst >= IA64_REG_R4 && dst <= IA64_REG_R7);
+
+ c->loc[dst - IA64_REG_R4 + IA64_REG_NAT4] = nat_loc;
+ c->nat_bitnr[dst - IA64_REG_R4] = bitnr;
+}
+
+/* Apply the unwinding actions represented by OPS and update SR to
+ reflect the state that existed upon entry to the function that this
+ unwinder represents. */
+
+static inline int
+run_script (struct ia64_script *script, struct cursor *c)
+{
+ struct ia64_script_insn *ip, *limit, next_insn;
+ ia64_loc_t loc, nat_loc;
+ unsigned long opc, dst;
+ uint8_t nat_bitnr;
+ unw_word_t val;
+ int ret;
+
+ c->pi = script->pi;
+ ip = script->insn;
+ limit = script->insn + script->count;
+ next_insn = *ip;
+ c->abi_marker = script->abi_marker;
+
+ while (ip++ < limit)
+ {
+ opc = next_insn.opc;
+ dst = next_insn.dst;
+ val = next_insn.val;
+ next_insn = *ip;
+
+ /* This is by far the most common operation: */
+ if (likely (opc == IA64_INSN_MOVE_STACKED))
+ {
+ if ((ret = ia64_get_stacked (c, val, &loc, NULL)) < 0)
+ return ret;
+ }
+ else
+ switch (opc)
+ {
+ case IA64_INSN_INC_PSP:
+ c->psp += val;
+ continue;
+
+ case IA64_INSN_LOAD_PSP:
+ if ((ret = ia64_get (c, c->loc[IA64_REG_PSP], &c->psp)) < 0)
+ return ret;
+ continue;
+
+ case IA64_INSN_ADD_PSP:
+ loc = IA64_LOC_ADDR (c->psp + val, (val & IA64_LOC_TYPE_FP));
+ break;
+
+ case IA64_INSN_ADD_SP:
+ loc = IA64_LOC_ADDR (c->sp + val, (val & IA64_LOC_TYPE_FP));
+ break;
+
+ case IA64_INSN_MOVE_NO_NAT:
+ set_nat_info (c, dst, IA64_NULL_LOC, 0);
+ case IA64_INSN_MOVE:
+ loc = c->loc[val];
+ break;
+
+ case IA64_INSN_MOVE_SCRATCH_NO_NAT:
+ set_nat_info (c, dst, IA64_NULL_LOC, 0);
+ case IA64_INSN_MOVE_SCRATCH:
+ loc = ia64_scratch_loc (c, val, NULL);
+ break;
+
+ case IA64_INSN_ADD_PSP_NAT:
+ loc = IA64_LOC_ADDR (c->psp + val, 0);
+ assert (!IA64_IS_REG_LOC (loc));
+ set_nat_info (c, dst,
+ c->loc[IA64_REG_PRI_UNAT_MEM],
+ ia64_unat_slot_num (IA64_GET_ADDR (loc)));
+ break;
+
+ case IA64_INSN_ADD_SP_NAT:
+ loc = IA64_LOC_ADDR (c->sp + val, 0);
+ assert (!IA64_IS_REG_LOC (loc));
+ set_nat_info (c, dst,
+ c->loc[IA64_REG_PRI_UNAT_MEM],
+ ia64_unat_slot_num (IA64_GET_ADDR (loc)));
+ break;
+
+ case IA64_INSN_MOVE_NAT:
+ loc = c->loc[val];
+ set_nat_info (c, dst,
+ c->loc[val - IA64_REG_R4 + IA64_REG_NAT4],
+ c->nat_bitnr[val - IA64_REG_R4]);
+ break;
+
+ case IA64_INSN_MOVE_STACKED_NAT:
+ if ((ret = ia64_get_stacked (c, val, &loc, &nat_loc)) < 0)
+ return ret;
+ assert (!IA64_IS_REG_LOC (loc));
+ set_nat_info (c, dst, nat_loc, rse_slot_num (IA64_GET_ADDR (loc)));
+ break;
+
+ case IA64_INSN_MOVE_SCRATCH_NAT:
+ loc = ia64_scratch_loc (c, val, NULL);
+ nat_loc = ia64_scratch_loc (c, val + (UNW_IA64_NAT - UNW_IA64_GR),
+ &nat_bitnr);
+ set_nat_info (c, dst, nat_loc, nat_bitnr);
+ break;
+ }
+ c->loc[dst] = loc;
+ }
+ return 0;
+}
+
+static int
+uncached_find_save_locs (struct cursor *c)
+{
+ struct ia64_script script;
+ int ret = 0;
+
+ if ((ret = ia64_fetch_proc_info (c, c->ip, 1)) < 0)
+ return ret;
+
+ script_init (&script, c->ip);
+ if ((ret = build_script (c, &script)) < 0)
+ {
+ if (ret != -UNW_ESTOPUNWIND)
+ Dprintf ("%s: failed to build unwind script for ip %lx\n",
+ __FUNCTION__, (long) c->ip);
+ return ret;
+ }
+ return run_script (&script, c);
+}
+
+HIDDEN int
+ia64_find_save_locs (struct cursor *c)
+{
+ struct ia64_script_cache *cache = NULL;
+ struct ia64_script *script = NULL;
+ intrmask_t saved_mask;
+ int ret = 0;
+
+ if (c->as->caching_policy == UNW_CACHE_NONE)
+ return uncached_find_save_locs (c);
+
+ cache = get_script_cache (c->as, &saved_mask);
+ if (!cache)
+ {
+ Debug (1, "contention on script-cache; doing uncached lookup\n");
+ return uncached_find_save_locs (c);
+ }
+ {
+ script = script_lookup (cache, c);
+ Debug (8, "ip %lx %s in script cache\n", (long) c->ip,
+ script ? "hit" : "missed");
+
+ if (!script || (script->count == 0 && !script->pi.unwind_info))
+ {
+ if ((ret = ia64_fetch_proc_info (c, c->ip, 1)) < 0)
+ goto out;
+ }
+
+ if (!script)
+ {
+ script = script_new (cache, c->ip);
+ if (!script)
+ {
+ Dprintf ("%s: failed to create unwind script\n", __FUNCTION__);
+ ret = -UNW_EUNSPEC;
+ goto out;
+ }
+ }
+ cache->buckets[c->prev_script].hint = script - cache->buckets;
+
+ if (script->count == 0)
+ ret = build_script (c, script);
+
+ assert (script->count > 0);
+
+ c->hint = script->hint;
+ c->prev_script = script - cache->buckets;
+
+ if (ret < 0)
+ {
+ if (ret != -UNW_ESTOPUNWIND)
+ Dprintf ("%s: failed to locate/build unwind script for ip %lx\n",
+ __FUNCTION__, (long) c->ip);
+ goto out;
+ }
+
+ ret = run_script (script, c);
+ }
+ out:
+ put_script_cache (c->as, cache, &saved_mask);
+ return ret;
+}
+
+HIDDEN void
+ia64_validate_cache (unw_addr_space_t as, void *arg)
+{
+#ifndef UNW_REMOTE_ONLY
+ if (as == unw_local_addr_space && ia64_local_validate_cache (as, arg) == 1)
+ return;
+#endif
+
+#ifndef UNW_LOCAL_ONLY
+ /* local info is up-to-date, check dynamic info. */
+ unwi_dyn_validate_cache (as, arg);
+#endif
+}
+
+HIDDEN int
+ia64_cache_proc_info (struct cursor *c)
+{
+ struct ia64_script_cache *cache;
+ struct ia64_script *script;
+ intrmask_t saved_mask;
+ int ret = 0;
+
+ cache = get_script_cache (c->as, &saved_mask);
+ if (!cache)
+ return ret; /* cache is busy */
+
+ /* Re-check to see if a cache entry has been added in the meantime: */
+ script = script_lookup (cache, c);
+ if (script)
+ goto out;
+
+ script = script_new (cache, c->ip);
+ if (!script)
+ {
+ Dprintf ("%s: failed to create unwind script\n", __FUNCTION__);
+ ret = -UNW_EUNSPEC;
+ goto out;
+ }
+
+ script->pi = c->pi;
+
+ out:
+ put_script_cache (c->as, cache, &saved_mask);
+ return ret;
+}
+
+HIDDEN int
+ia64_get_cached_proc_info (struct cursor *c)
+{
+ struct ia64_script_cache *cache;
+ struct ia64_script *script;
+ intrmask_t saved_mask;
+
+ cache = get_script_cache (c->as, &saved_mask);
+ if (!cache)
+ return -UNW_ENOINFO; /* cache is busy */
+ {
+ script = script_lookup (cache, c);
+ if (script)
+ c->pi = script->pi;
+ }
+ put_script_cache (c->as, cache, &saved_mask);
+ return script ? 0 : -UNW_ENOINFO;
+}
diff --git a/src/pal/src/libunwind/src/ia64/Gstep.c b/src/pal/src/libunwind/src/ia64/Gstep.c
new file mode 100644
index 0000000000..df4ecb8796
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Gstep.c
@@ -0,0 +1,359 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "offsets.h"
+#include "unwind_i.h"
+
+static inline int
+linux_sigtramp (struct cursor *c, ia64_loc_t prev_cfm_loc,
+ unw_word_t *num_regsp)
+{
+#if defined(UNW_LOCAL_ONLY) && !defined(__linux)
+ return -UNW_EINVAL;
+#else
+ unw_word_t sc_addr;
+ int ret;
+
+ if ((ret = ia64_get (c, IA64_LOC_ADDR (c->sp + 0x10
+ + LINUX_SIGFRAME_ARG2_OFF, 0),
+ &sc_addr)) < 0)
+ return ret;
+
+ c->sigcontext_addr = sc_addr;
+
+ if (!IA64_IS_REG_LOC (c->loc[IA64_REG_IP])
+ && IA64_GET_ADDR (c->loc[IA64_REG_IP]) == sc_addr + LINUX_SC_BR_OFF + 8)
+ {
+ /* Linux kernels before 2.4.19 and 2.5.10 had buggy
+ unwind info for sigtramp. Fix it up here. */
+ c->loc[IA64_REG_IP] = IA64_LOC_ADDR (sc_addr + LINUX_SC_IP_OFF, 0);
+ c->cfm_loc = IA64_LOC_ADDR (sc_addr + LINUX_SC_CFM_OFF, 0);
+ }
+
+ /* do what can't be described by unwind directives: */
+ c->loc[IA64_REG_PFS] = IA64_LOC_ADDR (sc_addr + LINUX_SC_AR_PFS_OFF, 0);
+ c->ec_loc = prev_cfm_loc;
+ *num_regsp = c->cfm & 0x7f; /* size of frame */
+ return 0;
+#endif
+}
+
+static inline int
+linux_interrupt (struct cursor *c, ia64_loc_t prev_cfm_loc,
+ unw_word_t *num_regsp, int marker)
+{
+#if defined(UNW_LOCAL_ONLY) && !(defined(__linux) && defined(__KERNEL__))
+ return -UNW_EINVAL;
+#else
+ unw_word_t sc_addr, num_regs;
+ ia64_loc_t pfs_loc;
+
+ sc_addr = c->sigcontext_addr = c->sp + 0x10;
+
+ if ((c->pr & (1UL << LINUX_PT_P_NONSYS)) != 0)
+ num_regs = c->cfm & 0x7f;
+ else
+ num_regs = 0;
+
+ /* do what can't be described by unwind directives: */
+ if (marker == ABI_MARKER_OLD_LINUX_INTERRUPT)
+ pfs_loc = IA64_LOC_ADDR (sc_addr + LINUX_OLD_PT_PFS_OFF, 0);
+ else
+ pfs_loc = IA64_LOC_ADDR (sc_addr + LINUX_PT_PFS_OFF, 0);
+ c->loc[IA64_REG_PFS] = pfs_loc;
+ c->ec_loc = prev_cfm_loc;
+ *num_regsp = num_regs; /* size of frame */
+ return 0;
+#endif
+}
+
+static inline int
+hpux_sigtramp (struct cursor *c, ia64_loc_t prev_cfm_loc,
+ unw_word_t *num_regsp)
+{
+#if defined(UNW_LOCAL_ONLY) && !defined(__hpux)
+ return -UNW_EINVAL;
+#else
+ unw_word_t sc_addr, bsp, bspstore;
+ ia64_loc_t sc_loc;
+ int ret, i;
+
+ /* HP-UX passes the address of ucontext_t in r32: */
+ if ((ret = ia64_get_stacked (c, 32, &sc_loc, NULL)) < 0)
+ return ret;
+ if ((ret = ia64_get (c, sc_loc, &sc_addr)) < 0)
+ return ret;
+
+ c->sigcontext_addr = sc_addr;
+
+ /* Now mark all (preserved) registers as coming from the
+ signal context: */
+ c->cfm_loc = IA64_LOC_UC_REG (UNW_IA64_CFM, sc_addr);
+ c->loc[IA64_REG_PRI_UNAT_MEM] = IA64_NULL_LOC;
+ c->loc[IA64_REG_PSP] = IA64_LOC_UC_REG (UNW_IA64_GR + 12, sc_addr);
+ c->loc[IA64_REG_BSP] = IA64_LOC_UC_REG (UNW_IA64_AR_BSP, sc_addr);
+ c->loc[IA64_REG_BSPSTORE] = IA64_LOC_UC_REG (UNW_IA64_AR_BSPSTORE, sc_addr);
+ c->loc[IA64_REG_PFS] = IA64_LOC_UC_REG (UNW_IA64_AR_PFS, sc_addr);
+ c->loc[IA64_REG_RNAT] = IA64_LOC_UC_REG (UNW_IA64_AR_RNAT, sc_addr);
+ c->loc[IA64_REG_IP] = IA64_LOC_UC_REG (UNW_IA64_IP, sc_addr);
+ c->loc[IA64_REG_R4] = IA64_LOC_UC_REG (UNW_IA64_GR + 4, sc_addr);
+ c->loc[IA64_REG_R5] = IA64_LOC_UC_REG (UNW_IA64_GR + 5, sc_addr);
+ c->loc[IA64_REG_R6] = IA64_LOC_UC_REG (UNW_IA64_GR + 6, sc_addr);
+ c->loc[IA64_REG_R7] = IA64_LOC_UC_REG (UNW_IA64_GR + 7, sc_addr);
+ c->loc[IA64_REG_NAT4] = IA64_LOC_UC_REG (UNW_IA64_NAT + 4, sc_addr);
+ c->loc[IA64_REG_NAT5] = IA64_LOC_UC_REG (UNW_IA64_NAT + 5, sc_addr);
+ c->loc[IA64_REG_NAT6] = IA64_LOC_UC_REG (UNW_IA64_NAT + 6, sc_addr);
+ c->loc[IA64_REG_NAT7] = IA64_LOC_UC_REG (UNW_IA64_NAT + 7, sc_addr);
+ c->loc[IA64_REG_UNAT] = IA64_LOC_UC_REG (UNW_IA64_AR_UNAT, sc_addr);
+ c->loc[IA64_REG_PR] = IA64_LOC_UC_REG (UNW_IA64_PR, sc_addr);
+ c->loc[IA64_REG_LC] = IA64_LOC_UC_REG (UNW_IA64_AR_LC, sc_addr);
+ c->loc[IA64_REG_FPSR] = IA64_LOC_UC_REG (UNW_IA64_AR_FPSR, sc_addr);
+ c->loc[IA64_REG_B1] = IA64_LOC_UC_REG (UNW_IA64_BR + 1, sc_addr);
+ c->loc[IA64_REG_B2] = IA64_LOC_UC_REG (UNW_IA64_BR + 2, sc_addr);
+ c->loc[IA64_REG_B3] = IA64_LOC_UC_REG (UNW_IA64_BR + 3, sc_addr);
+ c->loc[IA64_REG_B4] = IA64_LOC_UC_REG (UNW_IA64_BR + 4, sc_addr);
+ c->loc[IA64_REG_B5] = IA64_LOC_UC_REG (UNW_IA64_BR + 5, sc_addr);
+ c->loc[IA64_REG_F2] = IA64_LOC_UC_REG (UNW_IA64_FR + 2, sc_addr);
+ c->loc[IA64_REG_F3] = IA64_LOC_UC_REG (UNW_IA64_FR + 3, sc_addr);
+ c->loc[IA64_REG_F4] = IA64_LOC_UC_REG (UNW_IA64_FR + 4, sc_addr);
+ c->loc[IA64_REG_F5] = IA64_LOC_UC_REG (UNW_IA64_FR + 5, sc_addr);
+ for (i = 0; i < 16; ++i)
+ c->loc[IA64_REG_F16 + i] = IA64_LOC_UC_REG (UNW_IA64_FR + 16 + i, sc_addr);
+
+ c->pi.flags |= UNW_PI_FLAG_IA64_RBS_SWITCH;
+
+ /* update the CFM cache: */
+ if ((ret = ia64_get (c, c->cfm_loc, &c->cfm)) < 0)
+ return ret;
+ /* update the PSP cache: */
+ if ((ret = ia64_get (c, c->loc[IA64_REG_PSP], &c->psp)) < 0)
+ return ret;
+
+ if ((ret = ia64_get (c, c->loc[IA64_REG_BSP], &bsp)) < 0
+ || (ret = ia64_get (c, c->loc[IA64_REG_BSPSTORE], &bspstore)) < 0)
+ return ret;
+ if (bspstore < bsp)
+ /* Dirty partition got spilled into the ucontext_t structure
+ itself. We'll need to access it via uc_access(3). */
+ rbs_switch (c, bsp, bspstore, IA64_LOC_UC_ADDR (bsp | 0x1f8, 0));
+
+ c->ec_loc = prev_cfm_loc;
+
+ *num_regsp = 0;
+ return 0;
+#endif
+}
+
+
+static inline int
+check_rbs_switch (struct cursor *c)
+{
+ unw_word_t saved_bsp, saved_bspstore, loadrs, ndirty;
+ int ret = 0;
+
+ saved_bsp = c->bsp;
+ if (c->pi.flags & UNW_PI_FLAG_IA64_RBS_SWITCH)
+ {
+ /* Got ourselves a frame that has saved ar.bspstore, ar.bsp,
+ and ar.rnat, so we're all set for rbs-switching: */
+ if ((ret = ia64_get (c, c->loc[IA64_REG_BSP], &saved_bsp)) < 0
+ || (ret = ia64_get (c, c->loc[IA64_REG_BSPSTORE], &saved_bspstore)))
+ return ret;
+ }
+ else if ((c->abi_marker == ABI_MARKER_LINUX_SIGTRAMP
+ || c->abi_marker == ABI_MARKER_OLD_LINUX_SIGTRAMP)
+ && !IA64_IS_REG_LOC (c->loc[IA64_REG_BSP])
+ && (IA64_GET_ADDR (c->loc[IA64_REG_BSP])
+ == c->sigcontext_addr + LINUX_SC_AR_BSP_OFF))
+ {
+ /* When Linux delivers a signal on an alternate stack, it
+ does things a bit differently from what the unwind
+ conventions allow us to describe: instead of saving
+ ar.rnat, ar.bsp, and ar.bspstore, it saves the former two
+ plus the "loadrs" value. Because of this, we need to
+ detect & record a potential rbs-area switch
+ manually... */
+
+ /* If ar.bsp has been saved already AND the current bsp is
+ not equal to the saved value, then we know for sure that
+ we're past the point where the backing store has been
+ switched (and before the point where it's restored). */
+ if ((ret = ia64_get (c, IA64_LOC_ADDR (c->sigcontext_addr
+ + LINUX_SC_AR_BSP_OFF, 0),
+ &saved_bsp) < 0)
+ || (ret = ia64_get (c, IA64_LOC_ADDR (c->sigcontext_addr
+ + LINUX_SC_LOADRS_OFF, 0),
+ &loadrs) < 0))
+ return ret;
+ loadrs >>= 16;
+ ndirty = rse_num_regs (c->bsp - loadrs, c->bsp);
+ saved_bspstore = rse_skip_regs (saved_bsp, -ndirty);
+ }
+
+ if (saved_bsp == c->bsp)
+ return 0;
+
+ return rbs_switch (c, saved_bsp, saved_bspstore, c->loc[IA64_REG_RNAT]);
+}
+
+static inline int
+update_frame_state (struct cursor *c)
+{
+ unw_word_t prev_ip, prev_sp, prev_bsp, ip, num_regs;
+ ia64_loc_t prev_cfm_loc;
+ int ret;
+
+ prev_cfm_loc = c->cfm_loc;
+ prev_ip = c->ip;
+ prev_sp = c->sp;
+ prev_bsp = c->bsp;
+
+ /* Update the IP cache (do this first: if we reach the end of the
+ frame-chain, the rest of the info may not be valid/useful
+ anymore. */
+ ret = ia64_get (c, c->loc[IA64_REG_IP], &ip);
+ if (ret < 0)
+ return ret;
+ c->ip = ip;
+
+ if ((ip & 0xc) != 0)
+ {
+ /* don't let obviously bad addresses pollute the cache */
+ Debug (1, "rejecting bad ip=0x%lx\n", (long) c->ip);
+ return -UNW_EINVALIDIP;
+ }
+
+ c->cfm_loc = c->loc[IA64_REG_PFS];
+ /* update the CFM cache: */
+ ret = ia64_get (c, c->cfm_loc, &c->cfm);
+ if (ret < 0)
+ return ret;
+
+ /* Normally, AR.EC is stored in the CFM save-location. That
+ save-location contains the full function-state as defined by
+ AR.PFS. However, interruptions only save the frame-marker, not
+ any other info in CFM. Instead, AR.EC gets saved on the first
+ call by the interruption-handler. Thus, interruption-related
+ frames need to track the _previous_ CFM save-location since
+ that's were AR.EC is saved. We support this by setting ec_loc to
+ cfm_loc by default and giving frames marked with an ABI-marker
+ the chance to override this value with prev_cfm_loc. */
+ c->ec_loc = c->cfm_loc;
+
+ num_regs = 0;
+ if (unlikely (c->abi_marker))
+ {
+ c->last_abi_marker = c->abi_marker;
+ switch (ia64_get_abi_marker (c))
+ {
+ case ABI_MARKER_LINUX_SIGTRAMP:
+ case ABI_MARKER_OLD_LINUX_SIGTRAMP:
+ ia64_set_abi (c, ABI_LINUX);
+ if ((ret = linux_sigtramp (c, prev_cfm_loc, &num_regs)) < 0)
+ return ret;
+ break;
+
+ case ABI_MARKER_OLD_LINUX_INTERRUPT:
+ case ABI_MARKER_LINUX_INTERRUPT:
+ ia64_set_abi (c, ABI_LINUX);
+ if ((ret = linux_interrupt (c, prev_cfm_loc, &num_regs,
+ c->abi_marker)) < 0)
+ return ret;
+ break;
+
+ case ABI_MARKER_HP_UX_SIGTRAMP:
+ ia64_set_abi (c, ABI_HPUX);
+ if ((ret = hpux_sigtramp (c, prev_cfm_loc, &num_regs)) < 0)
+ return ret;
+ break;
+
+ default:
+ Debug (1, "unknown ABI marker: ABI=%u, context=%u\n",
+ c->abi_marker >> 8, c->abi_marker & 0xff);
+ return -UNW_EINVAL;
+ }
+ Debug (12, "sigcontext_addr=%lx (ret=%d)\n",
+ (unsigned long) c->sigcontext_addr, ret);
+
+ c->sigcontext_off = c->sigcontext_addr - c->sp;
+
+ /* update the IP cache: */
+ if ((ret = ia64_get (c, c->loc[IA64_REG_IP], &ip)) < 0)
+ return ret;
+ c->ip = ip;
+ if (ip == 0)
+ /* end of frame-chain reached */
+ return 0;
+ }
+ else
+ num_regs = (c->cfm >> 7) & 0x7f; /* size of locals */
+
+ if (!IA64_IS_NULL_LOC (c->loc[IA64_REG_BSP]))
+ {
+ ret = check_rbs_switch (c);
+ if (ret < 0)
+ return ret;
+ }
+
+ c->bsp = rse_skip_regs (c->bsp, -num_regs);
+
+ c->sp = c->psp;
+ c->abi_marker = 0;
+
+ if (c->ip == prev_ip && c->sp == prev_sp && c->bsp == prev_bsp)
+ {
+ Dprintf ("%s: ip, sp, and bsp unchanged; stopping here (ip=0x%lx)\n",
+ __FUNCTION__, (long) ip);
+ return -UNW_EBADFRAME;
+ }
+
+ /* as we unwind, the saved ar.unat becomes the primary unat: */
+ c->loc[IA64_REG_PRI_UNAT_MEM] = c->loc[IA64_REG_UNAT];
+
+ /* restore the predicates: */
+ ret = ia64_get (c, c->loc[IA64_REG_PR], &c->pr);
+ if (ret < 0)
+ return ret;
+
+ c->pi_valid = 0;
+ return 0;
+}
+
+
+int
+unw_step (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ Debug (1, "(cursor=%p, ip=0x%016lx)\n", c, (unsigned long) c->ip);
+
+ if ((ret = ia64_find_save_locs (c)) >= 0
+ && (ret = update_frame_state (c)) >= 0)
+ ret = (c->ip == 0) ? 0 : 1;
+
+ Debug (2, "returning %d (ip=0x%016lx)\n", ret, (unsigned long) c->ip);
+ return ret;
+}
diff --git a/src/pal/src/libunwind/src/ia64/Gtables.c b/src/pal/src/libunwind/src/ia64/Gtables.c
new file mode 100644
index 0000000000..f5e8f2d8f4
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Gtables.c
@@ -0,0 +1,731 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2001-2005 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stddef.h>
+
+#include "unwind_i.h"
+
+#ifdef HAVE_IA64INTRIN_H
+# include <ia64intrin.h>
+#endif
+
+extern unw_addr_space_t _ULia64_local_addr_space;
+
+struct ia64_table_entry
+ {
+ uint64_t start_offset;
+ uint64_t end_offset;
+ uint64_t info_offset;
+ };
+
+#ifdef UNW_LOCAL_ONLY
+
+static inline int
+is_local_addr_space (unw_addr_space_t as)
+{
+ return 1;
+}
+
+static inline int
+read_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, void *arg)
+{
+ *valp = *(unw_word_t *) addr;
+ return 0;
+}
+
+#else /* !UNW_LOCAL_ONLY */
+
+static inline int
+is_local_addr_space (unw_addr_space_t as)
+{
+ return as == unw_local_addr_space;
+}
+
+static inline int
+read_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, void *arg)
+{
+ unw_accessors_t *a = unw_get_accessors_int (as);
+
+ return (*a->access_mem) (as, addr, valp, 0, arg);
+}
+
+/* Helper macro for reading an ia64_table_entry from remote memory. */
+#define remote_read(addr, member) \
+ (*a->access_mem) (as, (addr) + offsetof (struct ia64_table_entry, \
+ member), &member, 0, arg)
+
+/* Lookup an unwind-table entry in remote memory. Returns 1 if an
+ entry is found, 0 if no entry is found, negative if an error
+ occurred reading remote memory. */
+static int
+remote_lookup (unw_addr_space_t as,
+ unw_word_t table, size_t table_size, unw_word_t rel_ip,
+ struct ia64_table_entry *e, void *arg)
+{
+ unw_word_t e_addr = 0, start_offset, end_offset, info_offset;
+ unw_accessors_t *a = unw_get_accessors_int (as);
+ unsigned long lo, hi, mid;
+ int ret;
+
+ /* do a binary search for right entry: */
+ for (lo = 0, hi = table_size / sizeof (struct ia64_table_entry); lo < hi;)
+ {
+ mid = (lo + hi) / 2;
+ e_addr = table + mid * sizeof (struct ia64_table_entry);
+ if ((ret = remote_read (e_addr, start_offset)) < 0)
+ return ret;
+
+ if (rel_ip < start_offset)
+ hi = mid;
+ else
+ {
+ if ((ret = remote_read (e_addr, end_offset)) < 0)
+ return ret;
+
+ if (rel_ip >= end_offset)
+ lo = mid + 1;
+ else
+ break;
+ }
+ }
+ if (rel_ip < start_offset || rel_ip >= end_offset)
+ return 0;
+ e->start_offset = start_offset;
+ e->end_offset = end_offset;
+
+ if ((ret = remote_read (e_addr, info_offset)) < 0)
+ return ret;
+ e->info_offset = info_offset;
+ return 1;
+}
+
+HIDDEN void
+tdep_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg)
+{
+ if (!pi->unwind_info)
+ return;
+
+ if (is_local_addr_space (as))
+ {
+ free (pi->unwind_info);
+ pi->unwind_info = NULL;
+ }
+}
+
+unw_word_t
+_Uia64_find_dyn_list (unw_addr_space_t as, unw_dyn_info_t *di, void *arg)
+{
+ unw_word_t hdr_addr, info_addr, hdr, directives, pers, cookie, off;
+ unw_word_t start_offset, end_offset, info_offset, segbase;
+ struct ia64_table_entry *e;
+ size_t table_size;
+ unw_word_t gp = di->gp;
+ int ret;
+
+ switch (di->format)
+ {
+ case UNW_INFO_FORMAT_DYNAMIC:
+ default:
+ return 0;
+
+ case UNW_INFO_FORMAT_TABLE:
+ e = (struct ia64_table_entry *) di->u.ti.table_data;
+ table_size = di->u.ti.table_len * sizeof (di->u.ti.table_data[0]);
+ segbase = di->u.ti.segbase;
+ if (table_size < sizeof (struct ia64_table_entry))
+ return 0;
+ start_offset = e[0].start_offset;
+ end_offset = e[0].end_offset;
+ info_offset = e[0].info_offset;
+ break;
+
+ case UNW_INFO_FORMAT_REMOTE_TABLE:
+ {
+ unw_accessors_t *a = unw_get_accessors_int (as);
+ unw_word_t e_addr = di->u.rti.table_data;
+
+ table_size = di->u.rti.table_len * sizeof (unw_word_t);
+ segbase = di->u.rti.segbase;
+ if (table_size < sizeof (struct ia64_table_entry))
+ return 0;
+
+ if ( (ret = remote_read (e_addr, start_offset) < 0)
+ || (ret = remote_read (e_addr, end_offset) < 0)
+ || (ret = remote_read (e_addr, info_offset) < 0))
+ return ret;
+ }
+ break;
+ }
+
+ if (start_offset != end_offset)
+ /* dyn-list entry cover a zero-length "procedure" and should be
+ first entry (note: technically a binary could contain code
+ below the segment base, but this doesn't happen for normal
+ binaries and certainly doesn't happen when libunwind is a
+ separate shared object. For weird cases, the application may
+ have to provide its own (slower) version of this routine. */
+ return 0;
+
+ hdr_addr = info_offset + segbase;
+ info_addr = hdr_addr + 8;
+
+ /* read the header word: */
+ if ((ret = read_mem (as, hdr_addr, &hdr, arg)) < 0)
+ return ret;
+
+ if (IA64_UNW_VER (hdr) != 1
+ || IA64_UNW_FLAG_EHANDLER (hdr) || IA64_UNW_FLAG_UHANDLER (hdr))
+ /* dyn-list entry must be version 1 and doesn't have ehandler
+ or uhandler */
+ return 0;
+
+ if (IA64_UNW_LENGTH (hdr) != 1)
+ /* dyn-list entry must consist of a single word of NOP directives */
+ return 0;
+
+ if ( ((ret = read_mem (as, info_addr, &directives, arg)) < 0)
+ || ((ret = read_mem (as, info_addr + 0x08, &pers, arg)) < 0)
+ || ((ret = read_mem (as, info_addr + 0x10, &cookie, arg)) < 0)
+ || ((ret = read_mem (as, info_addr + 0x18, &off, arg)) < 0))
+ return 0;
+
+ if (directives != 0 || pers != 0
+ || (!as->big_endian && cookie != 0x7473696c2d6e7964ULL)
+ || ( as->big_endian && cookie != 0x64796e2d6c697374ULL))
+ return 0;
+
+ /* OK, we ran the gauntlet and found it: */
+ return off + gp;
+}
+
+#endif /* !UNW_LOCAL_ONLY */
+
+static inline const struct ia64_table_entry *
+lookup (struct ia64_table_entry *table, size_t table_size, unw_word_t rel_ip)
+{
+ const struct ia64_table_entry *e = 0;
+ unsigned long lo, hi, mid;
+
+ /* do a binary search for right entry: */
+ for (lo = 0, hi = table_size / sizeof (struct ia64_table_entry); lo < hi;)
+ {
+ mid = (lo + hi) / 2;
+ e = table + mid;
+ if (rel_ip < e->start_offset)
+ hi = mid;
+ else if (rel_ip >= e->end_offset)
+ lo = mid + 1;
+ else
+ break;
+ }
+ if (rel_ip < e->start_offset || rel_ip >= e->end_offset)
+ return NULL;
+ return e;
+}
+
+int
+unw_search_ia64_unwind_table (unw_addr_space_t as, unw_word_t ip,
+ unw_dyn_info_t *di, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg)
+{
+ unw_word_t addr, hdr_addr, info_addr, info_end_addr, hdr, *wp;
+ const struct ia64_table_entry *e = NULL;
+ unw_word_t handler_offset, segbase = 0;
+ int ret, is_local;
+#ifndef UNW_LOCAL_ONLY
+ struct ia64_table_entry ent;
+#endif
+
+ assert ((di->format == UNW_INFO_FORMAT_TABLE
+ || di->format == UNW_INFO_FORMAT_REMOTE_TABLE)
+ && (ip >= di->start_ip && ip < di->end_ip));
+
+ pi->flags = 0;
+ pi->unwind_info = 0;
+ pi->handler = 0;
+
+ if (likely (di->format == UNW_INFO_FORMAT_TABLE))
+ {
+ segbase = di->u.ti.segbase;
+ e = lookup ((struct ia64_table_entry *) di->u.ti.table_data,
+ di->u.ti.table_len * sizeof (unw_word_t),
+ ip - segbase);
+ }
+#ifndef UNW_LOCAL_ONLY
+ else
+ {
+ segbase = di->u.rti.segbase;
+ if ((ret = remote_lookup (as, di->u.rti.table_data,
+ di->u.rti.table_len * sizeof (unw_word_t),
+ ip - segbase, &ent, arg)) < 0)
+ return ret;
+ if (ret)
+ e = &ent;
+ }
+#endif
+ if (!e)
+ {
+ /* IP is inside this table's range, but there is no explicit
+ unwind info => use default conventions (i.e., this is NOT an
+ error). */
+ memset (pi, 0, sizeof (*pi));
+ pi->start_ip = 0;
+ pi->end_ip = 0;
+ pi->gp = di->gp;
+ pi->lsda = 0;
+ return 0;
+ }
+
+ pi->start_ip = e->start_offset + segbase;
+ pi->end_ip = e->end_offset + segbase;
+
+ hdr_addr = e->info_offset + segbase;
+ info_addr = hdr_addr + 8;
+
+ /* Read the header word. Note: the actual unwind-info is always
+ assumed to reside in memory, independent of whether di->format is
+ UNW_INFO_FORMAT_TABLE or UNW_INFO_FORMAT_REMOTE_TABLE. */
+
+ if ((ret = read_mem (as, hdr_addr, &hdr, arg)) < 0)
+ return ret;
+
+ if (IA64_UNW_VER (hdr) != 1)
+ {
+ Debug (1, "Unknown header version %ld (hdr word=0x%lx @ 0x%lx)\n",
+ IA64_UNW_VER (hdr), (unsigned long) hdr,
+ (unsigned long) hdr_addr);
+ return -UNW_EBADVERSION;
+ }
+
+ info_end_addr = info_addr + 8 * IA64_UNW_LENGTH (hdr);
+
+ is_local = is_local_addr_space (as);
+
+ /* If we must have the unwind-info, return it. Also, if we are in
+ the local address-space, return the unwind-info because it's so
+ cheap to do so and it may come in handy later on. */
+ if (need_unwind_info || is_local)
+ {
+ pi->unwind_info_size = 8 * IA64_UNW_LENGTH (hdr);
+
+ if (is_local)
+ pi->unwind_info = (void *) (uintptr_t) info_addr;
+ else
+ {
+ /* Internalize unwind info. Note: since we're doing this
+ only for non-local address spaces, there is no
+ signal-safety issue and it is OK to use malloc()/free(). */
+ pi->unwind_info = malloc (8 * IA64_UNW_LENGTH (hdr));
+ if (!pi->unwind_info)
+ return -UNW_ENOMEM;
+
+ wp = (unw_word_t *) pi->unwind_info;
+ for (addr = info_addr; addr < info_end_addr; addr += 8, ++wp)
+ {
+ if ((ret = read_mem (as, addr, wp, arg)) < 0)
+ {
+ free (pi->unwind_info);
+ return ret;
+ }
+ }
+ }
+ }
+
+ if (IA64_UNW_FLAG_EHANDLER (hdr) || IA64_UNW_FLAG_UHANDLER (hdr))
+ {
+ /* read the personality routine address (address is gp-relative): */
+ if ((ret = read_mem (as, info_end_addr, &handler_offset, arg)) < 0)
+ return ret;
+ Debug (4, "handler ptr @ offset=%lx, gp=%lx\n", handler_offset, di->gp);
+ if ((read_mem (as, handler_offset + di->gp, &pi->handler, arg)) < 0)
+ return ret;
+ }
+ pi->lsda = info_end_addr + 8;
+ pi->gp = di->gp;
+ pi->format = di->format;
+ return 0;
+}
+
+#ifndef UNW_REMOTE_ONLY
+
+# if defined(HAVE_DL_ITERATE_PHDR)
+# include <link.h>
+# include <stdlib.h>
+
+# if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 2) \
+ || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && !defined(DT_CONFIG))
+# error You need GLIBC 2.2.4 or later on IA-64 Linux
+# endif
+
+# if defined(HAVE_GETUNWIND)
+ extern unsigned long getunwind (void *buf, size_t len);
+# else /* HAVE_GETUNWIND */
+# include <unistd.h>
+# include <sys/syscall.h>
+# ifndef __NR_getunwind
+# define __NR_getunwind 1215
+# endif
+
+static unsigned long
+getunwind (void *buf, size_t len)
+{
+ return syscall (SYS_getunwind, buf, len);
+}
+
+# endif /* HAVE_GETUNWIND */
+
+static unw_dyn_info_t kernel_table;
+
+static int
+get_kernel_table (unw_dyn_info_t *di)
+{
+ struct ia64_table_entry *ktab, *etab;
+ size_t size;
+
+ Debug (16, "getting kernel table");
+
+ size = getunwind (NULL, 0);
+ ktab = sos_alloc (size);
+ if (!ktab)
+ {
+ Dprintf (__FILE__".%s: failed to allocate %zu bytes",
+ __FUNCTION__, size);
+ return -UNW_ENOMEM;
+ }
+ getunwind (ktab, size);
+
+ /* Determine length of kernel's unwind table & relocate its entries. */
+ for (etab = ktab; etab->start_offset; ++etab)
+ etab->info_offset += (uint64_t) ktab;
+
+ di->format = UNW_INFO_FORMAT_TABLE;
+ di->gp = 0;
+ di->start_ip = ktab[0].start_offset;
+ di->end_ip = etab[-1].end_offset;
+ di->u.ti.name_ptr = (unw_word_t) "<kernel>";
+ di->u.ti.segbase = 0;
+ di->u.ti.table_len = ((char *) etab - (char *) ktab) / sizeof (unw_word_t);
+ di->u.ti.table_data = (unw_word_t *) ktab;
+
+ Debug (16, "found table `%s': [%lx-%lx) segbase=%lx len=%lu\n",
+ (char *) di->u.ti.name_ptr, di->start_ip, di->end_ip,
+ di->u.ti.segbase, di->u.ti.table_len);
+ return 0;
+}
+
+# ifndef UNW_LOCAL_ONLY
+
+/* This is exported for the benefit of libunwind-ptrace.a. */
+int
+_Uia64_get_kernel_table (unw_dyn_info_t *di)
+{
+ int ret;
+
+ if (!kernel_table.u.ti.table_data)
+ if ((ret = get_kernel_table (&kernel_table)) < 0)
+ return ret;
+
+ memcpy (di, &kernel_table, sizeof (*di));
+ return 0;
+}
+
+# endif /* !UNW_LOCAL_ONLY */
+
+static inline unsigned long
+current_gp (void)
+{
+# if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+ register unsigned long gp __asm__("gp");
+ return gp;
+# elif HAVE_IA64INTRIN_H
+ return __getReg (_IA64_REG_GP);
+# else
+# error Implement me.
+# endif
+}
+
+static int
+callback (struct dl_phdr_info *info, size_t size, void *ptr)
+{
+ unw_dyn_info_t *di = ptr;
+ const Elf64_Phdr *phdr, *p_unwind, *p_dynamic, *p_text;
+ long n;
+ Elf64_Addr load_base, segbase = 0;
+
+ /* Make sure struct dl_phdr_info is at least as big as we need. */
+ if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
+ + sizeof (info->dlpi_phnum))
+ return -1;
+
+ Debug (16, "checking `%s' (load_base=%lx)\n",
+ info->dlpi_name, info->dlpi_addr);
+
+ phdr = info->dlpi_phdr;
+ load_base = info->dlpi_addr;
+ p_text = NULL;
+ p_unwind = NULL;
+ p_dynamic = NULL;
+
+ /* See if PC falls into one of the loaded segments. Find the unwind
+ segment at the same time. */
+ for (n = info->dlpi_phnum; --n >= 0; phdr++)
+ {
+ if (phdr->p_type == PT_LOAD)
+ {
+ Elf64_Addr vaddr = phdr->p_vaddr + load_base;
+ if (di->u.ti.segbase >= vaddr
+ && di->u.ti.segbase < vaddr + phdr->p_memsz)
+ p_text = phdr;
+ }
+ else if (phdr->p_type == PT_IA_64_UNWIND)
+ p_unwind = phdr;
+ else if (phdr->p_type == PT_DYNAMIC)
+ p_dynamic = phdr;
+ }
+ if (!p_text || !p_unwind)
+ return 0;
+
+ if (likely (p_unwind->p_vaddr >= p_text->p_vaddr
+ && p_unwind->p_vaddr < p_text->p_vaddr + p_text->p_memsz))
+ /* normal case: unwind table is inside text segment */
+ segbase = p_text->p_vaddr + load_base;
+ else
+ {
+ /* Special case: unwind table is in some other segment; this
+ happens for the Linux kernel's gate DSO, for example. */
+ phdr = info->dlpi_phdr;
+ for (n = info->dlpi_phnum; --n >= 0; phdr++)
+ {
+ if (phdr->p_type == PT_LOAD && p_unwind->p_vaddr >= phdr->p_vaddr
+ && p_unwind->p_vaddr < phdr->p_vaddr + phdr->p_memsz)
+ {
+ segbase = phdr->p_vaddr + load_base;
+ break;
+ }
+ }
+ }
+
+ if (p_dynamic)
+ {
+ /* For dynamicly linked executables and shared libraries,
+ DT_PLTGOT is the gp value for that object. */
+ Elf64_Dyn *dyn = (Elf64_Dyn *)(p_dynamic->p_vaddr + load_base);
+ for (; dyn->d_tag != DT_NULL; ++dyn)
+ if (dyn->d_tag == DT_PLTGOT)
+ {
+ /* On IA-64, _DYNAMIC is writable and GLIBC has relocated it. */
+ di->gp = dyn->d_un.d_ptr;
+ break;
+ }
+ }
+ else
+ /* Otherwise this is a static executable with no _DYNAMIC.
+ The gp is constant program-wide. */
+ di->gp = current_gp();
+ di->format = UNW_INFO_FORMAT_TABLE;
+ di->start_ip = p_text->p_vaddr + load_base;
+ di->end_ip = p_text->p_vaddr + load_base + p_text->p_memsz;
+ di->u.ti.name_ptr = (unw_word_t) info->dlpi_name;
+ di->u.ti.table_data = (void *) (p_unwind->p_vaddr + load_base);
+ di->u.ti.table_len = p_unwind->p_memsz / sizeof (unw_word_t);
+ di->u.ti.segbase = segbase;
+
+ Debug (16, "found table `%s': segbase=%lx, len=%lu, gp=%lx, "
+ "table_data=%p\n", (char *) di->u.ti.name_ptr, di->u.ti.segbase,
+ di->u.ti.table_len, di->gp, di->u.ti.table_data);
+ return 1;
+}
+
+# ifdef HAVE_DL_PHDR_REMOVALS_COUNTER
+
+static inline int
+validate_cache (unw_addr_space_t as)
+{
+ /* Note: we don't need to serialize here with respect to
+ dl_iterate_phdr() because if somebody were to remove an object
+ that is required to complete the unwind on whose behalf we're
+ validating the cache here, we'd be hosed anyhow. What we're
+ guarding against here is the case where library FOO gets mapped,
+ unwind info for FOO gets cached, FOO gets unmapped, BAR gets
+ mapped in the place where FOO was and then we unwind across a
+ function in FOO. Since no thread can execute in BAR before FOO
+ has been removed, we are guaranteed that
+ dl_phdr_removals_counter() would have been incremented before we
+ get here. */
+ unsigned long long removals = dl_phdr_removals_counter ();
+
+ if (removals == as->shared_object_removals)
+ return 1;
+
+ as->shared_object_removals = removals;
+ unw_flush_cache (as, 0, 0);
+ return -1;
+}
+
+# else /* !HAVE_DL_PHDR_REMOVALS_COUNTER */
+
+/* Check whether any phdrs have been removed since we last flushed the
+ cache. If so we flush the cache and return -1, if not, we do
+ nothing and return 1. */
+
+static int
+check_callback (struct dl_phdr_info *info, size_t size, void *ptr)
+{
+# ifdef HAVE_STRUCT_DL_PHDR_INFO_DLPI_SUBS
+ unw_addr_space_t as = ptr;
+
+ if (size <
+ offsetof (struct dl_phdr_info, dlpi_subs) + sizeof (info->dlpi_subs))
+ /* It would be safer to flush the cache here, but that would
+ disable caching for older libc's which would be incompatible
+ with the behavior of older versions of libunwind so we return 1
+ instead and hope nobody runs into stale cache info... */
+ return 1;
+
+ if (info->dlpi_subs == as->shared_object_removals)
+ return 1;
+
+ as->shared_object_removals = info->dlpi_subs;
+ unw_flush_cache (as, 0, 0);
+ return -1; /* indicate that there were removals */
+# else
+ return 1;
+# endif
+}
+
+static inline int
+validate_cache (unw_addr_space_t as)
+{
+ intrmask_t saved_mask;
+ int ret;
+
+ SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask);
+ ret = dl_iterate_phdr (check_callback, as);
+ SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
+ return ret;
+}
+
+# endif /* HAVE_DL_PHDR_REMOVALS_COUNTER */
+
+# elif defined(HAVE_DLMODINFO)
+ /* Support for HP-UX-style dlmodinfo() */
+# include <dlfcn.h>
+
+static inline int
+validate_cache (unw_addr_space_t as)
+{
+ return 1;
+}
+
+# endif /* !HAVE_DLMODINFO */
+
+HIDDEN int
+tdep_find_proc_info (unw_addr_space_t as, unw_word_t ip,
+ unw_proc_info_t *pi, int need_unwind_info, void *arg)
+{
+# if defined(HAVE_DL_ITERATE_PHDR)
+ unw_dyn_info_t di, *dip = &di;
+ intrmask_t saved_mask;
+ int ret;
+
+ di.u.ti.segbase = ip; /* this is cheap... */
+
+ SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask);
+ ret = dl_iterate_phdr (callback, &di);
+ SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
+
+ if (ret <= 0)
+ {
+ if (!kernel_table.u.ti.table_data)
+ {
+ if ((ret = get_kernel_table (&kernel_table)) < 0)
+ return ret;
+ }
+ if (ip < kernel_table.start_ip || ip >= kernel_table.end_ip)
+ return -UNW_ENOINFO;
+ dip = &kernel_table;
+ }
+# elif defined(HAVE_DLMODINFO)
+# define UNWIND_TBL_32BIT 0x8000000000000000
+ struct load_module_desc lmd;
+ unw_dyn_info_t di, *dip = &di;
+ struct unwind_header
+ {
+ uint64_t header_version;
+ uint64_t start_offset;
+ uint64_t end_offset;
+ }
+ *uhdr;
+
+ if (!dlmodinfo (ip, &lmd, sizeof (lmd), NULL, 0, 0))
+ return -UNW_ENOINFO;
+
+ di.format = UNW_INFO_FORMAT_TABLE;
+ di.start_ip = lmd.text_base;
+ di.end_ip = lmd.text_base + lmd.text_size;
+ di.gp = lmd.linkage_ptr;
+ di.u.ti.name_ptr = 0; /* no obvious table-name available */
+ di.u.ti.segbase = lmd.text_base;
+
+ uhdr = (struct unwind_header *) lmd.unwind_base;
+
+ if ((uhdr->header_version & ~UNWIND_TBL_32BIT) != 1
+ && (uhdr->header_version & ~UNWIND_TBL_32BIT) != 2)
+ {
+ Debug (1, "encountered unknown unwind header version %ld\n",
+ (long) (uhdr->header_version & ~UNWIND_TBL_32BIT));
+ return -UNW_EBADVERSION;
+ }
+ if (uhdr->header_version & UNWIND_TBL_32BIT)
+ {
+ Debug (1, "32-bit unwind tables are not supported yet\n");
+ return -UNW_EINVAL;
+ }
+
+ di.u.ti.table_data = (unw_word_t *) (di.u.ti.segbase + uhdr->start_offset);
+ di.u.ti.table_len = ((uhdr->end_offset - uhdr->start_offset)
+ / sizeof (unw_word_t));
+
+ Debug (16, "found table `%s': segbase=%lx, len=%lu, gp=%lx, "
+ "table_data=%p\n", (char *) di.u.ti.name_ptr, di.u.ti.segbase,
+ di.u.ti.table_len, di.gp, di.u.ti.table_data);
+# endif
+
+ /* now search the table: */
+ return tdep_search_unwind_table (as, ip, dip, pi, need_unwind_info, arg);
+}
+
+/* Returns 1 if the cache is up-to-date or -1 if the cache contained
+ stale data and had to be flushed. */
+
+HIDDEN int
+ia64_local_validate_cache (unw_addr_space_t as, void *arg)
+{
+ return validate_cache (as);
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/ia64/Lapply_reg_state.c b/src/pal/src/libunwind/src/ia64/Lapply_reg_state.c
new file mode 100644
index 0000000000..7ebada480e
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Lapply_reg_state.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Lcreate_addr_space.c b/src/pal/src/libunwind/src/ia64/Lcreate_addr_space.c
new file mode 100644
index 0000000000..0f2dc6be90
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Lcreate_addr_space.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gcreate_addr_space.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Lfind_unwind_table.c b/src/pal/src/libunwind/src/ia64/Lfind_unwind_table.c
new file mode 100644
index 0000000000..68e269f1d7
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Lfind_unwind_table.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gfind_unwind_table.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Lget_proc_info.c b/src/pal/src/libunwind/src/ia64/Lget_proc_info.c
new file mode 100644
index 0000000000..69028b019f
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Lget_proc_info.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_proc_info.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Lget_save_loc.c b/src/pal/src/libunwind/src/ia64/Lget_save_loc.c
new file mode 100644
index 0000000000..9ea048a907
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Lget_save_loc.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_save_loc.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Lglobal.c b/src/pal/src/libunwind/src/ia64/Lglobal.c
new file mode 100644
index 0000000000..6d7b489e14
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Lglobal.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gglobal.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Linit.c b/src/pal/src/libunwind/src/ia64/Linit.c
new file mode 100644
index 0000000000..e9abfdd46a
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Linit.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Linit_local.c b/src/pal/src/libunwind/src/ia64/Linit_local.c
new file mode 100644
index 0000000000..68a1687e85
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Linit_local.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_local.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Linit_remote.c b/src/pal/src/libunwind/src/ia64/Linit_remote.c
new file mode 100644
index 0000000000..58cb04ab7c
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Linit_remote.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_remote.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Linstall_cursor.S b/src/pal/src/libunwind/src/ia64/Linstall_cursor.S
new file mode 100644
index 0000000000..8c72339725
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Linstall_cursor.S
@@ -0,0 +1,6 @@
+#define UNW_LOCAL_ONLY
+#include "Ginstall_cursor.S"
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Lis_signal_frame.c b/src/pal/src/libunwind/src/ia64/Lis_signal_frame.c
new file mode 100644
index 0000000000..b9a7c4f51a
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Lis_signal_frame.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gis_signal_frame.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Lparser.c b/src/pal/src/libunwind/src/ia64/Lparser.c
new file mode 100644
index 0000000000..f23aaf48e9
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Lparser.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gparser.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Lrbs.c b/src/pal/src/libunwind/src/ia64/Lrbs.c
new file mode 100644
index 0000000000..a91b5f2979
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Lrbs.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Grbs.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Lreg_states_iterate.c b/src/pal/src/libunwind/src/ia64/Lreg_states_iterate.c
new file mode 100644
index 0000000000..f1eb1e79dc
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Lreg_states_iterate.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Lregs.c b/src/pal/src/libunwind/src/ia64/Lregs.c
new file mode 100644
index 0000000000..2c9c75cd7d
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Lregs.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gregs.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Lresume.c b/src/pal/src/libunwind/src/ia64/Lresume.c
new file mode 100644
index 0000000000..41a8cf003d
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Lresume.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gresume.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Lscript.c b/src/pal/src/libunwind/src/ia64/Lscript.c
new file mode 100644
index 0000000000..57b926bf80
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Lscript.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gscript.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Lstep.c b/src/pal/src/libunwind/src/ia64/Lstep.c
new file mode 100644
index 0000000000..c1ac3c7547
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Lstep.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gstep.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/Ltables.c b/src/pal/src/libunwind/src/ia64/Ltables.c
new file mode 100644
index 0000000000..876b0aac03
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/Ltables.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gtables.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/NOTES b/src/pal/src/libunwind/src/ia64/NOTES
new file mode 100644
index 0000000000..a5805e8345
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/NOTES
@@ -0,0 +1,65 @@
+- the frame state consists of the following:
+
+ - ip current instruction pointer
+ - sp current stack pointer value
+ - bsp current backing store pointer
+ - cfm current frame mask
+
+ these are derived from the next younger (more deeply nested) frame
+ as follows:
+
+ - ip == saved return-link (may be b0 or an alternate branch-reg)
+ - sp == if younger frame has a fixed-sized frame, sp + size-of-frame,
+ else saved sp
+ - cfm == saved ar.pfs
+ - bsp == if ar.bsp has been saved, saved ar.bsp, otherwise,
+ ar.bsp \ominus saved ar.pfs.pfm.sol
+
+The unwind cursor should represent the machine state as it existed at
+the address contained in register ip. This state consists of the
+*current* frame state and the save locations in the next younger
+frame.
+
+An unwind script current takes the old save locations and updates them
+for the next older frame. With the new setup, we need to update the
+frame state first, without updating the other save locations. For this
+to work, we need the following info:
+
+ - save location of return-link
+ - save location of ar.pfs
+ - save location of bsp (if it has been saved)
+ - size of stack frame (fixed case) or save location of sp
+
+
+setup:
+
+ func: ...
+ ...
+ ...
+ br.call foo <-- call site
+ ... <-- ip
+ ...
+
+initial state:
+
+ The unwind cursor represents the (preserved) machine state
+ as it existed at "ip".
+
+ Evaluating the unwind descriptors for "ip" yields the following
+ info:
+
+ - frame size at call site (or previous sp)
+ - what registers where saved where by func before
+ the call site was reached
+
+
+ Note that there is some procedure info that needs to be obtained
+ for the new "ip" which is contained in the unwind descriptors.
+ Specifically, the following is needed:
+
+ - procedure's start address
+ - personality address
+ - pointer to language-specific data area
+
+ This info is stored in a separate proc_info structure and needs
+ to be obtained right after running the unwind script for func.
diff --git a/src/pal/src/libunwind/src/ia64/dyn_info_list.S b/src/pal/src/libunwind/src/ia64/dyn_info_list.S
new file mode 100644
index 0000000000..31265f66a0
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/dyn_info_list.S
@@ -0,0 +1,26 @@
+#ifndef UNW_REMOTE_ONLY
+
+/*
+ * Create a special unwind-table entry which makes it easy for an
+ * unwinder to locate the dynamic registration list. The special
+ * entry covers address range [0-0) and is therefore guaranteed to be
+ * the first in the unwind-table.
+ */
+ .global _U_dyn_info_list
+ .hidden _U_dyn_info_list
+
+ .section .IA_64.unwind_info,"a","progbits"
+.info: data8 (1<<48) | 1 /* v1, length==1 (8-byte word) */
+ data8 0 /* 8 empty .prologue directives (nops) */
+ data8 0 /* personality routine (ignored) */
+ string "dyn-list" /* lsda */
+ data8 @gprel(_U_dyn_info_list)
+
+ .section .IA_64.unwind, "a", "progbits"
+ data8 0, 0, @segrel(.info)
+
+#endif
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/getcontext.S b/src/pal/src/libunwind/src/ia64/getcontext.S
new file mode 100644
index 0000000000..d8da732acc
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/getcontext.S
@@ -0,0 +1,177 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "ucontext_i.h"
+
+#define GR(n) (SC_GR + (n)*8)
+#define BR(n) (SC_BR + (n)*8)
+#define FR(n) (SC_FR + (n)*16)
+
+/* This should be compatible to the libc's getcontext(), except that
+ the sc->sc_mask field is always cleared and that the name is
+ prefixed with _Uia64_ so we don't step on the application's
+ name-space. */
+
+ .align 32
+ .protected _Uia64_getcontext
+ .global _Uia64_getcontext
+ .proc _Uia64_getcontext
+_Uia64_getcontext:
+ .prologue
+ alloc rPFS = ar.pfs, 1, 0, 0, 0 // M2
+ mov rPR = pr // I0, 2 cycles
+ add r2 = GR(1), in0 // I1
+ ;;
+
+ .save ar.unat, rUNAT
+ mov.m rUNAT = ar.unat // M2, 5 cycles
+ .body
+ st8.spill [r2] = r1, (SC_FLAGS - GR(1)) // M3
+ dep.z rFLAGS = -1, IA64_SC_FLAG_SYNCHRONOUS_BIT, 1 // I0, 1 cycle
+ ;;
+
+ mov.m rRSC = ar.rsc // M2, 12 cyc.
+ st8 [r2] = rFLAGS, (SC_PR - SC_FLAGS) // M3
+ add r3 = FR(2), in0
+ ;;
+
+ mov.m rBSP = ar.bsp // M2, 12 cyc.
+ st8 [r2] = rPR, (GR(12) - SC_PR) // M3
+ add r8 = FR(16), in0
+ ;;
+
+ mov.m rFPSR = ar.fpsr // M2, 12 cyc.
+ st8.spill [r2] = r12, (GR(4) - GR(12)) // M3
+ add r9 = FR(24), in0
+ ;;
+
+ stf.spill [r3] = f2 // M2
+ stf.spill [r8] = f16 // M3
+ add r3 = GR(7), in0
+ ;;
+
+ flushrs // M0
+ stf.spill [r9] = f24, (FR(31) - FR(24)) // M2
+ mov rB0 = b0 // I0, 2 cycles
+ ;;
+
+ stf.spill [r9] = f31 // M2
+ st8.spill [r2] = r4, (GR(5) - GR(4)) // M3, bank 1
+ mov rB1 = b1 // I0, 2 cycles
+ ;;
+
+.mem.offset 0,0; st8.spill [r2] = r5, (GR(6) - GR(5)) // M4, bank 0
+.mem.offset 8,0; st8.spill [r3] = r7, (BR(0) - GR(7)) // M3, bank 0
+ mov rB2 = b2 // I0, 2 cycles
+ ;;
+
+ st8.spill [r2] = r6, (BR(1) - GR(6)) // M2, bank 1
+ st8 [r3] = rB0, (BR(4) - BR(0)) // M3, bank 1
+ mov rB4 = b4 // I0, 2 cycles
+ ;;
+
+ mov.m rNAT = ar.unat // M2, 5 cycles
+ st8 [r2] = rB1, (BR(2) - BR(1)) // M3, bank 0
+ mov rB3 = b3
+ ;;
+
+ st8 [r2] = rB2, (BR(3) - BR(2)) // M2, bank 1
+ st8 [r3] = rB4, (SC_LC - BR(4)) // M3, bank 1
+ mov rB5 = b5 // I0, 2 cycles
+ ;;
+
+ and rTMP = ~0x3, rRSC // M0
+ add rPOS = GR(0), in0 // rPOS <- &sc_gr[0] // M1
+ mov.i rLC = ar.lc // I0, 2 cycles
+ ;;
+
+ mov.m ar.rsc = rTMP // put RSE into lazy mode // M2, ? cycles
+ st8 [r2] = rB3, (BR(5) - BR(3)) // M3, bank 0
+ extr.u rPOS = rPOS, 3, 6 // get NaT bitnr for r0 // I0
+ ;;
+
+ mov.m rRNAT = ar.rnat // M2, 5 cycles
+ st8 [r2] = rB5, (SC_PFS - BR(5)) // M3, bank 0
+ sub rCPOS = 64, rPOS // I0
+ ;;
+
+ st8 [r2] = rPFS, (SC_UNAT - SC_PFS) // M2
+ st8 [r3] = rLC, (SC_BSP - SC_LC) // M3
+ shr.u rTMP = rNAT, rPOS // I0, 3 cycles
+ ;;
+
+ st8 [r2] = rUNAT, (SC_FPSR - SC_UNAT) // M2
+ st8 [r3] = rBSP // M3
+ add r8 = FR(3), in0
+ ;;
+
+ st8 [r2] = rFPSR, (SC_RNAT - SC_FPSR) // M2
+ stf.spill [r8] = f3, (FR(4) - FR(3)) // M3
+ add r9 = FR(5), in0
+ ;;
+
+ stf.spill [r8] = f4, (FR(17) - FR(4)) // M2
+ stf.spill [r9] = f5, (FR(19) - FR(5)) // M3
+ shl rNAT = rNAT, rCPOS // I0, 3 cycles
+ ;;
+
+ st8 [r2] = rRNAT, (SC_NAT - SC_RNAT) // M2
+ stf.spill [r8] = f17, (FR(18) - FR(17)) // M3
+ nop.i 0
+ ;;
+
+ stf.spill [r8] = f18, (FR(20) - FR(18)) // M2
+ stf.spill [r9] = f19, (FR(21) - FR(19)) // M3
+ nop.i 0
+ ;;
+
+ stf.spill [r8] = f20, (FR(22) - FR(20)) // M2
+ stf.spill [r9] = f21, (FR(23) - FR(21)) // M3
+ or rNAT = rNAT, rTMP // I0
+ ;;
+
+ st8 [r2] = rNAT // M2
+ stf.spill [r8] = f22, (FR(25) - FR(22)) // M3
+ ;;
+ stf.spill [r9] = f23, (FR(26) - FR(23)) // M2
+ stf.spill [r8] = f25, (FR(27) - FR(25)) // M3
+ ;;
+ stf.spill [r9] = f26, (FR(28) - FR(26)) // M2
+ stf.spill [r8] = f27, (FR(29) - FR(27)) // M3
+ ;;
+ mov.m ar.rsc = rRSC // restore RSE mode // M2
+ stf.spill [r9] = f28, (FR(30) - FR(28)) // M3
+ ;;
+ mov.m ar.unat = rUNAT // restore caller's UNaT // M2
+ stf.spill [r8] = f29 // M3
+ ;;
+ stf.spill [r9] = f30 // M2
+ mov r8 = 0
+ br.ret.sptk.many rp
+ .endp _Uia64_getcontext
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/init.h b/src/pal/src/libunwind/src/ia64/init.h
new file mode 100644
index 0000000000..6628a1d888
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/init.h
@@ -0,0 +1,132 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+static ALWAYS_INLINE int
+common_init (struct cursor *c, unw_word_t sp, unw_word_t bsp)
+{
+ unw_word_t bspstore, rbs_base;
+ int ret;
+
+ if (c->as->caching_policy != UNW_CACHE_NONE)
+ /* ensure cache doesn't have any stale contents: */
+ ia64_validate_cache (c->as, c->as_arg);
+
+ c->cfm_loc = IA64_REG_LOC (c, UNW_IA64_CFM);
+ c->loc[IA64_REG_BSP] = IA64_NULL_LOC;
+ c->loc[IA64_REG_BSPSTORE] = IA64_REG_LOC (c, UNW_IA64_AR_BSPSTORE);
+ c->loc[IA64_REG_PFS] = IA64_REG_LOC (c, UNW_IA64_AR_PFS);
+ c->loc[IA64_REG_RNAT] = IA64_REG_LOC (c, UNW_IA64_AR_RNAT);
+ c->loc[IA64_REG_IP] = IA64_REG_LOC (c, UNW_IA64_IP);
+ c->loc[IA64_REG_PRI_UNAT_MEM] = IA64_NULL_LOC; /* no primary UNaT location */
+ c->loc[IA64_REG_UNAT] = IA64_REG_LOC (c, UNW_IA64_AR_UNAT);
+ c->loc[IA64_REG_PR] = IA64_REG_LOC (c, UNW_IA64_PR);
+ c->loc[IA64_REG_LC] = IA64_REG_LOC (c, UNW_IA64_AR_LC);
+ c->loc[IA64_REG_FPSR] = IA64_REG_LOC (c, UNW_IA64_AR_FPSR);
+
+ c->loc[IA64_REG_R4] = IA64_REG_LOC (c, UNW_IA64_GR + 4);
+ c->loc[IA64_REG_R5] = IA64_REG_LOC (c, UNW_IA64_GR + 5);
+ c->loc[IA64_REG_R6] = IA64_REG_LOC (c, UNW_IA64_GR + 6);
+ c->loc[IA64_REG_R7] = IA64_REG_LOC (c, UNW_IA64_GR + 7);
+
+ c->loc[IA64_REG_NAT4] = IA64_REG_NAT_LOC (c, UNW_IA64_NAT + 4, &c->nat_bitnr[0]);
+ c->loc[IA64_REG_NAT5] = IA64_REG_NAT_LOC (c, UNW_IA64_NAT + 5, &c->nat_bitnr[1]);
+ c->loc[IA64_REG_NAT6] = IA64_REG_NAT_LOC (c, UNW_IA64_NAT + 6, &c->nat_bitnr[2]);
+ c->loc[IA64_REG_NAT7] = IA64_REG_NAT_LOC (c, UNW_IA64_NAT + 7, &c->nat_bitnr[3]);
+
+ c->loc[IA64_REG_B1] = IA64_REG_LOC (c, UNW_IA64_BR + 1);
+ c->loc[IA64_REG_B2] = IA64_REG_LOC (c, UNW_IA64_BR + 2);
+ c->loc[IA64_REG_B3] = IA64_REG_LOC (c, UNW_IA64_BR + 3);
+ c->loc[IA64_REG_B4] = IA64_REG_LOC (c, UNW_IA64_BR + 4);
+ c->loc[IA64_REG_B5] = IA64_REG_LOC (c, UNW_IA64_BR + 5);
+
+ c->loc[IA64_REG_F2] = IA64_FPREG_LOC (c, UNW_IA64_FR + 2);
+ c->loc[IA64_REG_F3] = IA64_FPREG_LOC (c, UNW_IA64_FR + 3);
+ c->loc[IA64_REG_F4] = IA64_FPREG_LOC (c, UNW_IA64_FR + 4);
+ c->loc[IA64_REG_F5] = IA64_FPREG_LOC (c, UNW_IA64_FR + 5);
+ c->loc[IA64_REG_F16] = IA64_FPREG_LOC (c, UNW_IA64_FR + 16);
+ c->loc[IA64_REG_F17] = IA64_FPREG_LOC (c, UNW_IA64_FR + 17);
+ c->loc[IA64_REG_F18] = IA64_FPREG_LOC (c, UNW_IA64_FR + 18);
+ c->loc[IA64_REG_F19] = IA64_FPREG_LOC (c, UNW_IA64_FR + 19);
+ c->loc[IA64_REG_F20] = IA64_FPREG_LOC (c, UNW_IA64_FR + 20);
+ c->loc[IA64_REG_F21] = IA64_FPREG_LOC (c, UNW_IA64_FR + 21);
+ c->loc[IA64_REG_F22] = IA64_FPREG_LOC (c, UNW_IA64_FR + 22);
+ c->loc[IA64_REG_F23] = IA64_FPREG_LOC (c, UNW_IA64_FR + 23);
+ c->loc[IA64_REG_F24] = IA64_FPREG_LOC (c, UNW_IA64_FR + 24);
+ c->loc[IA64_REG_F25] = IA64_FPREG_LOC (c, UNW_IA64_FR + 25);
+ c->loc[IA64_REG_F26] = IA64_FPREG_LOC (c, UNW_IA64_FR + 26);
+ c->loc[IA64_REG_F27] = IA64_FPREG_LOC (c, UNW_IA64_FR + 27);
+ c->loc[IA64_REG_F28] = IA64_FPREG_LOC (c, UNW_IA64_FR + 28);
+ c->loc[IA64_REG_F29] = IA64_FPREG_LOC (c, UNW_IA64_FR + 29);
+ c->loc[IA64_REG_F30] = IA64_FPREG_LOC (c, UNW_IA64_FR + 30);
+ c->loc[IA64_REG_F31] = IA64_FPREG_LOC (c, UNW_IA64_FR + 31);
+
+ ret = ia64_get (c, c->loc[IA64_REG_IP], &c->ip);
+ if (ret < 0)
+ return ret;
+
+ ret = ia64_get (c, c->cfm_loc, &c->cfm);
+ if (ret < 0)
+ return ret;
+
+ ret = ia64_get (c, c->loc[IA64_REG_PR], &c->pr);
+ if (ret < 0)
+ return ret;
+
+ c->sp = c->psp = sp;
+ c->bsp = bsp;
+
+ ret = ia64_get (c, c->loc[IA64_REG_BSPSTORE], &bspstore);
+ if (ret < 0)
+ return ret;
+
+ c->rbs_curr = c->rbs_left_edge = 0;
+
+ /* Try to find a base of the register backing-store. We may default
+ to a reasonable value (e.g., half the address-space down from
+ bspstore). If the BSPSTORE looks corrupt, we fail. */
+ if ((ret = rbs_get_base (c, bspstore, &rbs_base)) < 0)
+ return ret;
+
+ c->rbs_area[0].end = bspstore;
+ c->rbs_area[0].size = bspstore - rbs_base;
+ c->rbs_area[0].rnat_loc = IA64_REG_LOC (c, UNW_IA64_AR_RNAT);
+ Debug (10, "initial rbs-area: [0x%llx-0x%llx), rnat@%s\n",
+ (long long) rbs_base, (long long) c->rbs_area[0].end,
+ ia64_strloc (c->rbs_area[0].rnat_loc));
+
+ c->pi.flags = 0;
+
+ c->sigcontext_addr = 0;
+ c->abi_marker = 0;
+ c->last_abi_marker = 0;
+
+ c->hint = 0;
+ c->prev_script = 0;
+ c->eh_valid_mask = 0;
+ c->pi_valid = 0;
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/ia64/longjmp.S b/src/pal/src/libunwind/src/ia64/longjmp.S
new file mode 100644
index 0000000000..2a2f286594
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/longjmp.S
@@ -0,0 +1,42 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+ .global _UI_longjmp_cont
+
+ .align 32
+ .proc longjmp_continuation
+longjmp_continuation:
+_UI_longjmp_cont: // non-function label for {sig,}longjmp.c
+ .prologue
+ .save rp, r15
+ .body
+ mov rp = r15
+ mov r8 = r16
+ br.sptk.many rp
+ .endp longjmp_continuation
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/mk_cursor_i b/src/pal/src/libunwind/src/ia64/mk_cursor_i
new file mode 100755
index 0000000000..9211f91bbb
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/mk_cursor_i
@@ -0,0 +1,7 @@
+#!/bin/sh
+test -z "$1" && exit 1
+echo "/* GENERATED */"
+echo "#ifndef cursor_i_h"
+echo "#define cursor_i_h"
+sed -ne 's/^->"\(\S*\)" \(\d*\)/#define \1 \2/p' < $1 || exit $?
+echo "#endif"
diff --git a/src/pal/src/libunwind/src/ia64/offsets.h b/src/pal/src/libunwind/src/ia64/offsets.h
new file mode 100644
index 0000000000..5ab7f8b31e
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/offsets.h
@@ -0,0 +1,137 @@
+/* Linux-specific definitions: */
+
+/* Define various structure offsets to simplify cross-compilation. */
+
+/* The first three 64-bit words in a signal frame contain the signal
+ number, siginfo pointer, and sigcontext pointer passed to the
+ signal handler. We use this to locate the sigcontext pointer. */
+
+#define LINUX_SIGFRAME_ARG2_OFF 0x10
+
+#define LINUX_SC_FLAGS_OFF 0x000
+#define LINUX_SC_NAT_OFF 0x008
+#define LINUX_SC_STACK_OFF 0x010
+#define LINUX_SC_IP_OFF 0x028
+#define LINUX_SC_CFM_OFF 0x030
+#define LINUX_SC_UM_OFF 0x038
+#define LINUX_SC_AR_RSC_OFF 0x040
+#define LINUX_SC_AR_BSP_OFF 0x048
+#define LINUX_SC_AR_RNAT_OFF 0x050
+#define LINUX_SC_AR_CCV 0x058
+#define LINUX_SC_AR_UNAT_OFF 0x060
+#define LINUX_SC_AR_FPSR_OFF 0x068
+#define LINUX_SC_AR_PFS_OFF 0x070
+#define LINUX_SC_AR_LC_OFF 0x078
+#define LINUX_SC_PR_OFF 0x080
+#define LINUX_SC_BR_OFF 0x088
+#define LINUX_SC_GR_OFF 0x0c8
+#define LINUX_SC_FR_OFF 0x1d0
+#define LINUX_SC_RBS_BASE_OFF 0x9d0
+#define LINUX_SC_LOADRS_OFF 0x9d8
+#define LINUX_SC_AR_CSD_OFF 0x9e0
+#define LINUX_SC_AR_SSD_OFF 0x9e8
+#define LINUX_SC_MASK 0xa50
+
+/* Layout of old Linux kernel interrupt frame (struct pt_regs). */
+
+#define LINUX_OLD_PT_IPSR_OFF 0x000
+#define LINUX_OLD_PT_IIP_OFF 0x008
+#define LINUX_OLD_PT_IFS_OFF 0x010
+#define LINUX_OLD_PT_UNAT_OFF 0x018
+#define LINUX_OLD_PT_PFS_OFF 0x020
+#define LINUX_OLD_PT_RSC_OFF 0x028
+#define LINUX_OLD_PT_RNAT_OFF 0x030
+#define LINUX_OLD_PT_BSPSTORE_OFF 0x038
+#define LINUX_OLD_PT_PR_OFF 0x040
+#define LINUX_OLD_PT_B6_OFF 0x048
+#define LINUX_OLD_PT_LOADRS_OFF 0x050
+#define LINUX_OLD_PT_R1_OFF 0x058
+#define LINUX_OLD_PT_R2_OFF 0x060
+#define LINUX_OLD_PT_R3_OFF 0x068
+#define LINUX_OLD_PT_R12_OFF 0x070
+#define LINUX_OLD_PT_R13_OFF 0x078
+#define LINUX_OLD_PT_R14_OFF 0x080
+#define LINUX_OLD_PT_R15_OFF 0x088
+#define LINUX_OLD_PT_R8_OFF 0x090
+#define LINUX_OLD_PT_R9_OFF 0x098
+#define LINUX_OLD_PT_R10_OFF 0x0a0
+#define LINUX_OLD_PT_R11_OFF 0x0a8
+#define LINUX_OLD_PT_R16_OFF 0x0b0
+#define LINUX_OLD_PT_R17_OFF 0x0b8
+#define LINUX_OLD_PT_R18_OFF 0x0c0
+#define LINUX_OLD_PT_R19_OFF 0x0c8
+#define LINUX_OLD_PT_R20_OFF 0x0d0
+#define LINUX_OLD_PT_R21_OFF 0x0d8
+#define LINUX_OLD_PT_R22_OFF 0x0e0
+#define LINUX_OLD_PT_R23_OFF 0x0e8
+#define LINUX_OLD_PT_R24_OFF 0x0f0
+#define LINUX_OLD_PT_R25_OFF 0x0f8
+#define LINUX_OLD_PT_R26_OFF 0x100
+#define LINUX_OLD_PT_R27_OFF 0x108
+#define LINUX_OLD_PT_R28_OFF 0x110
+#define LINUX_OLD_PT_R29_OFF 0x118
+#define LINUX_OLD_PT_R30_OFF 0x120
+#define LINUX_OLD_PT_R31_OFF 0x128
+#define LINUX_OLD_PT_CCV_OFF 0x130
+#define LINUX_OLD_PT_FPSR_OFF 0x138
+#define LINUX_OLD_PT_B0_OFF 0x140
+#define LINUX_OLD_PT_B7_OFF 0x148
+#define LINUX_OLD_PT_F6_OFF 0x150
+#define LINUX_OLD_PT_F7_OFF 0x160
+#define LINUX_OLD_PT_F8_OFF 0x170
+#define LINUX_OLD_PT_F9_OFF 0x180
+
+/* Layout of new Linux kernel interrupt frame (struct pt_regs). */
+
+#define LINUX_PT_B6_OFF 0
+#define LINUX_PT_B7_OFF 8
+#define LINUX_PT_CSD_OFF 16
+#define LINUX_PT_SSD_OFF 24
+#define LINUX_PT_R8_OFF 32
+#define LINUX_PT_R9_OFF 40
+#define LINUX_PT_R10_OFF 48
+#define LINUX_PT_R11_OFF 56
+#define LINUX_PT_IPSR_OFF 64
+#define LINUX_PT_IIP_OFF 72
+#define LINUX_PT_IFS_OFF 80
+#define LINUX_PT_UNAT_OFF 88
+#define LINUX_PT_PFS_OFF 96
+#define LINUX_PT_RSC_OFF 104
+#define LINUX_PT_RNAT_OFF 112
+#define LINUX_PT_BSPSTORE_OFF 120
+#define LINUX_PT_PR_OFF 128
+#define LINUX_PT_B0_OFF 136
+#define LINUX_PT_LOADRS_OFF 144
+#define LINUX_PT_R1_OFF 152
+#define LINUX_PT_R12_OFF 160
+#define LINUX_PT_R13_OFF 168
+#define LINUX_PT_FPSR_OFF 176
+#define LINUX_PT_R15_OFF 184
+#define LINUX_PT_R14_OFF 192
+#define LINUX_PT_R2_OFF 200
+#define LINUX_PT_R3_OFF 208
+#define LINUX_PT_R16_OFF 216
+#define LINUX_PT_R17_OFF 224
+#define LINUX_PT_R18_OFF 232
+#define LINUX_PT_R19_OFF 240
+#define LINUX_PT_R20_OFF 248
+#define LINUX_PT_R21_OFF 256
+#define LINUX_PT_R22_OFF 264
+#define LINUX_PT_R23_OFF 272
+#define LINUX_PT_R24_OFF 280
+#define LINUX_PT_R25_OFF 288
+#define LINUX_PT_R26_OFF 296
+#define LINUX_PT_R27_OFF 304
+#define LINUX_PT_R28_OFF 312
+#define LINUX_PT_R29_OFF 320
+#define LINUX_PT_R30_OFF 328
+#define LINUX_PT_R31_OFF 336
+#define LINUX_PT_CCV_OFF 344
+#define LINUX_PT_F6_OFF 352
+#define LINUX_PT_F7_OFF 368
+#define LINUX_PT_F8_OFF 384
+#define LINUX_PT_F9_OFF 400
+#define LINUX_PT_F10_OFF 416
+#define LINUX_PT_F11_OFF 432
+
+#define LINUX_PT_P_NONSYS 5 /* must match pNonSys in entry.h */
diff --git a/src/pal/src/libunwind/src/ia64/regname.c b/src/pal/src/libunwind/src/ia64/regname.c
new file mode 100644
index 0000000000..3636df87de
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/regname.c
@@ -0,0 +1,189 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Logically, we like to think of the stack as a contiguous region of
+memory. Unfortunately, this logical view doesn't work for the
+register backing store, because the RSE is an asynchronous engine and
+because UNIX/Linux allow for stack-switching via sigaltstack(2).
+Specifically, this means that any given stacked register may or may
+not be backed up by memory in the current stack. If not, then the
+backing memory may be found in any of the "more inner" (younger)
+stacks. The routines in this file help manage the discontiguous
+nature of the register backing store. The routines are completely
+independent of UNIX/Linux, but each stack frame that switches the
+backing store is expected to reserve 4 words for use by libunwind. For
+example, in the Linux sigcontext, sc_fr[0] and sc_fr[1] serve this
+purpose. */
+
+#include "libunwind_i.h"
+
+/* Maintain the register names as a single string to keep the number
+ of dynamic relocations in the shared object to a minimum. */
+
+#define regname_len 9
+#define regname_str \
+ "r0\0\0\0\0\0\0\0r1\0\0\0\0\0\0\0r2\0\0\0\0\0\0\0r3\0\0\0\0\0\0\0" \
+ "r4\0\0\0\0\0\0\0r5\0\0\0\0\0\0\0r6\0\0\0\0\0\0\0r7\0\0\0\0\0\0\0" \
+ "r8\0\0\0\0\0\0\0r9\0\0\0\0\0\0\0r10\0\0\0\0\0\0r11\0\0\0\0\0\0" \
+ "r12\0\0\0\0\0\0r13\0\0\0\0\0\0r14\0\0\0\0\0\0r15\0\0\0\0\0\0" \
+ "r16\0\0\0\0\0\0r17\0\0\0\0\0\0r18\0\0\0\0\0\0r19\0\0\0\0\0\0" \
+ "r20\0\0\0\0\0\0r21\0\0\0\0\0\0r22\0\0\0\0\0\0r23\0\0\0\0\0\0" \
+ "r24\0\0\0\0\0\0r25\0\0\0\0\0\0r26\0\0\0\0\0\0r27\0\0\0\0\0\0" \
+ "r28\0\0\0\0\0\0r29\0\0\0\0\0\0r30\0\0\0\0\0\0r31\0\0\0\0\0\0" \
+ "r32\0\0\0\0\0\0r33\0\0\0\0\0\0r34\0\0\0\0\0\0r35\0\0\0\0\0\0" \
+ "r36\0\0\0\0\0\0r37\0\0\0\0\0\0r38\0\0\0\0\0\0r39\0\0\0\0\0\0" \
+ "r40\0\0\0\0\0\0r41\0\0\0\0\0\0r42\0\0\0\0\0\0r43\0\0\0\0\0\0" \
+ "r44\0\0\0\0\0\0r45\0\0\0\0\0\0r46\0\0\0\0\0\0r47\0\0\0\0\0\0" \
+ "r48\0\0\0\0\0\0r49\0\0\0\0\0\0r50\0\0\0\0\0\0r51\0\0\0\0\0\0" \
+ "r52\0\0\0\0\0\0r53\0\0\0\0\0\0r54\0\0\0\0\0\0r55\0\0\0\0\0\0" \
+ "r56\0\0\0\0\0\0r57\0\0\0\0\0\0r58\0\0\0\0\0\0r59\0\0\0\0\0\0" \
+ "r60\0\0\0\0\0\0r61\0\0\0\0\0\0r62\0\0\0\0\0\0r63\0\0\0\0\0\0" \
+ "r64\0\0\0\0\0\0r65\0\0\0\0\0\0r66\0\0\0\0\0\0r67\0\0\0\0\0\0" \
+ "r68\0\0\0\0\0\0r69\0\0\0\0\0\0r70\0\0\0\0\0\0r71\0\0\0\0\0\0" \
+ "r72\0\0\0\0\0\0r73\0\0\0\0\0\0r74\0\0\0\0\0\0r75\0\0\0\0\0\0" \
+ "r76\0\0\0\0\0\0r77\0\0\0\0\0\0r78\0\0\0\0\0\0r79\0\0\0\0\0\0" \
+ "r80\0\0\0\0\0\0r81\0\0\0\0\0\0r82\0\0\0\0\0\0r83\0\0\0\0\0\0" \
+ "r84\0\0\0\0\0\0r85\0\0\0\0\0\0r86\0\0\0\0\0\0r87\0\0\0\0\0\0" \
+ "r88\0\0\0\0\0\0r89\0\0\0\0\0\0r90\0\0\0\0\0\0r91\0\0\0\0\0\0" \
+ "r92\0\0\0\0\0\0r93\0\0\0\0\0\0r94\0\0\0\0\0\0r95\0\0\0\0\0\0" \
+ "r96\0\0\0\0\0\0r97\0\0\0\0\0\0r98\0\0\0\0\0\0r99\0\0\0\0\0\0" \
+ "r100\0\0\0\0\0r101\0\0\0\0\0r102\0\0\0\0\0r103\0\0\0\0\0" \
+ "r104\0\0\0\0\0r105\0\0\0\0\0r106\0\0\0\0\0r107\0\0\0\0\0" \
+ "r108\0\0\0\0\0r109\0\0\0\0\0r110\0\0\0\0\0r111\0\0\0\0\0" \
+ "r112\0\0\0\0\0r113\0\0\0\0\0r114\0\0\0\0\0r115\0\0\0\0\0" \
+ "r116\0\0\0\0\0r117\0\0\0\0\0r118\0\0\0\0\0r119\0\0\0\0\0" \
+ "r120\0\0\0\0\0r121\0\0\0\0\0r122\0\0\0\0\0r123\0\0\0\0\0" \
+ "r124\0\0\0\0\0r125\0\0\0\0\0r126\0\0\0\0\0r127\0\0\0\0\0" \
+ "nat0\0\0\0\0\0nat1\0\0\0\0\0nat2\0\0\0\0\0nat3\0\0\0\0\0" \
+ "nat4\0\0\0\0\0nat5\0\0\0\0\0nat6\0\0\0\0\0nat7\0\0\0\0\0" \
+ "nat8\0\0\0\0\0nat9\0\0\0\0\0nat10\0\0\0\0nat11\0\0\0\0" \
+ "nat12\0\0\0\0nat13\0\0\0\0nat14\0\0\0\0nat15\0\0\0\0" \
+ "nat16\0\0\0\0nat17\0\0\0\0nat18\0\0\0\0nat19\0\0\0\0" \
+ "nat20\0\0\0\0nat21\0\0\0\0nat22\0\0\0\0nat23\0\0\0\0" \
+ "nat24\0\0\0\0nat25\0\0\0\0nat26\0\0\0\0nat27\0\0\0\0" \
+ "nat28\0\0\0\0nat29\0\0\0\0nat30\0\0\0\0nat31\0\0\0\0" \
+ "nat32\0\0\0\0nat33\0\0\0\0nat34\0\0\0\0nat35\0\0\0\0" \
+ "nat36\0\0\0\0nat37\0\0\0\0nat38\0\0\0\0nat39\0\0\0\0" \
+ "nat40\0\0\0\0nat41\0\0\0\0nat42\0\0\0\0nat43\0\0\0\0" \
+ "nat44\0\0\0\0nat45\0\0\0\0nat46\0\0\0\0nat47\0\0\0\0" \
+ "nat48\0\0\0\0nat49\0\0\0\0nat50\0\0\0\0nat51\0\0\0\0" \
+ "nat52\0\0\0\0nat53\0\0\0\0nat54\0\0\0\0nat55\0\0\0\0" \
+ "nat56\0\0\0\0nat57\0\0\0\0nat58\0\0\0\0nat59\0\0\0\0" \
+ "nat60\0\0\0\0nat61\0\0\0\0nat62\0\0\0\0nat63\0\0\0\0" \
+ "nat64\0\0\0\0nat65\0\0\0\0nat66\0\0\0\0nat67\0\0\0\0" \
+ "nat68\0\0\0\0nat69\0\0\0\0nat70\0\0\0\0nat71\0\0\0\0" \
+ "nat72\0\0\0\0nat73\0\0\0\0nat74\0\0\0\0nat75\0\0\0\0" \
+ "nat76\0\0\0\0nat77\0\0\0\0nat78\0\0\0\0nat79\0\0\0\0" \
+ "nat80\0\0\0\0nat81\0\0\0\0nat82\0\0\0\0nat83\0\0\0\0" \
+ "nat84\0\0\0\0nat85\0\0\0\0nat86\0\0\0\0nat87\0\0\0\0" \
+ "nat88\0\0\0\0nat89\0\0\0\0nat90\0\0\0\0nat91\0\0\0\0" \
+ "nat92\0\0\0\0nat93\0\0\0\0nat94\0\0\0\0nat95\0\0\0\0" \
+ "nat96\0\0\0\0nat97\0\0\0\0nat98\0\0\0\0nat99\0\0\0\0" \
+ "nat100\0\0\0nat101\0\0\0nat102\0\0\0nat103\0\0\0" \
+ "nat104\0\0\0nat105\0\0\0nat106\0\0\0nat107\0\0\0" \
+ "nat108\0\0\0nat109\0\0\0nat110\0\0\0nat111\0\0\0" \
+ "nat112\0\0\0nat113\0\0\0nat114\0\0\0nat115\0\0\0" \
+ "nat116\0\0\0nat117\0\0\0nat118\0\0\0nat119\0\0\0" \
+ "nat120\0\0\0nat121\0\0\0nat122\0\0\0nat123\0\0\0" \
+ "nat124\0\0\0nat125\0\0\0nat126\0\0\0nat127\0\0\0" \
+ "f0\0\0\0\0\0\0\0f1\0\0\0\0\0\0\0f2\0\0\0\0\0\0\0f3\0\0\0\0\0\0\0" \
+ "f4\0\0\0\0\0\0\0f5\0\0\0\0\0\0\0f6\0\0\0\0\0\0\0f7\0\0\0\0\0\0\0" \
+ "f8\0\0\0\0\0\0\0f9\0\0\0\0\0\0\0f10\0\0\0\0\0\0f11\0\0\0\0\0\0" \
+ "f12\0\0\0\0\0\0f13\0\0\0\0\0\0f14\0\0\0\0\0\0f15\0\0\0\0\0\0" \
+ "f16\0\0\0\0\0\0f17\0\0\0\0\0\0f18\0\0\0\0\0\0f19\0\0\0\0\0\0" \
+ "f20\0\0\0\0\0\0f21\0\0\0\0\0\0f22\0\0\0\0\0\0f23\0\0\0\0\0\0" \
+ "f24\0\0\0\0\0\0f25\0\0\0\0\0\0f26\0\0\0\0\0\0f27\0\0\0\0\0\0" \
+ "f28\0\0\0\0\0\0f29\0\0\0\0\0\0f30\0\0\0\0\0\0f31\0\0\0\0\0\0" \
+ "f32\0\0\0\0\0\0f33\0\0\0\0\0\0f34\0\0\0\0\0\0f35\0\0\0\0\0\0" \
+ "f36\0\0\0\0\0\0f37\0\0\0\0\0\0f38\0\0\0\0\0\0f39\0\0\0\0\0\0" \
+ "f40\0\0\0\0\0\0f41\0\0\0\0\0\0f42\0\0\0\0\0\0f43\0\0\0\0\0\0" \
+ "f44\0\0\0\0\0\0f45\0\0\0\0\0\0f46\0\0\0\0\0\0f47\0\0\0\0\0\0" \
+ "f48\0\0\0\0\0\0f49\0\0\0\0\0\0f50\0\0\0\0\0\0f51\0\0\0\0\0\0" \
+ "f52\0\0\0\0\0\0f53\0\0\0\0\0\0f54\0\0\0\0\0\0f55\0\0\0\0\0\0" \
+ "f56\0\0\0\0\0\0f57\0\0\0\0\0\0f58\0\0\0\0\0\0f59\0\0\0\0\0\0" \
+ "f60\0\0\0\0\0\0f61\0\0\0\0\0\0f62\0\0\0\0\0\0f63\0\0\0\0\0\0" \
+ "f64\0\0\0\0\0\0f65\0\0\0\0\0\0f66\0\0\0\0\0\0f67\0\0\0\0\0\0" \
+ "f68\0\0\0\0\0\0f69\0\0\0\0\0\0f70\0\0\0\0\0\0f71\0\0\0\0\0\0" \
+ "f72\0\0\0\0\0\0f73\0\0\0\0\0\0f74\0\0\0\0\0\0f75\0\0\0\0\0\0" \
+ "f76\0\0\0\0\0\0f77\0\0\0\0\0\0f78\0\0\0\0\0\0f79\0\0\0\0\0\0" \
+ "f80\0\0\0\0\0\0f81\0\0\0\0\0\0f82\0\0\0\0\0\0f83\0\0\0\0\0\0" \
+ "f84\0\0\0\0\0\0f85\0\0\0\0\0\0f86\0\0\0\0\0\0f87\0\0\0\0\0\0" \
+ "f88\0\0\0\0\0\0f89\0\0\0\0\0\0f90\0\0\0\0\0\0f91\0\0\0\0\0\0" \
+ "f92\0\0\0\0\0\0f93\0\0\0\0\0\0f94\0\0\0\0\0\0f95\0\0\0\0\0\0" \
+ "f96\0\0\0\0\0\0f97\0\0\0\0\0\0f98\0\0\0\0\0\0f99\0\0\0\0\0\0" \
+ "f100\0\0\0\0\0f101\0\0\0\0\0f102\0\0\0\0\0f103\0\0\0\0\0" \
+ "f104\0\0\0\0\0f105\0\0\0\0\0f106\0\0\0\0\0f107\0\0\0\0\0" \
+ "f108\0\0\0\0\0f109\0\0\0\0\0f110\0\0\0\0\0f111\0\0\0\0\0" \
+ "f112\0\0\0\0\0f113\0\0\0\0\0f114\0\0\0\0\0f115\0\0\0\0\0" \
+ "f116\0\0\0\0\0f117\0\0\0\0\0f118\0\0\0\0\0f119\0\0\0\0\0" \
+ "f120\0\0\0\0\0f121\0\0\0\0\0f122\0\0\0\0\0f123\0\0\0\0\0" \
+ "f124\0\0\0\0\0f125\0\0\0\0\0f126\0\0\0\0\0f127\0\0\0\0\0" \
+ "ar0\0\0\0\0\0\0ar1\0\0\0\0\0\0ar2\0\0\0\0\0\0ar3\0\0\0\0\0\0" \
+ "ar4\0\0\0\0\0\0ar5\0\0\0\0\0\0ar6\0\0\0\0\0\0ar7\0\0\0\0\0\0" \
+ "ar8\0\0\0\0\0\0ar9\0\0\0\0\0\0ar10\0\0\0\0\0ar11\0\0\0\0\0" \
+ "ar12\0\0\0\0\0ar13\0\0\0\0\0ar14\0\0\0\0\0ar15\0\0\0\0\0" \
+ "rsc\0\0\0\0\0\0bsp\0\0\0\0\0\0bspstore\0rnat\0\0\0\0\0" \
+ "ar20\0\0\0\0\0ar21\0\0\0\0\0ar22\0\0\0\0\0ar23\0\0\0\0\0" \
+ "ar24\0\0\0\0\0ar25\0\0\0\0\0ar26\0\0\0\0\0ar27\0\0\0\0\0" \
+ "ar28\0\0\0\0\0ar29\0\0\0\0\0ar30\0\0\0\0\0ar31\0\0\0\0\0" \
+ "ccv\0\0\0\0\0\0ar33\0\0\0\0\0ar34\0\0\0\0\0ar35\0\0\0\0\0" \
+ "unat\0\0\0\0\0ar37\0\0\0\0\0ar38\0\0\0\0\0ar39\0\0\0\0\0" \
+ "fpsr\0\0\0\0\0ar41\0\0\0\0\0ar42\0\0\0\0\0ar43\0\0\0\0\0" \
+ "ar44\0\0\0\0\0ar45\0\0\0\0\0ar46\0\0\0\0\0ar47\0\0\0\0\0" \
+ "ar48\0\0\0\0\0ar49\0\0\0\0\0ar50\0\0\0\0\0ar51\0\0\0\0\0" \
+ "ar52\0\0\0\0\0ar53\0\0\0\0\0ar54\0\0\0\0\0ar55\0\0\0\0\0" \
+ "ar56\0\0\0\0\0ar57\0\0\0\0\0ar58\0\0\0\0\0ar59\0\0\0\0\0" \
+ "ar60\0\0\0\0\0ar61\0\0\0\0\0ar62\0\0\0\0\0ar63\0\0\0\0\0" \
+ "pfs\0\0\0\0\0\0lc\0\0\0\0\0\0\0ec\0\0\0\0\0\0\0ar67\0\0\0\0\0" \
+ "ar68\0\0\0\0\0ar69\0\0\0\0\0ar70\0\0\0\0\0ar71\0\0\0\0\0" \
+ "ar72\0\0\0\0\0ar73\0\0\0\0\0ar74\0\0\0\0\0ar75\0\0\0\0\0" \
+ "ar76\0\0\0\0\0ar77\0\0\0\0\0ar78\0\0\0\0\0ar79\0\0\0\0\0" \
+ "ar80\0\0\0\0\0ar81\0\0\0\0\0ar82\0\0\0\0\0ar83\0\0\0\0\0" \
+ "ar84\0\0\0\0\0ar85\0\0\0\0\0ar86\0\0\0\0\0ar87\0\0\0\0\0" \
+ "ar88\0\0\0\0\0ar89\0\0\0\0\0ar90\0\0\0\0\0ar91\0\0\0\0\0" \
+ "ar92\0\0\0\0\0ar93\0\0\0\0\0ar94\0\0\0\0\0ar95\0\0\0\0\0" \
+ "ar96\0\0\0\0\0ar97\0\0\0\0\0ar98\0\0\0\0\0ar99\0\0\0\0\0" \
+ "ar100\0\0\0\0ar101\0\0\0\0ar102\0\0\0\0ar103\0\0\0\0" \
+ "ar104\0\0\0\0ar105\0\0\0\0ar106\0\0\0\0ar107\0\0\0\0" \
+ "ar108\0\0\0\0ar109\0\0\0\0ar110\0\0\0\0ar111\0\0\0\0" \
+ "ar112\0\0\0\0ar113\0\0\0\0ar114\0\0\0\0ar115\0\0\0\0" \
+ "ar116\0\0\0\0ar117\0\0\0\0ar118\0\0\0\0ar119\0\0\0\0" \
+ "ar120\0\0\0\0ar121\0\0\0\0ar122\0\0\0\0ar123\0\0\0\0" \
+ "ar124\0\0\0\0ar125\0\0\0\0ar126\0\0\0\0ar127\0\0\0\0" \
+ "rp\0\0\0\0\0\0\0b1\0\0\0\0\0\0\0b2\0\0\0\0\0\0\0b3\0\0\0\0\0\0\0" \
+ "b4\0\0\0\0\0\0\0b5\0\0\0\0\0\0\0b6\0\0\0\0\0\0\0b7\0\0\0\0\0\0\0" \
+ "pr\0\0\0\0\0\0\0cfm\0\0\0\0\0\0bsp\0\0\0\0\0\0ip\0\0\0\0\0\0\0" \
+ "sp\0\0\0\0\0\0\0"
+
+#define NREGS ((int) (sizeof (regname_str) - 1) / regname_len)
+
+const char *
+unw_regname (unw_regnum_t reg)
+{
+ if (reg < NREGS)
+ return regname_str + reg * regname_len;
+ else
+ return "???";
+}
diff --git a/src/pal/src/libunwind/src/ia64/regs.h b/src/pal/src/libunwind/src/ia64/regs.h
new file mode 100644
index 0000000000..a22a818776
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/regs.h
@@ -0,0 +1,73 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+/* Apply rotation to a general register. REG must be in the range 0-127. */
+
+static inline int
+rotate_gr (struct cursor *c, int reg)
+{
+ unsigned int rrb_gr, sor;
+ int preg;
+
+ sor = 8 * ((c->cfm >> 14) & 0xf);
+ rrb_gr = (c->cfm >> 18) & 0x7f;
+
+ if ((unsigned) (reg - 32) >= sor)
+ preg = reg;
+ else
+ {
+ preg = reg + rrb_gr; /* apply rotation */
+ if ((unsigned) (preg - 32) >= sor)
+ preg -= sor; /* wrap around */
+ }
+ if (sor)
+ Debug (15, "sor=%u rrb.gr=%u, r%d -> r%d\n", sor, rrb_gr, reg, preg);
+ return preg;
+}
+
+/* Apply rotation to a floating-point register. The number REG must
+ be in the range of 0-127. */
+
+static inline int
+rotate_fr (struct cursor *c, int reg)
+{
+ unsigned int rrb_fr;
+ int preg;
+
+ rrb_fr = (c->cfm >> 25) & 0x7f;
+ if (reg < 32)
+ preg = reg; /* register not part of the rotating partition */
+ else
+ {
+ preg = reg + rrb_fr; /* apply rotation */
+ if (preg > 127)
+ preg -= 96; /* wrap around */
+ }
+ if (rrb_fr)
+ Debug (15, "rrb.fr=%u, f%d -> f%d\n", rrb_fr, reg, preg);
+ return preg;
+}
diff --git a/src/pal/src/libunwind/src/ia64/setjmp.S b/src/pal/src/libunwind/src/ia64/setjmp.S
new file mode 100644
index 0000000000..384615b840
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/setjmp.S
@@ -0,0 +1,51 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "jmpbuf.h"
+
+ .align 32
+
+ .global _setjmp
+
+ .proc _setjmp
+
+_setjmp:
+ mov r2 = ar.bsp
+ st8 [r32] = r12 // jmp_buf[JB_SP] = sp
+ mov r3 = rp
+
+ adds r16 = JB_RP*8, r32
+ adds r17 = JB_BSP*8, r32
+ mov r8 = 0
+ ;;
+ st8 [r16] = r3 // jmp_buf[JB_RP] = rp
+ st8 [r17] = r2 // jmp_buf[JB_BSP] = bsp
+ br.ret.sptk.many rp
+
+ .endp _setjmp
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/siglongjmp.S b/src/pal/src/libunwind/src/ia64/siglongjmp.S
new file mode 100644
index 0000000000..d77b43753b
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/siglongjmp.S
@@ -0,0 +1,69 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#define SIG_SETMASK 2
+
+ .global _UI_siglongjmp_cont
+ .global sigprocmask
+
+ .align 32
+ .proc siglongjmp_continuation
+siglongjmp_continuation:
+_UI_siglongjmp_cont: // non-function label for siglongjmp.c
+ .prologue
+ .save rp, r15
+ .body
+ nop 0
+ nop 0
+ br.call.sptk.many b6 = .next
+ ;;
+ .prologue
+ .save ar.pfs, r33
+.next: alloc loc1 = ar.pfs, 0, 3, 3, 0
+ /*
+ * Note: we can use the scratch stack are because the caller
+ * of sigsetjmp() by definition is not a leaf-procedure.
+ */
+ st8 [sp] = r17 // store signal mask
+ .save rp, loc0
+ mov loc0 = r15 // final continuation point
+ ;;
+ .body
+ mov loc2 = r16 // value to return in r8
+
+ mov out0 = SIG_SETMASK
+ mov out1 = sp
+ mov out2 = r0
+ br.call.sptk.many rp = sigprocmask
+ ;;
+ mov rp = loc0
+ mov ar.pfs = loc1
+ mov r8 = loc2
+ br.ret.sptk.many rp
+ .endp siglongjmp_continuation
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/sigsetjmp.S b/src/pal/src/libunwind/src/ia64/sigsetjmp.S
new file mode 100644
index 0000000000..02f7af4b37
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/sigsetjmp.S
@@ -0,0 +1,69 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "jmpbuf.h"
+
+#define SIG_BLOCK 0
+
+ .align 32
+
+ .global __sigsetjmp
+ .global sigprocmask
+
+ .proc __sigsetjmp
+
+__sigsetjmp:
+ .prologue
+ .save ar.pfs, r35
+ alloc loc1 = ar.pfs, 2, 3, 3, 0
+ add out2 = JB_MASK*8, in0
+ .save rp, loc0
+ mov loc0 = rp
+ mov out0 = SIG_BLOCK
+ .body
+ ;;
+ cmp.ne p6, p0 = in1, r0
+ mov out1 = r0
+ mov loc2 = ar.bsp
+(p6) br.call.sptk.many rp = sigprocmask // sigjmp_buf[JB_MASK] = sigmask
+ ;;
+
+ add r16 = JB_MASK_SAVED*8, in0
+ st8 [in0] = sp, (JB_RP-JB_SP)*8 // sigjmp_buf[JB_SP] = sp
+ mov r8 = 0
+ ;;
+ st8 [in0] = loc0, (JB_BSP-JB_RP)*8 // sigjmp_buf[JB_RP] = rp
+ st8 [r16] = in1 // sigjmp_buf[JB_MASK_SAVED] = savemask
+ mov rp = loc0
+ ;;
+ st8 [in0] = loc2 // sigjmp_buf[JB_BSP] = bsp
+ mov.i ar.pfs = loc1
+ br.ret.sptk.many rp
+
+ .endp __sigsetjmp
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/src/ia64/ucontext_i.h b/src/pal/src/libunwind/src/ia64/ucontext_i.h
new file mode 100644
index 0000000000..ea32c8aaa0
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/ucontext_i.h
@@ -0,0 +1,68 @@
+/* Copyright (C) 2002 Hewlett-Packard Co.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Constants shared between setcontext() and getcontext(). Don't
+ install this header file. */
+
+#define SIG_BLOCK 0
+#define SIG_UNBLOCK 1
+#define SIG_SETMASK 2
+
+#define IA64_SC_FLAG_SYNCHRONOUS_BIT 63
+
+#define SC_FLAGS 0x000
+#define SC_NAT 0x008
+#define SC_BSP 0x048
+#define SC_RNAT 0x050
+#define SC_UNAT 0x060
+#define SC_FPSR 0x068
+#define SC_PFS 0x070
+#define SC_LC 0x078
+#define SC_PR 0x080
+#define SC_BR 0x088
+#define SC_GR 0x0c8
+#define SC_FR 0x1d0
+#define SC_MASK 0x9d0
+
+
+#define rTMP r10
+#define rPOS r11
+#define rCPOS r14
+#define rNAT r15
+#define rFLAGS r16
+
+#define rB5 r18
+#define rB4 r19
+#define rB3 r20
+#define rB2 r21
+#define rB1 r22
+#define rB0 r23
+#define rRSC r24
+#define rBSP r25
+#define rRNAT r26
+#define rUNAT r27
+#define rFPSR r28
+#define rPFS r29
+#define rLC r30
+#define rPR r31
diff --git a/src/pal/src/libunwind/src/ia64/unwind_decoder.h b/src/pal/src/libunwind/src/ia64/unwind_decoder.h
new file mode 100644
index 0000000000..7fd41740de
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/unwind_decoder.h
@@ -0,0 +1,477 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2002 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/*
+ * Generic IA-64 unwind info decoder.
+ *
+ * This file is used both by the Linux kernel and objdump. Please keep
+ * the two copies of this file in sync.
+ *
+ * You need to customize the decoder by defining the following
+ * macros/constants before including this file:
+ *
+ * Types:
+ * unw_word Unsigned integer type with at least 64 bits
+ *
+ * Register names:
+ * UNW_REG_BSP
+ * UNW_REG_BSPSTORE
+ * UNW_REG_FPSR
+ * UNW_REG_LC
+ * UNW_REG_PFS
+ * UNW_REG_PR
+ * UNW_REG_RNAT
+ * UNW_REG_PSP
+ * UNW_REG_RP
+ * UNW_REG_UNAT
+ *
+ * Decoder action macros:
+ * UNW_DEC_BAD_CODE(code)
+ * UNW_DEC_ABI(fmt,abi,context,arg)
+ * UNW_DEC_BR_GR(fmt,brmask,gr,arg)
+ * UNW_DEC_BR_MEM(fmt,brmask,arg)
+ * UNW_DEC_COPY_STATE(fmt,label,arg)
+ * UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
+ * UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
+ * UNW_DEC_FR_MEM(fmt,frmask,arg)
+ * UNW_DEC_GR_GR(fmt,grmask,gr,arg)
+ * UNW_DEC_GR_MEM(fmt,grmask,arg)
+ * UNW_DEC_LABEL_STATE(fmt,label,arg)
+ * UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
+ * UNW_DEC_MEM_STACK_V(fmt,t,arg)
+ * UNW_DEC_PRIUNAT_GR(fmt,r,arg)
+ * UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
+ * UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
+ * UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
+ * UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
+ * UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
+ * UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
+ * UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
+ * UNW_DEC_REG_REG(fmt,src,dst,arg)
+ * UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
+ * UNW_DEC_REG_WHEN(fmt,reg,t,arg)
+ * UNW_DEC_RESTORE(fmt,t,abreg,arg)
+ * UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
+ * UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
+ * UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
+ * UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
+ * UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
+ * UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
+ * UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
+ * UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
+ * UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
+ */
+
+static unw_word
+unw_decode_uleb128 (unsigned char **dpp)
+{
+ unsigned shift = 0;
+ unw_word byte, result = 0;
+ unsigned char *bp = *dpp;
+
+ while (1)
+ {
+ byte = *bp++;
+ result |= (byte & 0x7f) << shift;
+ if ((byte & 0x80) == 0)
+ break;
+ shift += 7;
+ }
+ *dpp = bp;
+ return result;
+}
+
+static unsigned char *
+unw_decode_x1 (unsigned char *dp, unsigned char code, void *arg)
+{
+ unsigned char byte1, abreg;
+ unw_word t, off;
+
+ byte1 = *dp++;
+ t = unw_decode_uleb128 (&dp);
+ off = unw_decode_uleb128 (&dp);
+ abreg = (byte1 & 0x7f);
+ if (byte1 & 0x80)
+ UNW_DEC_SPILL_SPREL(X1, t, abreg, off, arg);
+ else
+ UNW_DEC_SPILL_PSPREL(X1, t, abreg, off, arg);
+ return dp;
+}
+
+static unsigned char *
+unw_decode_x2 (unsigned char *dp, unsigned char code, void *arg)
+{
+ unsigned char byte1, byte2, abreg, x, ytreg;
+ unw_word t;
+
+ byte1 = *dp++; byte2 = *dp++;
+ t = unw_decode_uleb128 (&dp);
+ abreg = (byte1 & 0x7f);
+ ytreg = byte2;
+ x = (byte1 >> 7) & 1;
+ if ((byte1 & 0x80) == 0 && ytreg == 0)
+ UNW_DEC_RESTORE(X2, t, abreg, arg);
+ else
+ UNW_DEC_SPILL_REG(X2, t, abreg, x, ytreg, arg);
+ return dp;
+}
+
+static unsigned char *
+unw_decode_x3 (unsigned char *dp, unsigned char code, void *arg)
+{
+ unsigned char byte1, byte2, abreg, qp;
+ unw_word t, off;
+
+ byte1 = *dp++; byte2 = *dp++;
+ t = unw_decode_uleb128 (&dp);
+ off = unw_decode_uleb128 (&dp);
+
+ qp = (byte1 & 0x3f);
+ abreg = (byte2 & 0x7f);
+
+ if (byte1 & 0x80)
+ UNW_DEC_SPILL_SPREL_P(X3, qp, t, abreg, off, arg);
+ else
+ UNW_DEC_SPILL_PSPREL_P(X3, qp, t, abreg, off, arg);
+ return dp;
+}
+
+static unsigned char *
+unw_decode_x4 (unsigned char *dp, unsigned char code, void *arg)
+{
+ unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
+ unw_word t;
+
+ byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
+ t = unw_decode_uleb128 (&dp);
+
+ qp = (byte1 & 0x3f);
+ abreg = (byte2 & 0x7f);
+ x = (byte2 >> 7) & 1;
+ ytreg = byte3;
+
+ if ((byte2 & 0x80) == 0 && byte3 == 0)
+ UNW_DEC_RESTORE_P(X4, qp, t, abreg, arg);
+ else
+ UNW_DEC_SPILL_REG_P(X4, qp, t, abreg, x, ytreg, arg);
+ return dp;
+}
+
+static inline unsigned char *
+unw_decode_r1 (unsigned char *dp, unsigned char code, void *arg)
+{
+ int body = (code & 0x20) != 0;
+ unw_word rlen;
+
+ rlen = (code & 0x1f);
+ UNW_DEC_PROLOGUE(R1, body, rlen, arg);
+ return dp;
+}
+
+static inline unsigned char *
+unw_decode_r2 (unsigned char *dp, unsigned char code, void *arg)
+{
+ unsigned char byte1, mask, grsave;
+ unw_word rlen;
+
+ byte1 = *dp++;
+
+ mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
+ grsave = (byte1 & 0x7f);
+ rlen = unw_decode_uleb128 (&dp);
+ UNW_DEC_PROLOGUE_GR(R2, rlen, mask, grsave, arg);
+ return dp;
+}
+
+static inline unsigned char *
+unw_decode_r3 (unsigned char *dp, unsigned char code, void *arg)
+{
+ unw_word rlen;
+
+ rlen = unw_decode_uleb128 (&dp);
+ UNW_DEC_PROLOGUE(R3, ((code & 0x3) == 1), rlen, arg);
+ return dp;
+}
+
+static inline unsigned char *
+unw_decode_p1 (unsigned char *dp, unsigned char code, void *arg)
+{
+ unsigned char brmask = (code & 0x1f);
+
+ UNW_DEC_BR_MEM(P1, brmask, arg);
+ return dp;
+}
+
+static inline unsigned char *
+unw_decode_p2_p5 (unsigned char *dp, unsigned char code, void *arg)
+{
+ if ((code & 0x10) == 0)
+ {
+ unsigned char byte1 = *dp++;
+
+ UNW_DEC_BR_GR(P2, ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
+ (byte1 & 0x7f), arg);
+ }
+ else if ((code & 0x08) == 0)
+ {
+ unsigned char byte1 = *dp++, r, dst;
+
+ r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
+ dst = (byte1 & 0x7f);
+ switch (r)
+ {
+ case 0: UNW_DEC_REG_GR(P3, UNW_REG_PSP, dst, arg); break;
+ case 1: UNW_DEC_REG_GR(P3, UNW_REG_RP, dst, arg); break;
+ case 2: UNW_DEC_REG_GR(P3, UNW_REG_PFS, dst, arg); break;
+ case 3: UNW_DEC_REG_GR(P3, UNW_REG_PR, dst, arg); break;
+ case 4: UNW_DEC_REG_GR(P3, UNW_REG_UNAT, dst, arg); break;
+ case 5: UNW_DEC_REG_GR(P3, UNW_REG_LC, dst, arg); break;
+ case 6: UNW_DEC_RP_BR(P3, dst, arg); break;
+ case 7: UNW_DEC_REG_GR(P3, UNW_REG_RNAT, dst, arg); break;
+ case 8: UNW_DEC_REG_GR(P3, UNW_REG_BSP, dst, arg); break;
+ case 9: UNW_DEC_REG_GR(P3, UNW_REG_BSPSTORE, dst, arg); break;
+ case 10: UNW_DEC_REG_GR(P3, UNW_REG_FPSR, dst, arg); break;
+ case 11: UNW_DEC_PRIUNAT_GR(P3, dst, arg); break;
+ default: UNW_DEC_BAD_CODE(r); break;
+ }
+ }
+ else if ((code & 0x7) == 0)
+ UNW_DEC_SPILL_MASK(P4, dp, arg);
+ else if ((code & 0x7) == 1)
+ {
+ unw_word grmask, frmask, byte1, byte2, byte3;
+
+ byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
+ grmask = ((byte1 >> 4) & 0xf);
+ frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
+ UNW_DEC_FRGR_MEM(P5, grmask, frmask, arg);
+ }
+ else
+ UNW_DEC_BAD_CODE(code);
+ return dp;
+}
+
+static inline unsigned char *
+unw_decode_p6 (unsigned char *dp, unsigned char code, void *arg)
+{
+ int gregs = (code & 0x10) != 0;
+ unsigned char mask = (code & 0x0f);
+
+ if (gregs)
+ UNW_DEC_GR_MEM(P6, mask, arg);
+ else
+ UNW_DEC_FR_MEM(P6, mask, arg);
+ return dp;
+}
+
+static inline unsigned char *
+unw_decode_p7_p10 (unsigned char *dp, unsigned char code, void *arg)
+{
+ unsigned char r, byte1, byte2;
+ unw_word t, size;
+
+ if ((code & 0x10) == 0)
+ {
+ r = (code & 0xf);
+ t = unw_decode_uleb128 (&dp);
+ switch (r)
+ {
+ case 0:
+ size = unw_decode_uleb128 (&dp);
+ UNW_DEC_MEM_STACK_F(P7, t, size, arg);
+ break;
+
+ case 1: UNW_DEC_MEM_STACK_V(P7, t, arg); break;
+ case 2: UNW_DEC_SPILL_BASE(P7, t, arg); break;
+ case 3: UNW_DEC_REG_SPREL(P7, UNW_REG_PSP, t, arg); break;
+ case 4: UNW_DEC_REG_WHEN(P7, UNW_REG_RP, t, arg); break;
+ case 5: UNW_DEC_REG_PSPREL(P7, UNW_REG_RP, t, arg); break;
+ case 6: UNW_DEC_REG_WHEN(P7, UNW_REG_PFS, t, arg); break;
+ case 7: UNW_DEC_REG_PSPREL(P7, UNW_REG_PFS, t, arg); break;
+ case 8: UNW_DEC_REG_WHEN(P7, UNW_REG_PR, t, arg); break;
+ case 9: UNW_DEC_REG_PSPREL(P7, UNW_REG_PR, t, arg); break;
+ case 10: UNW_DEC_REG_WHEN(P7, UNW_REG_LC, t, arg); break;
+ case 11: UNW_DEC_REG_PSPREL(P7, UNW_REG_LC, t, arg); break;
+ case 12: UNW_DEC_REG_WHEN(P7, UNW_REG_UNAT, t, arg); break;
+ case 13: UNW_DEC_REG_PSPREL(P7, UNW_REG_UNAT, t, arg); break;
+ case 14: UNW_DEC_REG_WHEN(P7, UNW_REG_FPSR, t, arg); break;
+ case 15: UNW_DEC_REG_PSPREL(P7, UNW_REG_FPSR, t, arg); break;
+ default: UNW_DEC_BAD_CODE(r); break;
+ }
+ }
+ else
+ {
+ switch (code & 0xf)
+ {
+ case 0x0: /* p8 */
+ {
+ r = *dp++;
+ t = unw_decode_uleb128 (&dp);
+ switch (r)
+ {
+ case 1: UNW_DEC_REG_SPREL(P8, UNW_REG_RP, t, arg); break;
+ case 2: UNW_DEC_REG_SPREL(P8, UNW_REG_PFS, t, arg); break;
+ case 3: UNW_DEC_REG_SPREL(P8, UNW_REG_PR, t, arg); break;
+ case 4: UNW_DEC_REG_SPREL(P8, UNW_REG_LC, t, arg); break;
+ case 5: UNW_DEC_REG_SPREL(P8, UNW_REG_UNAT, t, arg); break;
+ case 6: UNW_DEC_REG_SPREL(P8, UNW_REG_FPSR, t, arg); break;
+ case 7: UNW_DEC_REG_WHEN(P8, UNW_REG_BSP, t, arg); break;
+ case 8: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSP, t, arg); break;
+ case 9: UNW_DEC_REG_SPREL(P8, UNW_REG_BSP, t, arg); break;
+ case 10: UNW_DEC_REG_WHEN(P8, UNW_REG_BSPSTORE, t, arg); break;
+ case 11: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
+ case 12: UNW_DEC_REG_SPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
+ case 13: UNW_DEC_REG_WHEN(P8, UNW_REG_RNAT, t, arg); break;
+ case 14: UNW_DEC_REG_PSPREL(P8, UNW_REG_RNAT, t, arg); break;
+ case 15: UNW_DEC_REG_SPREL(P8, UNW_REG_RNAT, t, arg); break;
+ case 16: UNW_DEC_PRIUNAT_WHEN_GR(P8, t, arg); break;
+ case 17: UNW_DEC_PRIUNAT_PSPREL(P8, t, arg); break;
+ case 18: UNW_DEC_PRIUNAT_SPREL(P8, t, arg); break;
+ case 19: UNW_DEC_PRIUNAT_WHEN_MEM(P8, t, arg); break;
+ default: UNW_DEC_BAD_CODE(r); break;
+ }
+ }
+ break;
+
+ case 0x1:
+ byte1 = *dp++; byte2 = *dp++;
+ UNW_DEC_GR_GR(P9, (byte1 & 0xf), (byte2 & 0x7f), arg);
+ break;
+
+ case 0xf: /* p10 */
+ byte1 = *dp++; byte2 = *dp++;
+ UNW_DEC_ABI(P10, byte1, byte2, arg);
+ break;
+
+ case 0x9:
+ return unw_decode_x1 (dp, code, arg);
+
+ case 0xa:
+ return unw_decode_x2 (dp, code, arg);
+
+ case 0xb:
+ return unw_decode_x3 (dp, code, arg);
+
+ case 0xc:
+ return unw_decode_x4 (dp, code, arg);
+
+ default:
+ UNW_DEC_BAD_CODE(code);
+ break;
+ }
+ }
+ return dp;
+}
+
+static inline unsigned char *
+unw_decode_b1 (unsigned char *dp, unsigned char code, void *arg)
+{
+ unw_word label = (code & 0x1f);
+
+ if ((code & 0x20) != 0)
+ UNW_DEC_COPY_STATE(B1, label, arg);
+ else
+ UNW_DEC_LABEL_STATE(B1, label, arg);
+ return dp;
+}
+
+static inline unsigned char *
+unw_decode_b2 (unsigned char *dp, unsigned char code, void *arg)
+{
+ unw_word t;
+
+ t = unw_decode_uleb128 (&dp);
+ UNW_DEC_EPILOGUE(B2, t, (code & 0x1f), arg);
+ return dp;
+}
+
+static inline unsigned char *
+unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg)
+{
+ unw_word t, ecount, label;
+
+ if ((code & 0x10) == 0)
+ {
+ t = unw_decode_uleb128 (&dp);
+ ecount = unw_decode_uleb128 (&dp);
+ UNW_DEC_EPILOGUE(B3, t, ecount, arg);
+ }
+ else if ((code & 0x07) == 0)
+ {
+ label = unw_decode_uleb128 (&dp);
+ if ((code & 0x08) != 0)
+ UNW_DEC_COPY_STATE(B4, label, arg);
+ else
+ UNW_DEC_LABEL_STATE(B4, label, arg);
+ }
+ else
+ switch (code & 0x7)
+ {
+ case 1: return unw_decode_x1 (dp, code, arg);
+ case 2: return unw_decode_x2 (dp, code, arg);
+ case 3: return unw_decode_x3 (dp, code, arg);
+ case 4: return unw_decode_x4 (dp, code, arg);
+ default: UNW_DEC_BAD_CODE(code); break;
+ }
+ return dp;
+}
+
+typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *);
+
+/*
+ * Decode one descriptor and return address of next descriptor.
+ */
+static inline unsigned char *
+unw_decode (unsigned char *dp, int inside_body, void *arg)
+{
+ unsigned char code, primary;
+
+ code = *dp++;
+ primary = code >> 5;
+
+ if (primary < 2)
+ dp = unw_decode_r1 (dp, code, arg);
+ else if (primary == 2)
+ dp = unw_decode_r2 (dp, code, arg);
+ else if (primary == 3)
+ dp = unw_decode_r3 (dp, code, arg);
+ else if (inside_body)
+ switch (primary)
+ {
+ case 4:
+ case 5: dp = unw_decode_b1 (dp, code, arg); break;
+ case 6: dp = unw_decode_b2 (dp, code, arg); break;
+ case 7: dp = unw_decode_b3_x4 (dp, code, arg); break;
+ }
+ else
+ switch (primary)
+ {
+ case 4: dp = unw_decode_p1 (dp, code, arg); break;
+ case 5: dp = unw_decode_p2_p5 (dp, code, arg); break;
+ case 6: dp = unw_decode_p6 (dp, code, arg); break;
+ case 7: dp = unw_decode_p7_p10 (dp, code, arg); break;
+ }
+ return dp;
+}
diff --git a/src/pal/src/libunwind/src/ia64/unwind_i.h b/src/pal/src/libunwind/src/ia64/unwind_i.h
new file mode 100644
index 0000000000..8ccbb46c93
--- /dev/null
+++ b/src/pal/src/libunwind/src/ia64/unwind_i.h
@@ -0,0 +1,633 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef unwind_i_h
+#define unwind_i_h
+
+#include <string.h>
+#include <inttypes.h>
+
+#include <libunwind-ia64.h>
+
+#include "rse.h"
+
+#include "libunwind_i.h"
+
+#define IA64_UNW_VER(x) ((x) >> 48)
+#define IA64_UNW_FLAG_MASK ((unw_word_t) 0x0000ffff00000000ULL)
+#define IA64_UNW_FLAG_OSMASK ((unw_word_t) 0x0000f00000000000ULL)
+#define IA64_UNW_FLAG_EHANDLER(x) ((x) & (unw_word_t) 0x0000000100000000ULL)
+#define IA64_UNW_FLAG_UHANDLER(x) ((x) & (unw_word_t) 0x0000000200000000ULL)
+#define IA64_UNW_LENGTH(x) ((x) & (unw_word_t) 0x00000000ffffffffULL)
+
+#ifdef MIN
+# undef MIN
+#endif
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+#if !defined(HAVE_SYS_UC_ACCESS_H) && !defined(UNW_REMOTE_ONLY)
+
+static ALWAYS_INLINE void *
+inlined_uc_addr (ucontext_t *uc, int reg, uint8_t *nat_bitnr)
+{
+ unw_word_t reg_addr;
+ void *addr;
+
+ switch (reg)
+ {
+ case UNW_IA64_GR + 0: addr = &unw.read_only.r0; break;
+ case UNW_IA64_NAT + 0: addr = &unw.read_only.r0; break;
+ case UNW_IA64_FR + 0: addr = &unw.read_only.f0; break;
+ case UNW_IA64_FR + 1:
+ if (__BYTE_ORDER == __BIG_ENDIAN)
+ addr = &unw.read_only.f1_be;
+ else
+ addr = &unw.read_only.f1_le;
+ break;
+ case UNW_IA64_IP: addr = &uc->uc_mcontext.sc_br[0]; break;
+ case UNW_IA64_CFM: addr = &uc->uc_mcontext.sc_ar_pfs; break;
+ case UNW_IA64_AR_RNAT: addr = &uc->uc_mcontext.sc_ar_rnat; break;
+ case UNW_IA64_AR_UNAT: addr = &uc->uc_mcontext.sc_ar_unat; break;
+ case UNW_IA64_AR_LC: addr = &uc->uc_mcontext.sc_ar_lc; break;
+ case UNW_IA64_AR_FPSR: addr = &uc->uc_mcontext.sc_ar_fpsr; break;
+ case UNW_IA64_PR: addr = &uc->uc_mcontext.sc_pr; break;
+ case UNW_IA64_AR_BSPSTORE: addr = &uc->uc_mcontext.sc_ar_bsp; break;
+
+ case UNW_IA64_GR + 4 ... UNW_IA64_GR + 7:
+ case UNW_IA64_GR + 12:
+ addr = &uc->uc_mcontext.sc_gr[reg - UNW_IA64_GR];
+ break;
+
+ case UNW_IA64_NAT + 4 ... UNW_IA64_NAT + 7:
+ case UNW_IA64_NAT + 12:
+ addr = &uc->uc_mcontext.sc_nat;
+ reg_addr = (unw_word_t) &uc->uc_mcontext.sc_gr[reg - UNW_IA64_NAT];
+ *nat_bitnr = reg - UNW_IA64_NAT;
+ break;
+
+ case UNW_IA64_BR + 1 ... UNW_IA64_BR + 5:
+ addr = &uc->uc_mcontext.sc_br[reg - UNW_IA64_BR];
+ break;
+
+ case UNW_IA64_FR+ 2 ... UNW_IA64_FR+ 5:
+ case UNW_IA64_FR+16 ... UNW_IA64_FR+31:
+ addr = &uc->uc_mcontext.sc_fr[reg - UNW_IA64_FR];
+ break;
+
+ default:
+ addr = NULL;
+ }
+ return addr;
+}
+
+static inline void *
+uc_addr (ucontext_t *uc, int reg, uint8_t *nat_bitnr)
+{
+ if (__builtin_constant_p (reg))
+ return inlined_uc_addr (uc, reg, nat_bitnr);
+ else
+ return tdep_uc_addr (uc, reg, nat_bitnr);
+}
+
+/* Return TRUE if ADDR points inside unw.read_only_reg. */
+
+static inline long
+ia64_read_only_reg (void *addr)
+{
+ return ((unsigned long) ((char *) addr - (char *) &unw.read_only)
+ < sizeof (unw.read_only));
+}
+
+#endif /* !defined(HAVE_SYS_UC_ACCESS_H) && !defined(UNW_REMOTE_ONLY) */
+
+/* Bits 0 and 1 of a location are used to encode its type:
+ bit 0: set if location uses floating-point format.
+ bit 1: set if location is a NaT bit on memory stack. */
+
+#define IA64_LOC_TYPE_FP (1 << 0)
+#define IA64_LOC_TYPE_MEMSTK_NAT (1 << 1)
+
+#ifdef UNW_LOCAL_ONLY
+#define IA64_LOC_REG(r,t) (((r) << 2) | (t))
+#define IA64_LOC_ADDR(a,t) (((a) & ~0x3) | (t))
+#define IA64_LOC_UC_ADDR(a,t) IA64_LOC_ADDR(a, t)
+#define IA64_NULL_LOC (0)
+
+#define IA64_GET_REG(l) ((l) >> 2)
+#define IA64_GET_ADDR(l) ((l) & ~0x3)
+#define IA64_IS_NULL_LOC(l) ((l) == 0)
+#define IA64_IS_FP_LOC(l) (((l) & IA64_LOC_TYPE_FP) != 0)
+#define IA64_IS_MEMSTK_NAT(l) (((l) & IA64_LOC_TYPE_MEMSTK_NAT) != 0)
+#define IA64_IS_REG_LOC(l) 0
+#define IA64_IS_UC_LOC(l) 0
+
+#define IA64_REG_LOC(c,r) ((unw_word_t) uc_addr((c)->as_arg, r, NULL))
+#define IA64_REG_NAT_LOC(c,r,n) ((unw_word_t) uc_addr((c)->as_arg, r, n))
+#define IA64_FPREG_LOC(c,r) \
+ ((unw_word_t) uc_addr((c)->as_arg, (r), NULL) | IA64_LOC_TYPE_FP)
+
+# define ia64_find_proc_info(c,ip,n) \
+ tdep_find_proc_info(unw_local_addr_space, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define ia64_put_unwind_info(c, pi) do { ; } while (0)
+
+/* Note: the register accessors (ia64_{get,set}{,fp}()) must check for
+ NULL locations because uc_addr() returns NULL for unsaved
+ registers. */
+
+static inline int
+ia64_getfp (struct cursor *c, unw_word_t loc, unw_fpreg_t *val)
+{
+ if (IA64_IS_NULL_LOC (loc))
+ {
+ Debug (16, "access to unsaved register\n");
+ return -UNW_EBADREG;
+ }
+ *val = *(unw_fpreg_t *) IA64_GET_ADDR (loc);
+ return 0;
+}
+
+static inline int
+ia64_putfp (struct cursor *c, unw_word_t loc, unw_fpreg_t val)
+{
+ unw_fpreg_t *addr = (unw_fpreg_t *) IA64_GET_ADDR (loc);
+
+ if (IA64_IS_NULL_LOC (loc))
+ {
+ Debug (16, "access to unsaved register\n");
+ return -UNW_EBADREG;
+ }
+ else if (ia64_read_only_reg (addr))
+ {
+ Debug (16, "attempt to read-only register\n");
+ return -UNW_EREADONLYREG;
+ }
+ *addr = val;
+ return 0;
+}
+
+static inline int
+ia64_get (struct cursor *c, unw_word_t loc, unw_word_t *val)
+{
+ if (IA64_IS_NULL_LOC (loc))
+ {
+ Debug (16, "access to unsaved register\n");
+ return -UNW_EBADREG;
+ }
+ *val = *(unw_word_t *) IA64_GET_ADDR (loc);
+ return 0;
+}
+
+static inline int
+ia64_put (struct cursor *c, unw_word_t loc, unw_word_t val)
+{
+ unw_word_t *addr = (unw_word_t *) IA64_GET_ADDR (loc);
+
+ if (IA64_IS_NULL_LOC (loc))
+ {
+ Debug (16, "access to unsaved register\n");
+ return -UNW_EBADREG;
+ }
+ else if (ia64_read_only_reg (addr))
+ {
+ Debug (16, "attempt to read-only register\n");
+ return -UNW_EREADONLYREG;
+ }
+ *addr = val;
+ return 0;
+}
+
+#else /* !UNW_LOCAL_ONLY */
+
+/* Bits 0 and 1 of the second word (w1) of a location are used
+ to further distinguish what location we're dealing with:
+
+ bit 0: set if the location is a register
+ bit 1: set of the location is accessed via uc_access(3) */
+#define IA64_LOC_TYPE_REG (1 << 0)
+#define IA64_LOC_TYPE_UC (1 << 1)
+
+#define IA64_LOC_REG(r,t) ((ia64_loc_t) { ((r) << 2) | (t), \
+ IA64_LOC_TYPE_REG })
+#define IA64_LOC_ADDR(a,t) ((ia64_loc_t) { ((a) & ~0x3) | (t), 0 })
+#define IA64_LOC_UC_ADDR(a,t) ((ia64_loc_t) { ((a) & ~0x3) | (t), \
+ IA64_LOC_TYPE_UC })
+#define IA64_LOC_UC_REG(r,a) ((ia64_loc_t) { ((r) << 2), \
+ ((a) | IA64_LOC_TYPE_REG \
+ | IA64_LOC_TYPE_UC) })
+#define IA64_NULL_LOC ((ia64_loc_t) { 0, 0 })
+
+#define IA64_GET_REG(l) ((l).w0 >> 2)
+#define IA64_GET_ADDR(l) ((l).w0 & ~0x3)
+#define IA64_GET_AUX_ADDR(l) ((l).w1 & ~0x3)
+#define IA64_IS_NULL_LOC(l) (((l).w0 | (l).w1) == 0)
+#define IA64_IS_FP_LOC(l) (((l).w0 & IA64_LOC_TYPE_FP) != 0)
+#define IA64_IS_MEMSTK_NAT(l) (((l).w0 & IA64_LOC_TYPE_MEMSTK_NAT) != 0)
+#define IA64_IS_REG_LOC(l) (((l).w1 & IA64_LOC_TYPE_REG) != 0)
+#define IA64_IS_UC_LOC(l) (((l).w1 & IA64_LOC_TYPE_UC) != 0)
+
+#define IA64_REG_LOC(c,r) IA64_LOC_REG ((r), 0)
+#define IA64_REG_NAT_LOC(c,r,n) IA64_LOC_REG ((r), 0)
+#define IA64_FPREG_LOC(c,r) IA64_LOC_REG ((r), IA64_LOC_TYPE_FP)
+
+# define ia64_find_proc_info(c,ip,n) \
+ (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
+ (c)->as_arg)
+# define ia64_put_unwind_info(c,pi) \
+ (*(c)->as->acc.put_unwind_info)((c)->as, (pi), (c)->as_arg)
+
+#define ia64_uc_access_reg UNW_OBJ(uc_access_reg)
+#define ia64_uc_access_fpreg UNW_OBJ(uc_access_fpreg)
+
+extern int ia64_uc_access_reg (struct cursor *c, ia64_loc_t loc,
+ unw_word_t *valp, int write);
+extern int ia64_uc_access_fpreg (struct cursor *c, ia64_loc_t loc,
+ unw_fpreg_t *valp, int write);
+
+static inline int
+ia64_getfp (struct cursor *c, ia64_loc_t loc, unw_fpreg_t *val)
+{
+ unw_word_t addr;
+ int ret;
+
+ if (IA64_IS_NULL_LOC (loc))
+ {
+ Debug (16, "access to unsaved register\n");
+ return -UNW_EBADREG;
+ }
+
+ if (IA64_IS_UC_LOC (loc))
+ return ia64_uc_access_fpreg (c, loc, val, 0);
+
+ if (IA64_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, IA64_GET_REG (loc),
+ val, 0, c->as_arg);
+
+ addr = IA64_GET_ADDR (loc);
+ ret = (*c->as->acc.access_mem) (c->as, addr + 0, &val->raw.bits[0], 0,
+ c->as_arg);
+ if (ret < 0)
+ return ret;
+
+ return (*c->as->acc.access_mem) (c->as, addr + 8, &val->raw.bits[1], 0,
+ c->as_arg);
+}
+
+static inline int
+ia64_putfp (struct cursor *c, ia64_loc_t loc, unw_fpreg_t val)
+{
+ unw_word_t addr;
+ int ret;
+
+ if (IA64_IS_NULL_LOC (loc))
+ {
+ Debug (16, "access to unsaved register\n");
+ return -UNW_EBADREG;
+ }
+
+ if (IA64_IS_UC_LOC (loc))
+ return ia64_uc_access_fpreg (c, loc, &val, 1);
+
+ if (IA64_IS_REG_LOC (loc))
+ return (*c->as->acc.access_fpreg) (c->as, IA64_GET_REG (loc), &val, 1,
+ c->as_arg);
+
+ addr = IA64_GET_ADDR (loc);
+ ret = (*c->as->acc.access_mem) (c->as, addr + 0, &val.raw.bits[0], 1,
+ c->as_arg);
+ if (ret < 0)
+ return ret;
+
+ return (*c->as->acc.access_mem) (c->as, addr + 8, &val.raw.bits[1], 1,
+ c->as_arg);
+}
+
+/* Get the 64 data bits from location LOC. If bit 0 is cleared, LOC
+ is a memory address, otherwise it is a register number. If the
+ register is a floating-point register, the 64 bits are read from
+ the significand bits. */
+
+static inline int
+ia64_get (struct cursor *c, ia64_loc_t loc, unw_word_t *val)
+{
+ if (IA64_IS_NULL_LOC (loc))
+ {
+ Debug (16, "access to unsaved register\n");
+ return -UNW_EBADREG;
+ }
+
+ if (IA64_IS_FP_LOC (loc))
+ {
+ unw_fpreg_t tmp;
+ int ret;
+
+ ret = ia64_getfp (c, loc, &tmp);
+ if (ret < 0)
+ return ret;
+
+ if (c->as->big_endian)
+ *val = tmp.raw.bits[1];
+ else
+ *val = tmp.raw.bits[0];
+ return 0;
+ }
+
+ if (IA64_IS_UC_LOC (loc))
+ return ia64_uc_access_reg (c, loc, val, 0);
+
+ if (IA64_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg)(c->as, IA64_GET_REG (loc), val, 0,
+ c->as_arg);
+ else
+ return (*c->as->acc.access_mem)(c->as, IA64_GET_ADDR (loc), val, 0,
+ c->as_arg);
+}
+
+static inline int
+ia64_put (struct cursor *c, ia64_loc_t loc, unw_word_t val)
+{
+ if (IA64_IS_NULL_LOC (loc))
+ {
+ Debug (16, "access to unsaved register\n");
+ return -UNW_EBADREG;
+ }
+
+ if (IA64_IS_FP_LOC (loc))
+ {
+ unw_fpreg_t tmp;
+
+ memset (&tmp, 0, sizeof (tmp));
+ if (c->as->big_endian)
+ tmp.raw.bits[1] = val;
+ else
+ tmp.raw.bits[0] = val;
+ return ia64_putfp (c, loc, tmp);
+ }
+
+ if (IA64_IS_UC_LOC (loc))
+ return ia64_uc_access_reg (c, loc, &val, 1);
+
+ if (IA64_IS_REG_LOC (loc))
+ return (*c->as->acc.access_reg)(c->as, IA64_GET_REG (loc), &val, 1,
+ c->as_arg);
+ else
+ return (*c->as->acc.access_mem)(c->as, IA64_GET_ADDR (loc), &val, 1,
+ c->as_arg);
+}
+
+#endif /* !UNW_LOCAL_ONLY */
+
+struct ia64_unwind_block
+ {
+ unw_word_t header;
+ unw_word_t desc[0]; /* unwind descriptors */
+
+ /* Personality routine and language-specific data follow behind
+ descriptors. */
+ };
+
+enum ia64_where
+ {
+ IA64_WHERE_NONE, /* register isn't saved at all */
+ IA64_WHERE_GR, /* register is saved in a general register */
+ IA64_WHERE_FR, /* register is saved in a floating-point register */
+ IA64_WHERE_BR, /* register is saved in a branch register */
+ IA64_WHERE_SPREL, /* register is saved on memstack (sp-relative) */
+ IA64_WHERE_PSPREL, /* register is saved on memstack (psp-relative) */
+
+ /* At the end of each prologue these locations get resolved to
+ IA64_WHERE_PSPREL and IA64_WHERE_GR, respectively: */
+
+ IA64_WHERE_SPILL_HOME, /* register is saved in its spill home */
+ IA64_WHERE_GR_SAVE /* register is saved in next general register */
+ };
+
+#define IA64_WHEN_NEVER 0x7fffffff
+
+struct ia64_reg_info
+ {
+ unw_word_t val; /* save location: register number or offset */
+ enum ia64_where where; /* where the register gets saved */
+ int when; /* when the register gets saved */
+ };
+
+struct ia64_labeled_state; /* opaque structure */
+
+struct ia64_reg_state
+ {
+ struct ia64_reg_state *next; /* next (outer) element on state stack */
+ struct ia64_reg_info reg[IA64_NUM_PREGS]; /* register save locations */
+ };
+
+struct ia64_state_record
+ {
+ unsigned int first_region : 1; /* is this the first region? */
+ unsigned int done : 1; /* are we done scanning descriptors? */
+ unsigned int any_spills : 1; /* got any register spills? */
+ unsigned int in_body : 1; /* are we inside prologue or body? */
+ uint8_t *imask; /* imask of spill_mask record or NULL */
+ uint16_t abi_marker;
+
+ unw_word_t pr_val; /* predicate values */
+ unw_word_t pr_mask; /* predicate mask */
+
+ long spill_offset; /* psp-relative offset for spill base */
+ int region_start;
+ int region_len;
+ int when_sp_restored;
+ int epilogue_count;
+ int when_target;
+
+ uint8_t gr_save_loc; /* next save register */
+ uint8_t return_link_reg; /* branch register used as return pointer */
+
+ struct ia64_labeled_state *labeled_states;
+ struct ia64_reg_state curr;
+ };
+
+struct ia64_labeled_state
+ {
+ struct ia64_labeled_state *next; /* next label (or NULL) */
+ unsigned long label; /* label for this state */
+ struct ia64_reg_state saved_state;
+ };
+
+/* Convenience macros: */
+#define ia64_make_proc_info UNW_OBJ(make_proc_info)
+#define ia64_fetch_proc_info UNW_OBJ(fetch_proc_info)
+#define ia64_create_state_record UNW_OBJ(create_state_record)
+#define ia64_free_state_record UNW_OBJ(free_state_record)
+#define ia64_find_save_locs UNW_OBJ(find_save_locs)
+#define ia64_validate_cache UNW_OBJ(ia64_validate_cache)
+#define ia64_local_validate_cache UNW_OBJ(ia64_local_validate_cache)
+#define ia64_per_thread_cache UNW_OBJ(per_thread_cache)
+#define ia64_scratch_loc UNW_OBJ(scratch_loc)
+#define ia64_local_resume UNW_OBJ(local_resume)
+#define ia64_local_addr_space_init UNW_OBJ(local_addr_space_init)
+#define ia64_strloc UNW_OBJ(strloc)
+#define ia64_install_cursor UNW_OBJ(install_cursor)
+#define rbs_switch UNW_OBJ(rbs_switch)
+#define rbs_find_stacked UNW_OBJ(rbs_find_stacked)
+
+extern int ia64_make_proc_info (struct cursor *c);
+extern int ia64_fetch_proc_info (struct cursor *c, unw_word_t ip,
+ int need_unwind_info);
+/* The proc-info must be valid for IP before this routine can be
+ called: */
+extern int ia64_create_state_record (struct cursor *c,
+ struct ia64_state_record *sr);
+extern int ia64_free_state_record (struct ia64_state_record *sr);
+extern int ia64_find_save_locs (struct cursor *c);
+extern void ia64_validate_cache (unw_addr_space_t as, void *arg);
+extern int ia64_local_validate_cache (unw_addr_space_t as, void *arg);
+extern void ia64_local_addr_space_init (void);
+extern ia64_loc_t ia64_scratch_loc (struct cursor *c, unw_regnum_t reg,
+ uint8_t *nat_bitnr);
+
+extern NORETURN void ia64_install_cursor (struct cursor *c,
+ unw_word_t pri_unat,
+ unw_word_t *extra,
+ unw_word_t bspstore,
+ unw_word_t dirty_size,
+ unw_word_t *dirty_partition,
+ unw_word_t dirty_rnat);
+extern int ia64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
+ void *arg);
+extern int rbs_switch (struct cursor *c,
+ unw_word_t saved_bsp, unw_word_t saved_bspstore,
+ ia64_loc_t saved_rnat_loc);
+extern int rbs_find_stacked (struct cursor *c, unw_word_t regs_to_skip,
+ ia64_loc_t *locp, ia64_loc_t *rnat_locp);
+
+#ifndef UNW_REMOTE_ONLY
+# define NEED_RBS_COVER_AND_FLUSH
+# define rbs_cover_and_flush UNW_OBJ(rbs_cover_and_flush)
+ extern int rbs_cover_and_flush (struct cursor *c, unw_word_t nregs,
+ unw_word_t *dirty_partition,
+ unw_word_t *dirty_rnat,
+ unw_word_t *bspstore);
+#endif
+
+/* Warning: ia64_strloc() is for debugging only and it is NOT re-entrant! */
+extern const char *ia64_strloc (ia64_loc_t loc);
+
+/* Return true if the register-backing store is inside a ucontext_t
+ that needs to be accessed via uc_access(3). */
+
+static inline int
+rbs_on_uc (struct rbs_area *rbs)
+{
+ return IA64_IS_UC_LOC (rbs->rnat_loc) && !IA64_IS_REG_LOC (rbs->rnat_loc);
+}
+
+/* Return true if BSP points to a word that's stored on register
+ backing-store RBS. */
+static inline int
+rbs_contains (struct rbs_area *rbs, unw_word_t bsp)
+{
+ int result;
+
+ /* Caveat: this takes advantage of unsigned arithmetic. The full
+ test is (bsp >= rbs->end - rbs->size) && (bsp < rbs->end). We
+ take advantage of the fact that -n == ~n + 1. */
+ result = bsp - rbs->end > ~rbs->size;
+ Debug (16, "0x%lx in [0x%lx-0x%lx) => %d\n",
+ (long) bsp, (long) (rbs->end - rbs->size), (long) rbs->end, result);
+ return result;
+}
+
+static inline ia64_loc_t
+rbs_get_rnat_loc (struct rbs_area *rbs, unw_word_t bsp)
+{
+ unw_word_t rnat_addr = rse_rnat_addr (bsp);
+ ia64_loc_t rnat_loc;
+
+ if (rbs_contains (rbs, rnat_addr))
+ {
+ if (rbs_on_uc (rbs))
+ rnat_loc = IA64_LOC_UC_ADDR (rnat_addr, 0);
+ else
+ rnat_loc = IA64_LOC_ADDR (rnat_addr, 0);
+ }
+ else
+ rnat_loc = rbs->rnat_loc;
+ return rnat_loc;
+}
+
+static inline ia64_loc_t
+rbs_loc (struct rbs_area *rbs, unw_word_t bsp)
+{
+ if (rbs_on_uc (rbs))
+ return IA64_LOC_UC_ADDR (bsp, 0);
+ else
+ return IA64_LOC_ADDR (bsp, 0);
+}
+
+static inline int
+ia64_get_stacked (struct cursor *c, unw_word_t reg,
+ ia64_loc_t *locp, ia64_loc_t *rnat_locp)
+{
+ struct rbs_area *rbs = c->rbs_area + c->rbs_curr;
+ unw_word_t addr, regs_to_skip = reg - 32;
+ int ret = 0;
+
+ assert (reg >= 32 && reg < 128);
+
+ addr = rse_skip_regs (c->bsp, regs_to_skip);
+ if (locp)
+ *locp = rbs_loc (rbs, addr);
+ if (rnat_locp)
+ *rnat_locp = rbs_get_rnat_loc (rbs, addr);
+
+ if (!rbs_contains (rbs, addr))
+ ret = rbs_find_stacked (c, regs_to_skip, locp, rnat_locp);
+ return ret;
+}
+
+/* The UNaT slot # calculation is identical to the one for RNaT slots,
+ but for readability/clarity, we don't want to use
+ ia64_rnat_slot_num() directly. */
+#define ia64_unat_slot_num(addr) rse_slot_num(addr)
+
+/* The following are helper macros which makes it easier for libunwind
+ to be used in the kernel. They allow the kernel to optimize away
+ any unused code without littering everything with #ifdefs. */
+#define ia64_is_big_endian(c) ((c)->as->big_endian)
+#define ia64_get_abi(c) ((c)->as->abi)
+#define ia64_set_abi(c, v) ((c)->as->abi = (v))
+#define ia64_get_abi_marker(c) ((c)->last_abi_marker)
+
+/* XXX should be in glibc: */
+#ifndef IA64_SC_FLAG_ONSTACK
+# define IA64_SC_FLAG_ONSTACK_BIT 0 /* running on signal stack? */
+# define IA64_SC_FLAG_IN_SYSCALL_BIT 1 /* did signal interrupt a syscall? */
+# define IA64_SC_FLAG_FPH_VALID_BIT 2 /* is state in f[32]-f[127] valid? */
+
+# define IA64_SC_FLAG_ONSTACK (1 << IA64_SC_FLAG_ONSTACK_BIT)
+# define IA64_SC_FLAG_IN_SYSCALL (1 << IA64_SC_FLAG_IN_SYSCALL_BIT)
+# define IA64_SC_FLAG_FPH_VALID (1 << IA64_SC_FLAG_FPH_VALID_BIT)
+#endif
+
+#endif /* unwind_i_h */
diff --git a/src/pal/src/libunwind/src/libunwind-generic.pc.in b/src/pal/src/libunwind/src/libunwind-generic.pc.in
new file mode 100644
index 0000000000..1f3baffe5b
--- /dev/null
+++ b/src/pal/src/libunwind/src/libunwind-generic.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libunwind-generic
+Description: libunwind generic library
+Version: @VERSION@
+Requires: libunwind
+Libs: -L${libdir} -lunwind-generic
+Cflags: -I${includedir}
diff --git a/src/pal/src/libunwind/src/mi/Gdestroy_addr_space.c b/src/pal/src/libunwind/src/mi/Gdestroy_addr_space.c
new file mode 100644
index 0000000000..504558e1a7
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Gdestroy_addr_space.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002, 2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+void
+unw_destroy_addr_space (unw_addr_space_t as)
+{
+#ifndef UNW_LOCAL_ONLY
+# if UNW_DEBUG
+ memset (as, 0, sizeof (*as));
+# endif
+ free (as);
+#endif
+}
diff --git a/src/pal/src/libunwind/src/mi/Gdyn-extract.c b/src/pal/src/libunwind/src/mi/Gdyn-extract.c
new file mode 100644
index 0000000000..5f7682e650
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Gdyn-extract.c
@@ -0,0 +1,64 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2002, 2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+HIDDEN int
+unwi_extract_dynamic_proc_info (unw_addr_space_t as, unw_word_t ip,
+ unw_proc_info_t *pi, unw_dyn_info_t *di,
+ int need_unwind_info, void *arg)
+{
+ pi->start_ip = di->start_ip;
+ pi->end_ip = di->end_ip;
+ pi->gp = di->gp;
+ pi->format = di->format;
+ switch (di->format)
+ {
+ case UNW_INFO_FORMAT_DYNAMIC:
+ pi->handler = di->u.pi.handler;
+ pi->lsda = 0;
+ pi->flags = di->u.pi.flags;
+ pi->unwind_info_size = 0;
+ if (need_unwind_info)
+ pi->unwind_info = di;
+ else
+ pi->unwind_info = NULL;
+ return 0;
+
+ case UNW_INFO_FORMAT_TABLE:
+ case UNW_INFO_FORMAT_REMOTE_TABLE:
+ case UNW_INFO_FORMAT_ARM_EXIDX:
+ case UNW_INFO_FORMAT_IP_OFFSET:
+#ifdef tdep_search_unwind_table
+ /* call platform-specific search routine: */
+ return tdep_search_unwind_table (as, ip, di, pi, need_unwind_info, arg);
+#else
+ /* fall through */
+#endif
+ default:
+ break;
+ }
+ return -UNW_EINVAL;
+}
diff --git a/src/pal/src/libunwind/src/mi/Gdyn-remote.c b/src/pal/src/libunwind/src/mi/Gdyn-remote.c
new file mode 100644
index 0000000000..40a5ad8b5a
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Gdyn-remote.c
@@ -0,0 +1,326 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2002, 2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+
+#include "libunwind_i.h"
+#include "remote.h"
+
+static void
+free_regions (unw_dyn_region_info_t *region)
+{
+ if (region->next)
+ free_regions (region->next);
+ free (region);
+}
+
+static int
+intern_op (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ unw_dyn_op_t *op, void *arg)
+{
+ int ret;
+
+ if ((ret = fetch8 (as, a, addr, &op->tag, arg)) < 0
+ || (ret = fetch8 (as, a, addr, &op->qp, arg)) < 0
+ || (ret = fetch16 (as, a, addr, &op->reg, arg)) < 0
+ || (ret = fetch32 (as, a, addr, &op->when, arg)) < 0
+ || (ret = fetchw (as, a, addr, &op->val, arg)) < 0)
+ return ret;
+ return 0;
+}
+
+static int
+intern_regions (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t *addr, unw_dyn_region_info_t **regionp, void *arg)
+{
+ uint32_t insn_count, op_count, i;
+ unw_dyn_region_info_t *region;
+ unw_word_t next_addr;
+ int ret;
+
+ *regionp = NULL;
+
+ if (!*addr)
+ return 0; /* NULL region-list */
+
+ if ((ret = fetchw (as, a, addr, &next_addr, arg)) < 0
+ || (ret = fetch32 (as, a, addr, (int32_t *) &insn_count, arg)) < 0
+ || (ret = fetch32 (as, a, addr, (int32_t *) &op_count, arg)) < 0)
+ return ret;
+
+ region = calloc (1, _U_dyn_region_info_size (op_count));
+ if (!region)
+ {
+ ret = -UNW_ENOMEM;
+ goto out;
+ }
+
+ region->insn_count = insn_count;
+ region->op_count = op_count;
+ for (i = 0; i < op_count; ++i)
+ if ((ret = intern_op (as, a, addr, region->op + i, arg)) < 0)
+ goto out;
+
+ if (next_addr)
+ if ((ret = intern_regions (as, a, &next_addr, &region->next, arg)) < 0)
+ goto out;
+
+ *regionp = region;
+ return 0;
+
+ out:
+ if (region)
+ free_regions (region);
+ return ret;
+}
+
+static int
+intern_array (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t *addr, unw_word_t table_len, unw_word_t **table_data,
+ void *arg)
+{
+ unw_word_t i, *data = calloc (table_len, WSIZE);
+ int ret = 0;
+
+ if (!data)
+ {
+ ret = -UNW_ENOMEM;
+ goto out;
+ }
+
+ for (i = 0; i < table_len; ++i)
+ if (fetchw (as, a, addr, data + i, arg) < 0)
+ goto out;
+
+ *table_data = data;
+ return 0;
+
+ out:
+ if (data)
+ free (data);
+ return ret;
+}
+
+static void
+free_dyn_info (unw_dyn_info_t *di)
+{
+ switch (di->format)
+ {
+ case UNW_INFO_FORMAT_DYNAMIC:
+ if (di->u.pi.regions)
+ {
+ free_regions (di->u.pi.regions);
+ di->u.pi.regions = NULL;
+ }
+ break;
+
+ case UNW_INFO_FORMAT_TABLE:
+ if (di->u.ti.table_data)
+ {
+ free (di->u.ti.table_data);
+ di->u.ti.table_data = NULL;
+ }
+ break;
+
+ case UNW_INFO_FORMAT_REMOTE_TABLE:
+ default:
+ break;
+ }
+}
+
+static int
+intern_dyn_info (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t *addr, unw_dyn_info_t *di, void *arg)
+{
+ unw_word_t first_region;
+ int ret;
+
+ switch (di->format)
+ {
+ case UNW_INFO_FORMAT_DYNAMIC:
+ if ((ret = fetchw (as, a, addr, &di->u.pi.name_ptr, arg)) < 0
+ || (ret = fetchw (as, a, addr, &di->u.pi.handler, arg)) < 0
+ || (ret = fetch32 (as, a, addr,
+ (int32_t *) &di->u.pi.flags, arg)) < 0)
+ goto out;
+ *addr += 4; /* skip over pad0 */
+ if ((ret = fetchw (as, a, addr, &first_region, arg)) < 0
+ || (ret = intern_regions (as, a, &first_region, &di->u.pi.regions,
+ arg)) < 0)
+ goto out;
+ break;
+
+ case UNW_INFO_FORMAT_TABLE:
+ if ((ret = fetchw (as, a, addr, &di->u.ti.name_ptr, arg)) < 0
+ || (ret = fetchw (as, a, addr, &di->u.ti.segbase, arg)) < 0
+ || (ret = fetchw (as, a, addr, &di->u.ti.table_len, arg)) < 0
+ || (ret = intern_array (as, a, addr, di->u.ti.table_len,
+ &di->u.ti.table_data, arg)) < 0)
+ goto out;
+ break;
+
+ case UNW_INFO_FORMAT_REMOTE_TABLE:
+ if ((ret = fetchw (as, a, addr, &di->u.rti.name_ptr, arg)) < 0
+ || (ret = fetchw (as, a, addr, &di->u.rti.segbase, arg)) < 0
+ || (ret = fetchw (as, a, addr, &di->u.rti.table_len, arg)) < 0
+ || (ret = fetchw (as, a, addr, &di->u.rti.table_data, arg)) < 0)
+ goto out;
+ break;
+
+ default:
+ ret = -UNW_ENOINFO;
+ goto out;
+ }
+ return 0;
+
+ out:
+ free_dyn_info (di);
+ return ret;
+}
+
+HIDDEN int
+unwi_dyn_remote_find_proc_info (unw_addr_space_t as, unw_word_t ip,
+ unw_proc_info_t *pi,
+ int need_unwind_info, void *arg)
+{
+ unw_accessors_t *a = unw_get_accessors_int (as);
+ unw_word_t dyn_list_addr, addr, next_addr, gen1, gen2, start_ip, end_ip;
+ unw_dyn_info_t *di = NULL;
+ int ret;
+
+ if (as->dyn_info_list_addr)
+ dyn_list_addr = as->dyn_info_list_addr;
+ else
+ {
+ if ((*a->get_dyn_info_list_addr) (as, &dyn_list_addr, arg) < 0)
+ return -UNW_ENOINFO;
+ if (as->caching_policy != UNW_CACHE_NONE)
+ as->dyn_info_list_addr = dyn_list_addr;
+ }
+
+ do
+ {
+ addr = dyn_list_addr;
+
+ ret = -UNW_ENOINFO;
+
+ if (fetchw (as, a, &addr, &gen1, arg) < 0
+ || fetchw (as, a, &addr, &next_addr, arg) < 0)
+ return ret;
+
+ for (addr = next_addr; addr != 0; addr = next_addr)
+ {
+ if (fetchw (as, a, &addr, &next_addr, arg) < 0)
+ goto recheck; /* only fail if generation # didn't change */
+
+ addr += WSIZE; /* skip over prev_addr */
+
+ if (fetchw (as, a, &addr, &start_ip, arg) < 0
+ || fetchw (as, a, &addr, &end_ip, arg) < 0)
+ goto recheck; /* only fail if generation # didn't change */
+
+ if (ip >= start_ip && ip < end_ip)
+ {
+ if (!di)
+ di = calloc (1, sizeof (*di));
+
+ di->start_ip = start_ip;
+ di->end_ip = end_ip;
+
+ if (fetchw (as, a, &addr, &di->gp, arg) < 0
+ || fetch32 (as, a, &addr, &di->format, arg) < 0)
+ goto recheck; /* only fail if generation # didn't change */
+
+ addr += 4; /* skip over padding */
+
+ if (need_unwind_info
+ && intern_dyn_info (as, a, &addr, di, arg) < 0)
+ goto recheck; /* only fail if generation # didn't change */
+
+ if (unwi_extract_dynamic_proc_info (as, ip, pi, di,
+ need_unwind_info, arg) < 0)
+ {
+ free_dyn_info (di);
+ goto recheck; /* only fail if generation # didn't change */
+ }
+ ret = 0; /* OK, found it */
+ break;
+ }
+ }
+
+ /* Re-check generation number to ensure the data we have is
+ consistent. */
+ recheck:
+ addr = dyn_list_addr;
+ if (fetchw (as, a, &addr, &gen2, arg) < 0)
+ return ret;
+ }
+ while (gen1 != gen2);
+
+ if (ret < 0 && di)
+ free (di);
+
+ return ret;
+}
+
+HIDDEN void
+unwi_dyn_remote_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi,
+ void *arg)
+{
+ if (!pi->unwind_info)
+ return;
+
+ free_dyn_info (pi->unwind_info);
+ free (pi->unwind_info);
+ pi->unwind_info = NULL;
+}
+
+/* Returns 1 if the cache is up-to-date or -1 if the cache contained
+ stale data and had to be flushed. */
+
+HIDDEN int
+unwi_dyn_validate_cache (unw_addr_space_t as, void *arg)
+{
+ unw_word_t addr, gen;
+ unw_accessors_t *a;
+
+ if (!as->dyn_info_list_addr)
+ /* If we don't have the dyn_info_list_addr, we don't have anything
+ in the cache. */
+ return 0;
+
+ a = unw_get_accessors_int (as);
+ addr = as->dyn_info_list_addr;
+
+ if (fetchw (as, a, &addr, &gen, arg) < 0)
+ return 1;
+
+ if (gen == as->dyn_generation)
+ return 1;
+
+ unw_flush_cache (as, 0, 0);
+ as->dyn_generation = gen;
+ return -1;
+}
diff --git a/src/pal/src/libunwind/src/mi/Gfind_dynamic_proc_info.c b/src/pal/src/libunwind/src/mi/Gfind_dynamic_proc_info.c
new file mode 100644
index 0000000000..98d3501286
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Gfind_dynamic_proc_info.c
@@ -0,0 +1,91 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2002, 2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+static inline int
+local_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg)
+{
+ return -UNW_ENOINFO;
+}
+
+#else /* !UNW_REMOTE_ONLY */
+
+static inline int
+local_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg)
+{
+ unw_dyn_info_list_t *list;
+ unw_dyn_info_t *di;
+
+#ifndef UNW_LOCAL_ONLY
+# pragma weak _U_dyn_info_list_addr
+ if (!_U_dyn_info_list_addr)
+ return -UNW_ENOINFO;
+#endif
+
+ list = (unw_dyn_info_list_t *) (uintptr_t) _U_dyn_info_list_addr ();
+ for (di = list->first; di; di = di->next)
+ if (ip >= di->start_ip && ip < di->end_ip)
+ return unwi_extract_dynamic_proc_info (as, ip, pi, di, need_unwind_info,
+ arg);
+ return -UNW_ENOINFO;
+}
+
+#endif /* !UNW_REMOTE_ONLY */
+
+#ifdef UNW_LOCAL_ONLY
+
+static inline int
+remote_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg)
+{
+ return -UNW_ENOINFO;
+}
+
+#else /* !UNW_LOCAL_ONLY */
+
+static inline int
+remote_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg)
+{
+ return unwi_dyn_remote_find_proc_info (as, ip, pi, need_unwind_info, arg);
+}
+
+#endif /* !UNW_LOCAL_ONLY */
+
+HIDDEN int
+unwi_find_dynamic_proc_info (unw_addr_space_t as, unw_word_t ip,
+ unw_proc_info_t *pi, int need_unwind_info,
+ void *arg)
+{
+ if (as == unw_local_addr_space)
+ return local_find_proc_info (as, ip, pi, need_unwind_info, arg);
+ else
+ return remote_find_proc_info (as, ip, pi, need_unwind_info, arg);
+}
diff --git a/src/pal/src/libunwind/src/mi/Gget_accessors.c b/src/pal/src/libunwind/src/mi/Gget_accessors.c
new file mode 100644
index 0000000000..31a6fbaf02
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Gget_accessors.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002, 2004-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+HIDDEN ALIAS(unw_get_accessors) unw_accessors_t *
+unw_get_accessors_int (unw_addr_space_t as);
+
+unw_accessors_t *
+unw_get_accessors (unw_addr_space_t as)
+{
+ if (!tdep_init_done)
+ tdep_init ();
+ return &as->acc;
+}
diff --git a/src/pal/src/libunwind/src/mi/Gget_fpreg.c b/src/pal/src/libunwind/src/mi/Gget_fpreg.c
new file mode 100644
index 0000000000..f32b128625
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Gget_fpreg.c
@@ -0,0 +1,34 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+int
+unw_get_fpreg (unw_cursor_t *cursor, int regnum, unw_fpreg_t *valp)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return tdep_access_fpreg (c, regnum, valp, 0);
+}
diff --git a/src/pal/src/libunwind/src/mi/Gget_proc_info_by_ip.c b/src/pal/src/libunwind/src/mi/Gget_proc_info_by_ip.c
new file mode 100644
index 0000000000..2697ff84e7
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Gget_proc_info_by_ip.c
@@ -0,0 +1,39 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003, 2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+int
+unw_get_proc_info_by_ip (unw_addr_space_t as, unw_word_t ip,
+ unw_proc_info_t *pi, void *as_arg)
+{
+ unw_accessors_t *a = unw_get_accessors_int (as);
+ int ret;
+
+ ret = unwi_find_dynamic_proc_info (as, ip, pi, 0, as_arg);
+ if (ret == -UNW_ENOINFO)
+ ret = (*a->find_proc_info) (as, ip, pi, 0, as_arg);
+ return ret;
+}
diff --git a/src/pal/src/libunwind/src/mi/Gget_proc_name.c b/src/pal/src/libunwind/src/mi/Gget_proc_name.c
new file mode 100644
index 0000000000..840d9007f4
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Gget_proc_name.c
@@ -0,0 +1,118 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+#include "remote.h"
+
+static inline int
+intern_string (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t addr, char *buf, size_t buf_len, void *arg)
+{
+ size_t i;
+ int ret;
+
+ for (i = 0; i < buf_len; ++i)
+ {
+ if ((ret = fetch8 (as, a, &addr, (int8_t *) buf + i, arg)) < 0)
+ return ret;
+
+ if (buf[i] == '\0')
+ return 0; /* copied full string; return success */
+ }
+ buf[buf_len - 1] = '\0'; /* ensure string is NUL terminated */
+ return -UNW_ENOMEM;
+}
+
+static inline int
+get_proc_name (unw_addr_space_t as, unw_word_t ip,
+ char *buf, size_t buf_len, unw_word_t *offp, void *arg)
+{
+ unw_accessors_t *a = unw_get_accessors_int (as);
+ unw_proc_info_t pi;
+ int ret;
+
+ buf[0] = '\0'; /* always return a valid string, even if it's empty */
+
+ ret = unwi_find_dynamic_proc_info (as, ip, &pi, 1, arg);
+ if (ret == 0)
+ {
+ unw_dyn_info_t *di = pi.unwind_info;
+
+ if (offp)
+ *offp = ip - pi.start_ip;
+
+ switch (di->format)
+ {
+ case UNW_INFO_FORMAT_DYNAMIC:
+ ret = intern_string (as, a, di->u.pi.name_ptr, buf, buf_len, arg);
+ break;
+
+ case UNW_INFO_FORMAT_TABLE:
+ case UNW_INFO_FORMAT_REMOTE_TABLE:
+ /* XXX should we create a fake name, e.g.: "tablenameN",
+ where N is the index of the function in the table??? */
+ ret = -UNW_ENOINFO;
+ break;
+
+ default:
+ ret = -UNW_EINVAL;
+ break;
+ }
+ unwi_put_dynamic_unwind_info (as, &pi, arg);
+ return ret;
+ }
+
+ if (ret != -UNW_ENOINFO)
+ return ret;
+
+ /* not a dynamic procedure, try to lookup static procedure name: */
+
+ if (a->get_proc_name)
+ return (*a->get_proc_name) (as, ip, buf, buf_len, offp, arg);
+
+ return -UNW_ENOINFO;
+}
+
+int
+unw_get_proc_name (unw_cursor_t *cursor, char *buf, size_t buf_len,
+ unw_word_t *offp)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ unw_word_t ip;
+ int error;
+
+ ip = tdep_get_ip (c);
+#if !defined(__ia64__)
+ if (c->dwarf.use_prev_instr)
+ --ip;
+#endif
+ error = get_proc_name (tdep_get_as (c), ip, buf, buf_len, offp,
+ tdep_get_as_arg (c));
+#if !defined(__ia64__)
+ if (c->dwarf.use_prev_instr && offp != NULL && error == 0)
+ *offp += 1;
+#endif
+ return error;
+}
diff --git a/src/pal/src/libunwind/src/mi/Gget_reg.c b/src/pal/src/libunwind/src/mi/Gget_reg.c
new file mode 100644
index 0000000000..9fc725c9c8
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Gget_reg.c
@@ -0,0 +1,41 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002, 2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+int
+unw_get_reg (unw_cursor_t *cursor, int regnum, unw_word_t *valp)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ // We can get the IP value directly without needing a lookup.
+ if (regnum == UNW_REG_IP)
+ {
+ *valp = tdep_get_ip (c);
+ return 0;
+ }
+
+ return tdep_access_reg (c, regnum, valp, 0);
+}
diff --git a/src/pal/src/libunwind/src/mi/Gput_dynamic_unwind_info.c b/src/pal/src/libunwind/src/mi/Gput_dynamic_unwind_info.c
new file mode 100644
index 0000000000..ca377c98a8
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Gput_dynamic_unwind_info.c
@@ -0,0 +1,55 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2002, 2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+HIDDEN void
+unwi_put_dynamic_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi,
+ void *arg)
+{
+ switch (pi->format)
+ {
+ case UNW_INFO_FORMAT_DYNAMIC:
+#ifndef UNW_LOCAL_ONLY
+# ifdef UNW_REMOTE_ONLY
+ unwi_dyn_remote_put_unwind_info (as, pi, arg);
+# else
+ if (as != unw_local_addr_space)
+ unwi_dyn_remote_put_unwind_info (as, pi, arg);
+# endif
+#endif
+ break;
+
+ case UNW_INFO_FORMAT_TABLE:
+ case UNW_INFO_FORMAT_REMOTE_TABLE:
+#ifdef tdep_put_unwind_info
+ tdep_put_unwind_info (as, pi, arg);
+ break;
+#endif
+ /* fall through */
+ default:
+ break;
+ }
+}
diff --git a/src/pal/src/libunwind/src/mi/Gset_cache_size.c b/src/pal/src/libunwind/src/mi/Gset_cache_size.c
new file mode 100644
index 0000000000..07b282e2c1
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Gset_cache_size.c
@@ -0,0 +1,72 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2014
+ Contributed by Milian Wolff <address@hidden>
+ and Dave Watson <dade.watson@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+int
+unw_set_cache_size (unw_addr_space_t as, size_t size, int flag)
+{
+ size_t power = 1;
+ unsigned short log_size = 0;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ if (flag != 0)
+ return -1;
+
+ /* Currently not supported for per-thread cache due to memory leak */
+ /* A pthread-key destructor would work, but is not signal safe */
+#if defined(HAVE___THREAD) && HAVE___THREAD
+ return -1;
+#endif
+
+ /* Round up to next power of two, slowly but portably */
+ while(power < size)
+ {
+ power *= 2;
+ log_size++;
+ /* Largest size currently supported by rs_cache */
+ if (log_size >= 15)
+ break;
+ }
+
+#if !defined(__ia64__)
+ if (log_size == as->global_cache.log_size)
+ return 0; /* no change */
+
+ as->global_cache.log_size = log_size;
+#endif
+
+ /* Ensure caches are empty (and initialized). */
+ unw_flush_cache (as, 0, 0);
+#ifdef __ia64__
+ return 0;
+#else
+ /* Synchronously purge cache, to ensure memory is allocated */
+ return dwarf_flush_rs_cache(&as->global_cache);
+#endif
+}
diff --git a/src/pal/src/libunwind/src/mi/Gset_caching_policy.c b/src/pal/src/libunwind/src/mi/Gset_caching_policy.c
new file mode 100644
index 0000000000..aa3d237146
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Gset_caching_policy.c
@@ -0,0 +1,46 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002, 2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+int
+unw_set_caching_policy (unw_addr_space_t as, unw_caching_policy_t policy)
+{
+ if (!tdep_init_done)
+ tdep_init ();
+
+#if !(defined(HAVE___THREAD) && HAVE___THREAD)
+ if (policy == UNW_CACHE_PER_THREAD)
+ policy = UNW_CACHE_GLOBAL;
+#endif
+
+ if (policy == as->caching_policy)
+ return 0; /* no change */
+
+ as->caching_policy = policy;
+ /* Ensure caches are empty (and initialized). */
+ unw_flush_cache (as, 0, 0);
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/mi/Gset_fpreg.c b/src/pal/src/libunwind/src/mi/Gset_fpreg.c
new file mode 100644
index 0000000000..8c37afd226
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Gset_fpreg.c
@@ -0,0 +1,34 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+int
+unw_set_fpreg (unw_cursor_t *cursor, int regnum, unw_fpreg_t val)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return tdep_access_fpreg (c, regnum, &val, 1);
+}
diff --git a/src/pal/src/libunwind/src/mi/Gset_reg.c b/src/pal/src/libunwind/src/mi/Gset_reg.c
new file mode 100644
index 0000000000..b1b1770337
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Gset_reg.c
@@ -0,0 +1,34 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002, 2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+int
+unw_set_reg (unw_cursor_t *cursor, int regnum, unw_word_t valp)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return tdep_access_reg (c, regnum, &valp, 1);
+}
diff --git a/src/pal/src/libunwind/src/mi/Ldestroy_addr_space.c b/src/pal/src/libunwind/src/mi/Ldestroy_addr_space.c
new file mode 100644
index 0000000000..5bf9364bc7
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Ldestroy_addr_space.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gdestroy_addr_space.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mi/Ldyn-extract.c b/src/pal/src/libunwind/src/mi/Ldyn-extract.c
new file mode 100644
index 0000000000..1802f865f7
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Ldyn-extract.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gdyn-extract.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mi/Ldyn-remote.c b/src/pal/src/libunwind/src/mi/Ldyn-remote.c
new file mode 100644
index 0000000000..260722a04b
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Ldyn-remote.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gdyn-remote.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mi/Lfind_dynamic_proc_info.c b/src/pal/src/libunwind/src/mi/Lfind_dynamic_proc_info.c
new file mode 100644
index 0000000000..bc88e1c53f
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Lfind_dynamic_proc_info.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gfind_dynamic_proc_info.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mi/Lget_accessors.c b/src/pal/src/libunwind/src/mi/Lget_accessors.c
new file mode 100644
index 0000000000..555e37f30d
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Lget_accessors.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_accessors.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mi/Lget_fpreg.c b/src/pal/src/libunwind/src/mi/Lget_fpreg.c
new file mode 100644
index 0000000000..e3be441437
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Lget_fpreg.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_fpreg.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mi/Lget_proc_info_by_ip.c b/src/pal/src/libunwind/src/mi/Lget_proc_info_by_ip.c
new file mode 100644
index 0000000000..96910d83e4
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Lget_proc_info_by_ip.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_proc_info_by_ip.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mi/Lget_proc_name.c b/src/pal/src/libunwind/src/mi/Lget_proc_name.c
new file mode 100644
index 0000000000..378097b57a
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Lget_proc_name.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_proc_name.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mi/Lget_reg.c b/src/pal/src/libunwind/src/mi/Lget_reg.c
new file mode 100644
index 0000000000..effe8a8063
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Lget_reg.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_reg.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mi/Lput_dynamic_unwind_info.c b/src/pal/src/libunwind/src/mi/Lput_dynamic_unwind_info.c
new file mode 100644
index 0000000000..99597cd5fa
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Lput_dynamic_unwind_info.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gput_dynamic_unwind_info.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mi/Lset_cache_size.c b/src/pal/src/libunwind/src/mi/Lset_cache_size.c
new file mode 100644
index 0000000000..670f64d3a9
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Lset_cache_size.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gset_cache_size.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mi/Lset_caching_policy.c b/src/pal/src/libunwind/src/mi/Lset_caching_policy.c
new file mode 100644
index 0000000000..cc18816b37
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Lset_caching_policy.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gset_caching_policy.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mi/Lset_fpreg.c b/src/pal/src/libunwind/src/mi/Lset_fpreg.c
new file mode 100644
index 0000000000..2497d404f4
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Lset_fpreg.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gset_fpreg.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mi/Lset_reg.c b/src/pal/src/libunwind/src/mi/Lset_reg.c
new file mode 100644
index 0000000000..c7a872b016
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/Lset_reg.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gset_reg.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mi/_ReadSLEB.c b/src/pal/src/libunwind/src/mi/_ReadSLEB.c
new file mode 100644
index 0000000000..c041e37a05
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/_ReadSLEB.c
@@ -0,0 +1,25 @@
+#include <libunwind.h>
+
+unw_word_t
+_ReadSLEB (unsigned char **dpp)
+{
+ unsigned shift = 0;
+ unw_word_t byte, result = 0;
+ unsigned char *bp = *dpp;
+
+ while (1)
+ {
+ byte = *bp++;
+ result |= (byte & 0x7f) << shift;
+ shift += 7;
+ if ((byte & 0x80) == 0)
+ break;
+ }
+
+ if (shift < 8 * sizeof (unw_word_t) && (byte & 0x40) != 0)
+ /* sign-extend negative value */
+ result |= ((unw_word_t) -1) << shift;
+
+ *dpp = bp;
+ return result;
+}
diff --git a/src/pal/src/libunwind/src/mi/_ReadULEB.c b/src/pal/src/libunwind/src/mi/_ReadULEB.c
new file mode 100644
index 0000000000..116f3e19bc
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/_ReadULEB.c
@@ -0,0 +1,20 @@
+#include <libunwind.h>
+
+unw_word_t
+_ReadULEB (unsigned char **dpp)
+{
+ unsigned shift = 0;
+ unw_word_t byte, result = 0;
+ unsigned char *bp = *dpp;
+
+ while (1)
+ {
+ byte = *bp++;
+ result |= (byte & 0x7f) << shift;
+ if ((byte & 0x80) == 0)
+ break;
+ shift += 7;
+ }
+ *dpp = bp;
+ return result;
+}
diff --git a/src/pal/src/libunwind/src/mi/backtrace.c b/src/pal/src/libunwind/src/mi/backtrace.c
new file mode 100644
index 0000000000..c7aa2bdcdc
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/backtrace.c
@@ -0,0 +1,81 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2002 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef UNW_REMOTE_ONLY
+
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#include <libunwind_i.h>
+#include <string.h>
+
+/* See glibc manual for a description of this function. */
+
+static ALWAYS_INLINE int
+slow_backtrace (void **buffer, int size, unw_context_t *uc)
+{
+ unw_cursor_t cursor;
+ unw_word_t ip;
+ int n = 0;
+
+ if (unlikely (unw_init_local (&cursor, uc) < 0))
+ return 0;
+
+ while (unw_step (&cursor) > 0)
+ {
+ if (n >= size)
+ return n;
+
+ if (unw_get_reg (&cursor, UNW_REG_IP, &ip) < 0)
+ return n;
+ buffer[n++] = (void *) (uintptr_t) ip;
+ }
+ return n;
+}
+
+int
+unw_backtrace (void **buffer, int size)
+{
+ unw_cursor_t cursor;
+ unw_context_t uc;
+ int n = size;
+
+ tdep_getcontext_trace (&uc);
+
+ if (unlikely (unw_init_local (&cursor, &uc) < 0))
+ return 0;
+
+ if (unlikely (tdep_trace (&cursor, buffer, &n) < 0))
+ {
+ unw_getcontext (&uc);
+ return slow_backtrace (buffer, size, &uc);
+ }
+
+ return n;
+}
+
+extern int backtrace (void **buffer, int size)
+ WEAK ALIAS(unw_backtrace);
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/mi/dyn-cancel.c b/src/pal/src/libunwind/src/mi/dyn-cancel.c
new file mode 100644
index 0000000000..9d7472d5fd
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/dyn-cancel.c
@@ -0,0 +1,46 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2002, 2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+void
+_U_dyn_cancel (unw_dyn_info_t *di)
+{
+ mutex_lock (&_U_dyn_info_list_lock);
+ {
+ ++_U_dyn_info_list.generation;
+
+ if (di->prev)
+ di->prev->next = di->next;
+ else
+ _U_dyn_info_list.first = di->next;
+
+ if (di->next)
+ di->next->prev = di->prev;
+ }
+ mutex_unlock (&_U_dyn_info_list_lock);
+
+ di->next = di->prev = NULL;
+}
diff --git a/src/pal/src/libunwind/src/mi/dyn-info-list.c b/src/pal/src/libunwind/src/mi/dyn-info-list.c
new file mode 100644
index 0000000000..1c7c55090a
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/dyn-info-list.c
@@ -0,0 +1,34 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2002, 2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+HIDDEN unw_dyn_info_list_t _U_dyn_info_list;
+
+unw_word_t
+_U_dyn_info_list_addr (void)
+{
+ return (unw_word_t) (uintptr_t) &_U_dyn_info_list;
+}
diff --git a/src/pal/src/libunwind/src/mi/dyn-register.c b/src/pal/src/libunwind/src/mi/dyn-register.c
new file mode 100644
index 0000000000..efdad3de07
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/dyn-register.c
@@ -0,0 +1,44 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2002, 2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+HIDDEN define_lock (_U_dyn_info_list_lock);
+
+void
+_U_dyn_register (unw_dyn_info_t *di)
+{
+ mutex_lock (&_U_dyn_info_list_lock);
+ {
+ ++_U_dyn_info_list.generation;
+
+ di->next = _U_dyn_info_list.first;
+ di->prev = NULL;
+ if (di->next)
+ di->next->prev = di;
+ _U_dyn_info_list.first = di;
+ }
+ mutex_unlock (&_U_dyn_info_list_lock);
+}
diff --git a/src/pal/src/libunwind/src/mi/flush_cache.c b/src/pal/src/libunwind/src/mi/flush_cache.c
new file mode 100644
index 0000000000..cbd93e1a11
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/flush_cache.c
@@ -0,0 +1,59 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+void
+unw_flush_cache (unw_addr_space_t as, unw_word_t lo, unw_word_t hi)
+{
+#if !UNW_TARGET_IA64
+ struct unw_debug_frame_list *w = as->debug_frames;
+#endif
+
+ /* clear dyn_info_list_addr cache: */
+ as->dyn_info_list_addr = 0;
+
+#if !UNW_TARGET_IA64
+ for (; w; w = w->next)
+ {
+ if (w->index)
+ free (w->index);
+ free (w->debug_frame);
+ }
+ as->debug_frames = NULL;
+#endif
+
+ /* This lets us flush caches lazily. The implementation currently
+ ignores the flush range arguments (lo-hi). This is OK because
+ unw_flush_cache() is allowed to flush more than the requested
+ range. */
+
+#ifdef HAVE_FETCH_AND_ADD
+ fetch_and_add1 (&as->cache_generation);
+#else
+# warning unw_flush_cache(): need a way to atomically increment an integer.
+ ++as->cache_generation;
+#endif
+}
diff --git a/src/pal/src/libunwind/src/mi/init.c b/src/pal/src/libunwind/src/mi/init.c
new file mode 100644
index 0000000000..60a48c5892
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/init.c
@@ -0,0 +1,60 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+HIDDEN intrmask_t unwi_full_mask;
+
+static const char rcsid[] UNUSED =
+ "$Id: " PACKAGE_STRING " --- report bugs to " PACKAGE_BUGREPORT " $";
+
+#if UNW_DEBUG
+
+/* Must not be declared HIDDEN because libunwind.so and
+ libunwind-PLATFORM.so will both define their own copies of this
+ variable and we want to use only one or the other when both
+ libraries are loaded. */
+long unwi_debug_level;
+
+#endif /* UNW_DEBUG */
+
+HIDDEN void
+mi_init (void)
+{
+#if UNW_DEBUG
+ const char *str = getenv ("UNW_DEBUG_LEVEL");
+
+ if (str)
+ unwi_debug_level = atoi (str);
+
+ if (unwi_debug_level > 0)
+ {
+ setbuf (stdout, NULL);
+ setbuf (stderr, NULL);
+ }
+#endif
+
+ assert (sizeof (struct cursor) <= sizeof (unw_cursor_t));
+}
diff --git a/src/pal/src/libunwind/src/mi/mempool.c b/src/pal/src/libunwind/src/mi/mempool.c
new file mode 100644
index 0000000000..536b64e815
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/mempool.c
@@ -0,0 +1,184 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2003, 2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+/* From GCC docs: ``Gcc also provides a target specific macro
+ * __BIGGEST_ALIGNMENT__, which is the largest alignment ever used for any data
+ * type on the target machine you are compiling for.'' */
+#ifdef __BIGGEST_ALIGNMENT__
+# define MAX_ALIGN __BIGGEST_ALIGNMENT__
+#else
+/* Crude hack to check that MAX_ALIGN is power-of-two.
+ * sizeof(long double) = 12 on i386. */
+# define MAX_ALIGN_(n) (n < 8 ? 8 : \
+ n < 16 ? 16 : n)
+# define MAX_ALIGN MAX_ALIGN_(sizeof (long double))
+#endif
+
+static char sos_memory[SOS_MEMORY_SIZE] ALIGNED(MAX_ALIGN);
+static size_t sos_memory_freepos;
+static size_t pg_size;
+
+HIDDEN void *
+sos_alloc (size_t size)
+{
+ size_t pos;
+
+ size = UNW_ALIGN(size, MAX_ALIGN);
+
+#if defined(__GNUC__) && defined(HAVE_FETCH_AND_ADD)
+ /* Assume `sos_memory' is suitably aligned. */
+ assert(((uintptr_t) &sos_memory[0] & (MAX_ALIGN-1)) == 0);
+
+ pos = fetch_and_add (&sos_memory_freepos, size);
+#else
+ static define_lock (sos_lock);
+ intrmask_t saved_mask;
+
+ lock_acquire (&sos_lock, saved_mask);
+ {
+ /* No assumptions about `sos_memory' alignment. */
+ if (sos_memory_freepos == 0)
+ {
+ unsigned align = UNW_ALIGN((uintptr_t) &sos_memory[0], MAX_ALIGN)
+ - (uintptr_t) &sos_memory[0];
+ sos_memory_freepos = align;
+ }
+ pos = sos_memory_freepos;
+ sos_memory_freepos += size;
+ }
+ lock_release (&sos_lock, saved_mask);
+#endif
+
+ assert (((uintptr_t) &sos_memory[pos] & (MAX_ALIGN-1)) == 0);
+ assert ((pos+size) <= SOS_MEMORY_SIZE);
+
+ return &sos_memory[pos];
+}
+
+/* Must be called while holding the mempool lock. */
+
+static void
+free_object (struct mempool *pool, void *object)
+{
+ struct object *obj = object;
+
+ obj->next = pool->free_list;
+ pool->free_list = obj;
+ ++pool->num_free;
+}
+
+static void
+add_memory (struct mempool *pool, char *mem, size_t size, size_t obj_size)
+{
+ char *obj;
+
+ for (obj = mem; obj <= mem + size - obj_size; obj += obj_size)
+ free_object (pool, obj);
+}
+
+static void
+expand (struct mempool *pool)
+{
+ size_t size;
+ char *mem;
+
+ size = pool->chunk_size;
+ GET_MEMORY (mem, size);
+ if (!mem)
+ {
+ size = UNW_ALIGN(pool->obj_size, pg_size);
+ GET_MEMORY (mem, size);
+ if (!mem)
+ {
+ /* last chance: try to allocate one object from the SOS memory */
+ size = pool->obj_size;
+ mem = sos_alloc (size);
+ }
+ }
+ add_memory (pool, mem, size, pool->obj_size);
+}
+
+HIDDEN void
+mempool_init (struct mempool *pool, size_t obj_size, size_t reserve)
+{
+ if (pg_size == 0)
+ pg_size = getpagesize ();
+
+ memset (pool, 0, sizeof (*pool));
+
+ lock_init (&pool->lock);
+
+ /* round object-size up to integer multiple of MAX_ALIGN */
+ obj_size = UNW_ALIGN(obj_size, MAX_ALIGN);
+
+ if (!reserve)
+ {
+ reserve = pg_size / obj_size / 4;
+ if (!reserve)
+ reserve = 16;
+ }
+
+ pool->obj_size = obj_size;
+ pool->reserve = reserve;
+ pool->chunk_size = UNW_ALIGN(2*reserve*obj_size, pg_size);
+
+ expand (pool);
+}
+
+HIDDEN void *
+mempool_alloc (struct mempool *pool)
+{
+ intrmask_t saved_mask;
+ struct object *obj;
+
+ lock_acquire (&pool->lock, saved_mask);
+ {
+ if (pool->num_free <= pool->reserve)
+ expand (pool);
+
+ assert (pool->num_free > 0);
+
+ --pool->num_free;
+ obj = pool->free_list;
+ pool->free_list = obj->next;
+ }
+ lock_release (&pool->lock, saved_mask);
+ return obj;
+}
+
+HIDDEN void
+mempool_free (struct mempool *pool, void *object)
+{
+ intrmask_t saved_mask;
+
+ lock_acquire (&pool->lock, saved_mask);
+ {
+ free_object (pool, object);
+ }
+ lock_release (&pool->lock, saved_mask);
+}
diff --git a/src/pal/src/libunwind/src/mi/strerror.c b/src/pal/src/libunwind/src/mi/strerror.c
new file mode 100644
index 0000000000..2cec73d1db
--- /dev/null
+++ b/src/pal/src/libunwind/src/mi/strerror.c
@@ -0,0 +1,51 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 BEA Systems
+ Contributed by Thomas Hallgren <thallgre@bea.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+/* Returns the text corresponding to the given err_code or the
+ text "invalid error code" if the err_code is invalid. */
+const char *
+unw_strerror (int err_code)
+{
+ const char *cp;
+ unw_error_t error = (unw_error_t)-err_code;
+ switch (error)
+ {
+ case UNW_ESUCCESS: cp = "no error"; break;
+ case UNW_EUNSPEC: cp = "unspecified (general) error"; break;
+ case UNW_ENOMEM: cp = "out of memory"; break;
+ case UNW_EBADREG: cp = "bad register number"; break;
+ case UNW_EREADONLYREG: cp = "attempt to write read-only register"; break;
+ case UNW_ESTOPUNWIND: cp = "stop unwinding"; break;
+ case UNW_EINVALIDIP: cp = "invalid IP"; break;
+ case UNW_EBADFRAME: cp = "bad frame"; break;
+ case UNW_EINVAL: cp = "unsupported operation or bad value"; break;
+ case UNW_EBADVERSION: cp = "unwind info has unsupported version"; break;
+ case UNW_ENOINFO: cp = "no unwind info found"; break;
+ default: cp = "invalid error code";
+ }
+ return cp;
+}
diff --git a/src/pal/src/libunwind/src/mips/Gapply_reg_state.c b/src/pal/src/libunwind/src/mips/Gapply_reg_state.c
new file mode 100644
index 0000000000..82f056da67
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Gapply_reg_state.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+ void *reg_states_data)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
diff --git a/src/pal/src/libunwind/src/mips/Gcreate_addr_space.c b/src/pal/src/libunwind/src/mips/Gcreate_addr_space.c
new file mode 100644
index 0000000000..493d03db66
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Gcreate_addr_space.c
@@ -0,0 +1,66 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+
+#include "unwind_i.h"
+
+unw_addr_space_t
+unw_create_addr_space (unw_accessors_t *a, int byte_order)
+{
+#ifdef UNW_LOCAL_ONLY
+ return NULL;
+#else
+ unw_addr_space_t as;
+
+ /*
+ * MIPS supports only big or little-endian, not weird stuff like
+ * PDP_ENDIAN.
+ */
+ if (byte_order != 0
+ && byte_order != __LITTLE_ENDIAN
+ && byte_order != __BIG_ENDIAN)
+ return NULL;
+
+ as = malloc (sizeof (*as));
+ if (!as)
+ return NULL;
+
+ memset (as, 0, sizeof (*as));
+
+ as->acc = *a;
+
+ if (byte_order == 0)
+ /* use host default: */
+ as->big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
+ else
+ as->big_endian = (byte_order == __BIG_ENDIAN);
+
+ /* FIXME! There is no way to specify the ABI. */
+ as->abi = UNW_MIPS_ABI_O32;
+ as->addr_size = 4;
+
+ return as;
+#endif
+}
diff --git a/src/pal/src/libunwind/src/mips/Gget_proc_info.c b/src/pal/src/libunwind/src/mips/Gget_proc_info.c
new file mode 100644
index 0000000000..7b84be87b9
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Gget_proc_info.c
@@ -0,0 +1,41 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ /* We can only unwind using Dwarf into on MIPS: return failure code
+ if it's not present. */
+ ret = dwarf_make_proc_info (&c->dwarf);
+ if (ret < 0)
+ return ret;
+
+ *pi = c->dwarf.pi;
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/mips/Gget_save_loc.c b/src/pal/src/libunwind/src/mips/Gget_save_loc.c
new file mode 100644
index 0000000000..c21f9b06d0
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Gget_save_loc.c
@@ -0,0 +1,100 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+/* FIXME for MIPS. */
+
+int
+unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ dwarf_loc_t loc;
+
+ loc = DWARF_NULL_LOC; /* default to "not saved" */
+
+ switch (reg)
+ {
+ case UNW_MIPS_R0:
+ case UNW_MIPS_R1:
+ case UNW_MIPS_R2:
+ case UNW_MIPS_R3:
+ case UNW_MIPS_R4:
+ case UNW_MIPS_R5:
+ case UNW_MIPS_R6:
+ case UNW_MIPS_R7:
+ case UNW_MIPS_R8:
+ case UNW_MIPS_R9:
+ case UNW_MIPS_R10:
+ case UNW_MIPS_R11:
+ case UNW_MIPS_R12:
+ case UNW_MIPS_R13:
+ case UNW_MIPS_R14:
+ case UNW_MIPS_R15:
+ case UNW_MIPS_R16:
+ case UNW_MIPS_R17:
+ case UNW_MIPS_R18:
+ case UNW_MIPS_R19:
+ case UNW_MIPS_R20:
+ case UNW_MIPS_R21:
+ case UNW_MIPS_R22:
+ case UNW_MIPS_R23:
+ case UNW_MIPS_R24:
+ case UNW_MIPS_R25:
+ case UNW_MIPS_R26:
+ case UNW_MIPS_R27:
+ case UNW_MIPS_R28:
+ case UNW_MIPS_R29:
+ case UNW_MIPS_R30:
+ case UNW_MIPS_R31:
+ case UNW_MIPS_PC:
+ loc = c->dwarf.loc[reg - UNW_MIPS_R0];
+ break;
+
+ default:
+ break;
+ }
+
+ memset (sloc, 0, sizeof (*sloc));
+
+ if (DWARF_IS_NULL_LOC (loc))
+ {
+ sloc->type = UNW_SLT_NONE;
+ return 0;
+ }
+
+#if !defined(UNW_LOCAL_ONLY)
+ if (DWARF_IS_REG_LOC (loc))
+ {
+ sloc->type = UNW_SLT_REG;
+ sloc->u.regnum = DWARF_GET_LOC (loc);
+ }
+ else
+#endif
+ {
+ sloc->type = UNW_SLT_MEMORY;
+ sloc->u.addr = DWARF_GET_LOC (loc);
+ }
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/mips/Gglobal.c b/src/pal/src/libunwind/src/mips/Gglobal.c
new file mode 100644
index 0000000000..fa9478eebe
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Gglobal.c
@@ -0,0 +1,55 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "dwarf_i.h"
+
+HIDDEN define_lock (mips_lock);
+HIDDEN int tdep_init_done;
+
+HIDDEN void
+tdep_init (void)
+{
+ intrmask_t saved_mask;
+
+ sigfillset (&unwi_full_mask);
+
+ lock_acquire (&mips_lock, saved_mask);
+ {
+ if (tdep_init_done)
+ /* another thread else beat us to it... */
+ goto out;
+
+ mi_init ();
+
+ dwarf_init ();
+
+#ifndef UNW_REMOTE_ONLY
+ mips_local_addr_space_init ();
+#endif
+ tdep_init_done = 1; /* signal that we're initialized... */
+ }
+ out:
+ lock_release (&mips_lock, saved_mask);
+}
diff --git a/src/pal/src/libunwind/src/mips/Ginit.c b/src/pal/src/libunwind/src/mips/Ginit.c
new file mode 100644
index 0000000000..3df170c754
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Ginit.c
@@ -0,0 +1,210 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "unwind_i.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+/* unw_local_addr_space is a NULL pointer in this case. */
+unw_addr_space_t unw_local_addr_space;
+
+#else /* !UNW_REMOTE_ONLY */
+
+static struct unw_addr_space local_addr_space;
+
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
+
+/* Return the address of the 64-bit slot in UC for REG (even for o32,
+ where registers are 32-bit, the slots are still 64-bit). */
+
+static inline void *
+uc_addr (ucontext_t *uc, int reg)
+{
+ if (reg >= UNW_MIPS_R0 && reg < UNW_MIPS_R0 + 32)
+ return &uc->uc_mcontext.gregs[reg - UNW_MIPS_R0];
+ else if (reg == UNW_MIPS_PC)
+ return &uc->uc_mcontext.pc;
+ else
+ return NULL;
+}
+
+# ifdef UNW_LOCAL_ONLY
+
+HIDDEN void *
+tdep_uc_addr (ucontext_t *uc, int reg)
+{
+ char *addr = uc_addr (uc, reg);
+
+ if (((reg >= UNW_MIPS_R0 && reg <= UNW_MIPS_R31) || reg == UNW_MIPS_PC)
+ && tdep_big_endian (unw_local_addr_space)
+ && unw_local_addr_space->abi == UNW_MIPS_ABI_O32)
+ addr += 4;
+
+ return addr;
+}
+
+# endif /* UNW_LOCAL_ONLY */
+
+HIDDEN unw_dyn_info_list_t _U_dyn_info_list;
+
+/* XXX fix me: there is currently no way to locate the dyn-info list
+ by a remote unwinder. On ia64, this is done via a special
+ unwind-table entry. Perhaps something similar can be done with
+ DWARF2 unwind info. */
+
+static void
+put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
+{
+ /* it's a no-op */
+}
+
+static int
+get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
+ void *arg)
+{
+ *dyn_info_list_addr = (unw_word_t) (intptr_t) &_U_dyn_info_list;
+ return 0;
+}
+
+static int
+access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
+ void *arg)
+{
+ if (write)
+ {
+ Debug (16, "mem[%llx] <- %llx\n", (long long) addr, (long long) *val);
+ *(unw_word_t *) (intptr_t) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_word_t *) (intptr_t) addr;
+ Debug (16, "mem[%llx] -> %llx\n", (long long) addr, (long long) *val);
+ }
+ return 0;
+}
+
+static int
+access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
+ void *arg)
+{
+ unw_word_t *addr;
+ ucontext_t *uc = arg;
+
+ if (unw_is_fpreg (reg))
+ goto badreg;
+
+ Debug (16, "reg = %s\n", unw_regname (reg));
+ if (!(addr = uc_addr (uc, reg)))
+ goto badreg;
+
+ if (write)
+ {
+ *(unw_word_t *) (intptr_t) addr = (mips_reg_t) *val;
+ Debug (12, "%s <- %llx\n", unw_regname (reg), (long long) *val);
+ }
+ else
+ {
+ *val = (mips_reg_t) *(unw_word_t *) (intptr_t) addr;
+ Debug (12, "%s -> %llx\n", unw_regname (reg), (long long) *val);
+ }
+ return 0;
+
+ badreg:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+}
+
+static int
+access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
+ int write, void *arg)
+{
+ ucontext_t *uc = arg;
+ unw_fpreg_t *addr;
+
+ if (!unw_is_fpreg (reg))
+ goto badreg;
+
+ if (!(addr = uc_addr (uc, reg)))
+ goto badreg;
+
+ if (write)
+ {
+ Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg),
+ ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
+ *(unw_fpreg_t *) (intptr_t) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_fpreg_t *) (intptr_t) addr;
+ Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg),
+ ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
+ }
+ return 0;
+
+ badreg:
+ Debug (1, "bad register number %u\n", reg);
+ /* attempt to access a non-preserved register */
+ return -UNW_EBADREG;
+}
+
+static int
+get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
+ char *buf, size_t buf_len, unw_word_t *offp,
+ void *arg)
+{
+
+ return elf_w (get_proc_name) (as, getpid (), ip, buf, buf_len, offp);
+}
+
+HIDDEN void
+mips_local_addr_space_init (void)
+{
+ memset (&local_addr_space, 0, sizeof (local_addr_space));
+ local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
+#if _MIPS_SIM == _ABIO32
+ local_addr_space.abi = UNW_MIPS_ABI_O32;
+#elif _MIPS_SIM == _ABIN32
+ local_addr_space.abi = UNW_MIPS_ABI_N32;
+#elif _MIPS_SIM == _ABI64
+ local_addr_space.abi = UNW_MIPS_ABI_N64;
+#else
+# error Unsupported ABI
+#endif
+ local_addr_space.addr_size = sizeof (void *);
+ local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
+ local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
+ local_addr_space.acc.put_unwind_info = put_unwind_info;
+ local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
+ local_addr_space.acc.access_mem = access_mem;
+ local_addr_space.acc.access_reg = access_reg;
+ local_addr_space.acc.access_fpreg = access_fpreg;
+ local_addr_space.acc.resume = NULL; /* mips_local_resume? FIXME! */
+ local_addr_space.acc.get_proc_name = get_static_proc_name;
+ unw_flush_cache (&local_addr_space, 0, 0);
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/mips/Ginit_local.c b/src/pal/src/libunwind/src/mips/Ginit_local.c
new file mode 100644
index 0000000000..f3153b5ba0
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Ginit_local.c
@@ -0,0 +1,76 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "init.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+int
+unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+{
+ return -UNW_EINVAL;
+}
+
+#else /* !UNW_REMOTE_ONLY */
+
+static int
+unw_init_local_common(unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->dwarf.as = unw_local_addr_space;
+ c->dwarf.as_arg = uc;
+ return common_init (c, use_prev_instr);
+}
+
+int
+unw_init_local(unw_cursor_t *cursor, ucontext_t *uc)
+{
+ return unw_init_local_common(cursor, uc, 1);
+}
+
+int
+unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
+{
+ if (!flag)
+ {
+ return unw_init_local_common(cursor, uc, 1);
+ }
+ else if (flag == UNW_INIT_SIGNAL_FRAME)
+ {
+ return unw_init_local_common(cursor, uc, 0);
+ }
+ else
+ {
+ return -UNW_EINVAL;
+ }
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/mips/Ginit_remote.c b/src/pal/src/libunwind/src/mips/Ginit_remote.c
new file mode 100644
index 0000000000..9b8ba5b89d
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Ginit_remote.c
@@ -0,0 +1,45 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "init.h"
+#include "unwind_i.h"
+
+int
+unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
+{
+#ifdef UNW_LOCAL_ONLY
+ return -UNW_EINVAL;
+#else /* !UNW_LOCAL_ONLY */
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->dwarf.as = as;
+ c->dwarf.as_arg = as_arg;
+ return common_init (c, 0);
+#endif /* !UNW_LOCAL_ONLY */
+}
diff --git a/src/pal/src/libunwind/src/mips/Gis_signal_frame.c b/src/pal/src/libunwind/src/mips/Gis_signal_frame.c
new file mode 100644
index 0000000000..c0e3b98368
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Gis_signal_frame.c
@@ -0,0 +1,78 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2015 Imagination Technologies Limited
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include <stdio.h>
+
+int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ unw_word_t w0, w1, ip;
+ unw_addr_space_t as;
+ unw_accessors_t *a;
+ void *arg;
+ int ret;
+
+ as = c->dwarf.as;
+ a = unw_get_accessors_int (as);
+ arg = c->dwarf.as_arg;
+
+ ip = c->dwarf.ip;
+
+ /* syscall */
+ if ((ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0)
+ return 0;
+ if ((w1 & 0xffffffff) != 0x0c)
+ return 0;
+
+ /* li v0, 0x1061 (rt) or li v0, 0x1017 */
+ if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0)
+ return 0;
+
+ switch (c->dwarf.as->abi)
+ {
+ case UNW_MIPS_ABI_O32:
+ switch (w0 & 0xffffffff)
+ {
+ case 0x24021061:
+ return 1;
+ case 0x24021017:
+ return 2;
+ default:
+ return 0;
+ }
+ case UNW_MIPS_ABI_N64:
+ switch (w0 & 0xffffffff)
+ {
+ case 0x2402145b:
+ return 1;
+ default:
+ return 0;
+ }
+ default:
+ return 0;
+ }
+}
diff --git a/src/pal/src/libunwind/src/mips/Greg_states_iterate.c b/src/pal/src/libunwind/src/mips/Greg_states_iterate.c
new file mode 100644
index 0000000000..a17dc1b561
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Greg_states_iterate.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+ unw_reg_states_callback cb, void *token)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
diff --git a/src/pal/src/libunwind/src/mips/Gregs.c b/src/pal/src/libunwind/src/mips/Gregs.c
new file mode 100644
index 0000000000..95194022d2
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Gregs.c
@@ -0,0 +1,105 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+/* FIXME: The following is probably unfinished and/or at least partly bogus. */
+
+HIDDEN int
+tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
+ int write)
+{
+ dwarf_loc_t loc = DWARF_NULL_LOC;
+
+ switch (reg)
+ {
+ case UNW_MIPS_R0:
+ case UNW_MIPS_R1:
+ case UNW_MIPS_R2:
+ case UNW_MIPS_R3:
+ case UNW_MIPS_R4:
+ case UNW_MIPS_R5:
+ case UNW_MIPS_R6:
+ case UNW_MIPS_R7:
+ case UNW_MIPS_R8:
+ case UNW_MIPS_R9:
+ case UNW_MIPS_R10:
+ case UNW_MIPS_R11:
+ case UNW_MIPS_R12:
+ case UNW_MIPS_R13:
+ case UNW_MIPS_R14:
+ case UNW_MIPS_R15:
+ case UNW_MIPS_R16:
+ case UNW_MIPS_R17:
+ case UNW_MIPS_R18:
+ case UNW_MIPS_R19:
+ case UNW_MIPS_R20:
+ case UNW_MIPS_R21:
+ case UNW_MIPS_R22:
+ case UNW_MIPS_R23:
+ case UNW_MIPS_R24:
+ case UNW_MIPS_R25:
+ case UNW_MIPS_R26:
+ case UNW_MIPS_R27:
+ case UNW_MIPS_R28:
+ case UNW_MIPS_R29:
+ case UNW_MIPS_R30:
+ case UNW_MIPS_R31:
+ loc = c->dwarf.loc[reg - UNW_MIPS_R0];
+ break;
+
+ case UNW_MIPS_PC:
+ if (write)
+ c->dwarf.ip = *valp; /* update the IP cache */
+ loc = c->dwarf.loc[reg];
+ break;
+
+ case UNW_MIPS_CFA:
+ if (write)
+ return -UNW_EREADONLYREG;
+ *valp = c->dwarf.cfa;
+ return 0;
+
+ /* FIXME: IP? Copro & shadow registers? */
+
+ default:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+ }
+
+ if (write)
+ return dwarf_put (&c->dwarf, loc, *valp);
+ else
+ return dwarf_get (&c->dwarf, loc, valp);
+}
+
+/* FIXME for MIPS. */
+
+HIDDEN int
+tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
+ int write)
+{
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+}
diff --git a/src/pal/src/libunwind/src/mips/Gresume.c b/src/pal/src/libunwind/src/mips/Gresume.c
new file mode 100644
index 0000000000..cb70abc8c5
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Gresume.c
@@ -0,0 +1,45 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* FIXME for MIPS. */
+
+#include <stdlib.h>
+
+#include "unwind_i.h"
+
+#ifndef UNW_REMOTE_ONLY
+
+HIDDEN inline int
+mips_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
+{
+ return -UNW_EINVAL;
+}
+
+#endif /* !UNW_REMOTE_ONLY */
+
+int
+unw_resume (unw_cursor_t *cursor)
+{
+ return -UNW_EINVAL;
+}
diff --git a/src/pal/src/libunwind/src/mips/Gstep.c b/src/pal/src/libunwind/src/mips/Gstep.c
new file mode 100644
index 0000000000..937136aef1
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Gstep.c
@@ -0,0 +1,132 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2015 Imagination Technologies Limited
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "offsets.h"
+
+static int
+mips_handle_signal_frame (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ unw_word_t sc_addr, sp_addr = c->dwarf.cfa;
+ unw_word_t ra, fp;
+ int ret;
+
+ switch (unw_is_signal_frame (cursor)) {
+ case 1:
+ sc_addr = sp_addr + LINUX_SF_TRAMP_SIZE + sizeof (siginfo_t) +
+ LINUX_UC_MCONTEXT_OFF;
+ break;
+ case 2:
+ sc_addr = sp_addr + LINUX_UC_MCONTEXT_OFF;
+ break;
+ default:
+ return -UNW_EUNSPEC;
+ }
+
+ if (tdep_big_endian(c->dwarf.as))
+ sc_addr += 4;
+
+ c->sigcontext_addr = sc_addr;
+
+ /* Update the dwarf cursor. */
+ c->dwarf.loc[UNW_MIPS_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R11] = DWARF_LOC (sc_addr + LINUX_SC_R11_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R12] = DWARF_LOC (sc_addr + LINUX_SC_R12_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R13] = DWARF_LOC (sc_addr + LINUX_SC_R13_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R14] = DWARF_LOC (sc_addr + LINUX_SC_R14_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R15] = DWARF_LOC (sc_addr + LINUX_SC_R15_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R16] = DWARF_LOC (sc_addr + LINUX_SC_R16_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R17] = DWARF_LOC (sc_addr + LINUX_SC_R17_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R18] = DWARF_LOC (sc_addr + LINUX_SC_R18_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R19] = DWARF_LOC (sc_addr + LINUX_SC_R19_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R20] = DWARF_LOC (sc_addr + LINUX_SC_R20_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R21] = DWARF_LOC (sc_addr + LINUX_SC_R21_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R22] = DWARF_LOC (sc_addr + LINUX_SC_R22_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R23] = DWARF_LOC (sc_addr + LINUX_SC_R23_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R24] = DWARF_LOC (sc_addr + LINUX_SC_R24_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R25] = DWARF_LOC (sc_addr + LINUX_SC_R25_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R26] = DWARF_LOC (sc_addr + LINUX_SC_R26_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R27] = DWARF_LOC (sc_addr + LINUX_SC_R27_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R28] = DWARF_LOC (sc_addr + LINUX_SC_R28_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R29] = DWARF_LOC (sc_addr + LINUX_SC_R29_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R30] = DWARF_LOC (sc_addr + LINUX_SC_R30_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_R31] = DWARF_LOC (sc_addr + LINUX_SC_R31_OFF, 0);
+ c->dwarf.loc[UNW_MIPS_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0);
+
+ /* Set SP/CFA and PC/IP. */
+ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_MIPS_R29], &c->dwarf.cfa);
+
+ if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_PC_OFF, 0),
+ &c->dwarf.ip)) < 0)
+ return ret;
+
+ if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R31_OFF, 0),
+ &ra)) < 0)
+ return ret;
+ if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R30_OFF, 0),
+ &fp)) < 0)
+ return ret;
+
+ Debug (2, "SH (ip=0x%016llx, ra=0x%016llx, sp=0x%016llx, fp=0x%016llx)\n",
+ (unsigned long long)c->dwarf.ip, (unsigned long long)ra,
+ (unsigned long long)c->dwarf.cfa, (unsigned long long)fp);
+
+ c->dwarf.pi_valid = 0;
+ c->dwarf.use_prev_instr = 0;
+
+ return 1;
+}
+
+int
+unw_step (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ ret = mips_handle_signal_frame (cursor);
+ if (ret < 0)
+ /* Not a signal frame, try DWARF-based unwinding. */
+ ret = dwarf_step (&c->dwarf);
+
+ if (unlikely (ret == -UNW_ESTOPUNWIND))
+ return ret;
+
+ /* Dwarf unwinding didn't work, stop. */
+ if (unlikely (ret < 0))
+ return 0;
+
+ return (c->dwarf.ip == 0) ? 0 : 1;
+}
diff --git a/src/pal/src/libunwind/src/mips/Lapply_reg_state.c b/src/pal/src/libunwind/src/mips/Lapply_reg_state.c
new file mode 100644
index 0000000000..7ebada480e
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Lapply_reg_state.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mips/Lcreate_addr_space.c b/src/pal/src/libunwind/src/mips/Lcreate_addr_space.c
new file mode 100644
index 0000000000..0f2dc6be90
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Lcreate_addr_space.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gcreate_addr_space.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mips/Lget_proc_info.c b/src/pal/src/libunwind/src/mips/Lget_proc_info.c
new file mode 100644
index 0000000000..69028b019f
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Lget_proc_info.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_proc_info.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mips/Lget_save_loc.c b/src/pal/src/libunwind/src/mips/Lget_save_loc.c
new file mode 100644
index 0000000000..9ea048a907
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Lget_save_loc.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_save_loc.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mips/Lglobal.c b/src/pal/src/libunwind/src/mips/Lglobal.c
new file mode 100644
index 0000000000..6d7b489e14
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Lglobal.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gglobal.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mips/Linit.c b/src/pal/src/libunwind/src/mips/Linit.c
new file mode 100644
index 0000000000..e9abfdd46a
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Linit.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mips/Linit_local.c b/src/pal/src/libunwind/src/mips/Linit_local.c
new file mode 100644
index 0000000000..68a1687e85
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Linit_local.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_local.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mips/Linit_remote.c b/src/pal/src/libunwind/src/mips/Linit_remote.c
new file mode 100644
index 0000000000..58cb04ab7c
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Linit_remote.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_remote.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mips/Lis_signal_frame.c b/src/pal/src/libunwind/src/mips/Lis_signal_frame.c
new file mode 100644
index 0000000000..b9a7c4f51a
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Lis_signal_frame.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gis_signal_frame.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mips/Lreg_states_iterate.c b/src/pal/src/libunwind/src/mips/Lreg_states_iterate.c
new file mode 100644
index 0000000000..f1eb1e79dc
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Lreg_states_iterate.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mips/Lregs.c b/src/pal/src/libunwind/src/mips/Lregs.c
new file mode 100644
index 0000000000..2c9c75cd7d
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Lregs.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gregs.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mips/Lresume.c b/src/pal/src/libunwind/src/mips/Lresume.c
new file mode 100644
index 0000000000..41a8cf003d
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Lresume.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gresume.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mips/Lstep.c b/src/pal/src/libunwind/src/mips/Lstep.c
new file mode 100644
index 0000000000..c1ac3c7547
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/Lstep.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gstep.c"
+#endif
diff --git a/src/pal/src/libunwind/src/mips/elfxx.c b/src/pal/src/libunwind/src/mips/elfxx.c
new file mode 100644
index 0000000000..07d3d12b94
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/elfxx.c
@@ -0,0 +1,27 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+#include "../src/elfxx.c"
diff --git a/src/pal/src/libunwind/src/mips/gen-offsets.c b/src/pal/src/libunwind/src/mips/gen-offsets.c
new file mode 100644
index 0000000000..448f694532
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/gen-offsets.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include <stddef.h>
+#include <ucontext.h>
+
+#define UC(N,X) \
+ printf ("#define LINUX_UC_" N "_OFF\t0x%X\n", offsetof (ucontext_t, X))
+
+#define SC(N,X) \
+ printf ("#define LINUX_SC_" N "_OFF\t0x%X\n", offsetof (struct sigcontext, X))
+
+int
+main (void)
+{
+ printf (
+"/* Linux-specific definitions: */\n\n"
+
+"/* Define various structure offsets to simplify cross-compilation. */\n\n"
+
+"/* Offsets for MIPS Linux \"ucontext_t\": */\n\n");
+
+ UC ("FLAGS", uc_flags);
+ UC ("LINK", uc_link);
+ UC ("STACK", uc_stack);
+ UC ("MCONTEXT", uc_mcontext);
+ UC ("SIGMASK", uc_sigmask);
+
+ UC ("MCONTEXT_GREGS", uc_mcontext.gregs);
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/mips/getcontext.S b/src/pal/src/libunwind/src/mips/getcontext.S
new file mode 100644
index 0000000000..d1dbd57932
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/getcontext.S
@@ -0,0 +1,93 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "offsets.h"
+#include <endian.h>
+
+ .text
+
+#if _MIPS_SIM == _ABIO32
+# if __BYTE_ORDER == __BIG_ENDIAN
+# define OFFSET 4
+# else
+# define OFFSET 0
+# endif
+# define SREG(X) \
+ sw $X, (LINUX_UC_MCONTEXT_GREGS + 8 * X + OFFSET) ($4); \
+ sra $1, $X, 31; \
+ sw $1, (LINUX_UC_MCONTEXT_GREGS + 8 * X + 4 - OFFSET) ($4)
+/* Yes, we save the return address to PC. */
+# define SPC \
+ sw $31, (LINUX_UC_MCONTEXT_PC + OFFSET) ($4); \
+ sra $1, $31, 31; \
+ sw $1, (LINUX_UC_MCONTEXT_PC + 4 - OFFSET) ($4)
+#else
+# define SREG(X) sd $X, (LINUX_UC_MCONTEXT_GREGS + 8 * X) ($4)
+# define SPC sd $31, (LINUX_UC_MCONTEXT_PC) ($4)
+#endif
+
+ .global _Umips_getcontext
+ .type _Umips_getcontext, %function
+ # This is a stub version of getcontext() for MIPS which only stores core
+ # registers.
+_Umips_getcontext:
+ .set noat
+ SREG (1)
+ SREG (0)
+ SREG (2)
+ SREG (3)
+ SREG (4)
+ SREG (5)
+ SREG (6)
+ SREG (7)
+ SREG (8)
+ SREG (9)
+ SREG (10)
+ SREG (11)
+ SREG (12)
+ SREG (13)
+ SREG (14)
+ SREG (15)
+ SREG (16)
+ SREG (17)
+ SREG (18)
+ SREG (19)
+ SREG (20)
+ SREG (21)
+ SREG (22)
+ SREG (23)
+ SREG (24)
+ SREG (25)
+ SREG (26)
+ SREG (27)
+ SREG (28)
+ SREG (29)
+ SREG (30)
+ SREG (31)
+ SPC
+ li $2, 0
+ j $31
+
+ .size _Umips_getcontext, .-_Umips_getcontext
diff --git a/src/pal/src/libunwind/src/mips/init.h b/src/pal/src/libunwind/src/mips/init.h
new file mode 100644
index 0000000000..30c193a18f
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/init.h
@@ -0,0 +1,59 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+static inline int
+common_init (struct cursor *c, unsigned use_prev_instr)
+{
+ int ret, i;
+
+ for (i = 0; i < 32; i++)
+ c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, UNW_MIPS_R0 + i);
+ for (i = 32; i < DWARF_NUM_PRESERVED_REGS; ++i)
+ c->dwarf.loc[i] = DWARF_NULL_LOC;
+
+ c->dwarf.loc[UNW_MIPS_PC] = DWARF_REG_LOC (&c->dwarf, UNW_MIPS_PC);
+
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_MIPS_PC], &c->dwarf.ip);
+ if (ret < 0)
+ return ret;
+
+ ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_MIPS_R29),
+ &c->dwarf.cfa);
+ if (ret < 0)
+ return ret;
+
+ /* FIXME: Initialisation for other registers. */
+
+ c->dwarf.args_size = 0;
+ c->dwarf.stash_frames = 0;
+ c->dwarf.use_prev_instr = use_prev_instr;
+ c->dwarf.pi_valid = 0;
+ c->dwarf.pi_is_dynamic = 0;
+ c->dwarf.hint = 0;
+ c->dwarf.prev_rs = 0;
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/mips/is_fpreg.c b/src/pal/src/libunwind/src/mips/is_fpreg.c
new file mode 100644
index 0000000000..a92dd5ece7
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/is_fpreg.c
@@ -0,0 +1,35 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+/* FIXME: I'm not sure if libunwind's GP/FP register distinction is very useful
+ on MIPS. */
+
+int
+unw_is_fpreg (int regnum)
+{
+ /* FIXME: Support FP. */
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/mips/offsets.h b/src/pal/src/libunwind/src/mips/offsets.h
new file mode 100644
index 0000000000..b506051367
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/offsets.h
@@ -0,0 +1,86 @@
+/* Linux-specific definitions: */
+
+/* Define various structure offsets to simplify cross-compilation. */
+
+/* FIXME: Currently these are only used in getcontext.S, which is only used
+ for a local unwinder, so we can use the compile-time ABI. At a later date
+ we will want all three here, to use for signal handlers. Also, because
+ of the three ABIs, gen-offsets.c can not quite generate this file. */
+
+/* Offsets for MIPS Linux "ucontext_t": */
+
+/* First 24 bytes in sigframe are argument save space and padding for
+what used to be signal trampolines. Ref: arch/mips/kernel/signal.c */
+#define LINUX_SF_TRAMP_SIZE 0x18
+
+#if _MIPS_SIM == _ABIO32
+
+# define LINUX_UC_FLAGS_OFF 0x0
+# define LINUX_UC_LINK_OFF 0x4
+# define LINUX_UC_STACK_OFF 0x8
+# define LINUX_UC_MCONTEXT_OFF 0x18
+# define LINUX_UC_SIGMASK_OFF 0x268
+# define LINUX_UC_MCONTEXT_PC 0x20
+# define LINUX_UC_MCONTEXT_GREGS 0x28
+
+#elif _MIPS_SIM == _ABIN32
+
+# define LINUX_UC_FLAGS_OFF 0x0
+# define LINUX_UC_LINK_OFF 0x4
+# define LINUX_UC_STACK_OFF 0x8
+# define LINUX_UC_MCONTEXT_OFF 0x18
+# define LINUX_UC_SIGMASK_OFF 0x270
+# define LINUX_UC_MCONTEXT_PC 0x258
+# define LINUX_UC_MCONTEXT_GREGS 0x18
+
+#elif _MIPS_SIM == _ABI64
+
+# define LINUX_UC_FLAGS_OFF 0x0
+# define LINUX_UC_LINK_OFF 0x8
+# define LINUX_UC_STACK_OFF 0x10
+# define LINUX_UC_MCONTEXT_OFF 0x28
+# define LINUX_UC_SIGMASK_OFF 0x280
+# define LINUX_UC_MCONTEXT_PC 0x268
+# define LINUX_UC_MCONTEXT_GREGS 0x28
+
+#else
+
+#error Unsupported ABI
+
+#endif
+
+#define LINUX_SC_R0_OFF (LINUX_UC_MCONTEXT_GREGS - LINUX_UC_MCONTEXT_OFF)
+#define LINUX_SC_R1_OFF (LINUX_SC_R0_OFF + 1*8)
+#define LINUX_SC_R2_OFF (LINUX_SC_R0_OFF + 2*8)
+#define LINUX_SC_R3_OFF (LINUX_SC_R0_OFF + 3*8)
+#define LINUX_SC_R4_OFF (LINUX_SC_R0_OFF + 4*8)
+#define LINUX_SC_R5_OFF (LINUX_SC_R0_OFF + 5*8)
+#define LINUX_SC_R6_OFF (LINUX_SC_R0_OFF + 6*8)
+#define LINUX_SC_R7_OFF (LINUX_SC_R0_OFF + 7*8)
+#define LINUX_SC_R8_OFF (LINUX_SC_R0_OFF + 8*8)
+#define LINUX_SC_R9_OFF (LINUX_SC_R0_OFF + 9*8)
+#define LINUX_SC_R10_OFF (LINUX_SC_R0_OFF + 10*8)
+#define LINUX_SC_R11_OFF (LINUX_SC_R0_OFF + 11*8)
+#define LINUX_SC_R12_OFF (LINUX_SC_R0_OFF + 12*8)
+#define LINUX_SC_R13_OFF (LINUX_SC_R0_OFF + 13*8)
+#define LINUX_SC_R14_OFF (LINUX_SC_R0_OFF + 14*8)
+#define LINUX_SC_R15_OFF (LINUX_SC_R0_OFF + 15*8)
+#define LINUX_SC_R16_OFF (LINUX_SC_R0_OFF + 16*8)
+#define LINUX_SC_R17_OFF (LINUX_SC_R0_OFF + 17*8)
+#define LINUX_SC_R18_OFF (LINUX_SC_R0_OFF + 18*8)
+#define LINUX_SC_R19_OFF (LINUX_SC_R0_OFF + 19*8)
+#define LINUX_SC_R20_OFF (LINUX_SC_R0_OFF + 20*8)
+#define LINUX_SC_R21_OFF (LINUX_SC_R0_OFF + 21*8)
+#define LINUX_SC_R22_OFF (LINUX_SC_R0_OFF + 22*8)
+#define LINUX_SC_R23_OFF (LINUX_SC_R0_OFF + 23*8)
+#define LINUX_SC_R24_OFF (LINUX_SC_R0_OFF + 24*8)
+#define LINUX_SC_R25_OFF (LINUX_SC_R0_OFF + 25*8)
+#define LINUX_SC_R26_OFF (LINUX_SC_R0_OFF + 26*8)
+#define LINUX_SC_R27_OFF (LINUX_SC_R0_OFF + 27*8)
+#define LINUX_SC_R28_OFF (LINUX_SC_R0_OFF + 28*8)
+#define LINUX_SC_R29_OFF (LINUX_SC_R0_OFF + 29*8)
+#define LINUX_SC_R30_OFF (LINUX_SC_R0_OFF + 30*8)
+#define LINUX_SC_R31_OFF (LINUX_SC_R0_OFF + 31*8)
+
+#define LINUX_SC_SP_OFF LINUX_SC_R29_OFF
+#define LINUX_SC_PC_OFF (LINUX_UC_MCONTEXT_PC - LINUX_UC_MCONTEXT_OFF)
diff --git a/src/pal/src/libunwind/src/mips/regname.c b/src/pal/src/libunwind/src/mips/regname.c
new file mode 100644
index 0000000000..b137b972b6
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/regname.c
@@ -0,0 +1,48 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+static const char *regname[] =
+ {
+ /* 0. */
+ "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
+ /* 8. */
+ "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
+ /* 16. */
+ "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
+ /* 24. */
+ "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31",
+ };
+
+const char *
+unw_regname (unw_regnum_t reg)
+{
+ if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
+ return regname[reg];
+ else if (reg == UNW_MIPS_PC)
+ return "pc";
+ else
+ return "???";
+}
diff --git a/src/pal/src/libunwind/src/mips/siglongjmp.S b/src/pal/src/libunwind/src/mips/siglongjmp.S
new file mode 100644
index 0000000000..9cbcf3dc01
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/siglongjmp.S
@@ -0,0 +1,8 @@
+ /* Dummy implementation for now. */
+
+ .globl _UI_siglongjmp_cont
+ .globl _UI_longjmp_cont
+
+_UI_siglongjmp_cont:
+_UI_longjmp_cont:
+ j $31
diff --git a/src/pal/src/libunwind/src/mips/unwind_i.h b/src/pal/src/libunwind/src/mips/unwind_i.h
new file mode 100644
index 0000000000..3382dcfe58
--- /dev/null
+++ b/src/pal/src/libunwind/src/mips/unwind_i.h
@@ -0,0 +1,43 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef unwind_i_h
+#define unwind_i_h
+
+#include <stdint.h>
+
+#include <libunwind-mips.h>
+
+#include "libunwind_i.h"
+
+#define mips_lock UNW_OBJ(lock)
+#define mips_local_resume UNW_OBJ(local_resume)
+#define mips_local_addr_space_init UNW_OBJ(local_addr_space_init)
+
+extern int mips_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
+ void *arg);
+
+extern void mips_local_addr_space_init (void);
+
+#endif /* unwind_i_h */
diff --git a/src/pal/src/libunwind/src/os-freebsd.c b/src/pal/src/libunwind/src/os-freebsd.c
new file mode 100644
index 0000000000..753e819dfe
--- /dev/null
+++ b/src/pal/src/libunwind/src/os-freebsd.c
@@ -0,0 +1,166 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "libunwind_i.h"
+
+static void *
+get_mem(size_t sz)
+{
+ void *res;
+
+ res = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (res == MAP_FAILED)
+ return (NULL);
+ return (res);
+}
+
+static void
+free_mem(void *ptr, size_t sz)
+{
+ munmap(ptr, sz);
+}
+
+static int
+get_pid_by_tid(int tid)
+{
+ int mib[3], error;
+ size_t len, len1;
+ char *buf;
+ struct kinfo_proc *kv;
+ unsigned i, pid;
+
+ len = 0;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_ALL;
+
+ error = sysctl(mib, 3, NULL, &len, NULL, 0);
+ if (error == -1)
+ return (-1);
+ len1 = len * 4 / 3;
+ buf = get_mem(len1);
+ if (buf == NULL)
+ return (-1);
+ len = len1;
+ error = sysctl(mib, 3, buf, &len, NULL, 0);
+ if (error == -1) {
+ free_mem(buf, len1);
+ return (-1);
+ }
+ pid = -1;
+ for (i = 0, kv = (struct kinfo_proc *)buf; i < len / sizeof(*kv);
+ i++, kv++) {
+ if (kv->ki_tid == tid) {
+ pid = kv->ki_pid;
+ break;
+ }
+ }
+ free_mem(buf, len1);
+ return (pid);
+}
+
+int
+tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
+ unsigned long *segbase, unsigned long *mapoff, char *path, size_t pathlen)
+{
+ int mib[4], error, ret;
+ size_t len, len1;
+ char *buf, *bp, *eb;
+ struct kinfo_vmentry *kv;
+
+ len = 0;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_VMMAP;
+ mib[3] = pid;
+
+ error = sysctl(mib, 4, NULL, &len, NULL, 0);
+ if (error == -1) {
+ if (errno == ESRCH) {
+ mib[3] = get_pid_by_tid(pid);
+ if (mib[3] != -1)
+ error = sysctl(mib, 4, NULL, &len, NULL, 0);
+ if (error == -1)
+ return (-UNW_EUNSPEC);
+ } else
+ return (-UNW_EUNSPEC);
+ }
+ len1 = len * 4 / 3;
+ buf = get_mem(len1);
+ if (buf == NULL)
+ return (-UNW_EUNSPEC);
+ len = len1;
+ error = sysctl(mib, 4, buf, &len, NULL, 0);
+ if (error == -1) {
+ free_mem(buf, len1);
+ return (-UNW_EUNSPEC);
+ }
+ ret = -UNW_EUNSPEC;
+ for (bp = buf, eb = buf + len; bp < eb; bp += kv->kve_structsize) {
+ kv = (struct kinfo_vmentry *)(uintptr_t)bp;
+ if (ip < kv->kve_start || ip >= kv->kve_end)
+ continue;
+ if (kv->kve_type != KVME_TYPE_VNODE)
+ continue;
+ *segbase = kv->kve_start;
+ *mapoff = kv->kve_offset;
+ if (path)
+ {
+ strncpy(path, kv->kve_path, pathlen);
+ }
+ ret = elf_map_image (ei, kv->kve_path);
+ break;
+ }
+ free_mem(buf, len1);
+ return (ret);
+}
+
+#ifndef UNW_REMOTE_ONLY
+
+void
+tdep_get_exe_image_path (char *path)
+{
+ int mib[4], error;
+ size_t len;
+
+ len = 0;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PATHNAME;
+ mib[3] = getpid();
+
+ error = sysctl(mib, 4, path, &len, NULL, 0);
+ if (error == -1)
+ path[0] = 0;
+}
+
+#endif
diff --git a/src/pal/src/libunwind/src/os-hpux.c b/src/pal/src/libunwind/src/os-hpux.c
new file mode 100644
index 0000000000..48bfb05cf5
--- /dev/null
+++ b/src/pal/src/libunwind/src/os-hpux.c
@@ -0,0 +1,78 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <dlfcn.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libunwind_i.h"
+
+#include "elf64.h"
+
+HIDDEN int
+tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
+ unsigned long *segbase, unsigned long *mapoff,
+ char *path, size_t pathlen)
+{
+ struct load_module_desc lmd;
+ const char *path2;
+
+ if (pid != getpid ())
+ {
+ printf ("%s: remote case not implemented yet\n", __FUNCTION__);
+ return -UNW_ENOINFO;
+ }
+
+ if (!dlmodinfo (ip, &lmd, sizeof (lmd), NULL, 0, 0))
+ return -UNW_ENOINFO;
+
+ *segbase = lmd.text_base;
+ *mapoff = 0; /* XXX fix me? */
+
+ path2 = dlgetname (&lmd, sizeof (lmd), NULL, 0, 0);
+ if (!path2)
+ return -UNW_ENOINFO;
+ if (path)
+ {
+ strncpy(path, path2, pathlen);
+ path[pathlen - 1] = '\0';
+ if (strcmp(path, path2) != 0)
+ Debug(1, "buffer size (%d) not big enough to hold path\n", pathlen);
+ }
+ Debug(1, "segbase=%lx, mapoff=%lx, path=%s\n", *segbase, *mapoff, path);
+
+ return elf_map_image (ei, path);
+}
+
+#ifndef UNW_REMOTE_ONLY
+
+void
+tdep_get_exe_image_path (char *path)
+{
+ path[0] = 0; /* XXX */
+}
+
+#endif
+
diff --git a/src/pal/src/libunwind/src/os-linux.c b/src/pal/src/libunwind/src/os-linux.c
new file mode 100644
index 0000000000..8a00669fb3
--- /dev/null
+++ b/src/pal/src/libunwind/src/os-linux.c
@@ -0,0 +1,73 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <limits.h>
+#include <stdio.h>
+
+#include "libunwind_i.h"
+#include "os-linux.h"
+
+int
+tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
+ unsigned long *segbase, unsigned long *mapoff,
+ char *path, size_t pathlen)
+{
+ struct map_iterator mi;
+ int found = 0, rc;
+ unsigned long hi;
+
+ if (maps_init (&mi, pid) < 0)
+ return -1;
+
+ while (maps_next (&mi, segbase, &hi, mapoff))
+ if (ip >= *segbase && ip < hi)
+ {
+ found = 1;
+ break;
+ }
+
+ if (!found)
+ {
+ maps_close (&mi);
+ return -1;
+ }
+ if (path)
+ {
+ strncpy(path, mi.path, pathlen);
+ }
+ rc = elf_map_image (ei, mi.path);
+ maps_close (&mi);
+ return rc;
+}
+
+#ifndef UNW_REMOTE_ONLY
+
+void
+tdep_get_exe_image_path (char *path)
+{
+ strcpy(path, "/proc/self/exe");
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/os-linux.h b/src/pal/src/libunwind/src/os-linux.h
new file mode 100644
index 0000000000..3976b38cc2
--- /dev/null
+++ b/src/pal/src/libunwind/src/os-linux.h
@@ -0,0 +1,297 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Copyright (C) 2007 David Mosberger-Tang
+ Contributed by David Mosberger-Tang <dmosberger@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef os_linux_h
+#define os_linux_h
+
+struct map_iterator
+ {
+ off_t offset;
+ int fd;
+ size_t buf_size;
+ char *buf;
+ char *buf_end;
+ char *path;
+ };
+
+static inline char *
+ltoa (char *buf, long val)
+{
+ char *cp = buf, tmp;
+ ssize_t i, len;
+
+ do
+ {
+ *cp++ = '0' + (val % 10);
+ val /= 10;
+ }
+ while (val);
+
+ /* reverse the order of the digits: */
+ len = cp - buf;
+ --cp;
+ for (i = 0; i < len / 2; ++i)
+ {
+ tmp = buf[i];
+ buf[i] = cp[-i];
+ cp[-i] = tmp;
+ }
+ return buf + len;
+}
+
+static inline int
+maps_init (struct map_iterator *mi, pid_t pid)
+{
+ char path[sizeof ("/proc/0123456789/maps")], *cp;
+
+ memcpy (path, "/proc/", 6);
+ cp = ltoa (path + 6, pid);
+ assert (cp + 6 < path + sizeof (path));
+ memcpy (cp, "/maps", 6);
+
+ mi->fd = open (path, O_RDONLY);
+ if (mi->fd >= 0)
+ {
+ /* Try to allocate a page-sized buffer. */
+ mi->buf_size = getpagesize ();
+ cp = mmap (NULL, mi->buf_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (cp == MAP_FAILED)
+ {
+ close(mi->fd);
+ mi->fd = -1;
+ return -1;
+ }
+ else
+ {
+ mi->offset = 0;
+ mi->buf = mi->buf_end = cp + mi->buf_size;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static inline char *
+skip_whitespace (char *cp)
+{
+ if (!cp)
+ return NULL;
+
+ while (*cp == ' ' || *cp == '\t')
+ ++cp;
+ return cp;
+}
+
+static inline char *
+scan_hex (char *cp, unsigned long *valp)
+{
+ unsigned long num_digits = 0, digit, val = 0;
+
+ cp = skip_whitespace (cp);
+ if (!cp)
+ return NULL;
+
+ while (1)
+ {
+ digit = *cp;
+ if ((digit - '0') <= 9)
+ digit -= '0';
+ else if ((digit - 'a') < 6)
+ digit -= 'a' - 10;
+ else if ((digit - 'A') < 6)
+ digit -= 'A' - 10;
+ else
+ break;
+ val = (val << 4) | digit;
+ ++num_digits;
+ ++cp;
+ }
+ if (!num_digits)
+ return NULL;
+ *valp = val;
+ return cp;
+}
+
+static inline char *
+scan_dec (char *cp, unsigned long *valp)
+{
+ unsigned long num_digits = 0, digit, val = 0;
+
+ if (!(cp = skip_whitespace (cp)))
+ return NULL;
+
+ while (1)
+ {
+ digit = *cp;
+ if ((digit - '0') <= 9)
+ {
+ digit -= '0';
+ ++cp;
+ }
+ else
+ break;
+ val = (10 * val) + digit;
+ ++num_digits;
+ }
+ if (!num_digits)
+ return NULL;
+ *valp = val;
+ return cp;
+}
+
+static inline char *
+scan_char (char *cp, char *valp)
+{
+ if (!cp)
+ return NULL;
+
+ *valp = *cp;
+
+ /* don't step over NUL terminator */
+ if (*cp)
+ ++cp;
+ return cp;
+}
+
+/* Scan a string delimited by white-space. Fails on empty string or
+ if string is doesn't fit in the specified buffer. */
+static inline char *
+scan_string (char *cp, char *valp, size_t buf_size)
+{
+ size_t i = 0;
+
+ if (!(cp = skip_whitespace (cp)))
+ return NULL;
+
+ while (*cp != ' ' && *cp != '\t' && *cp != '\0')
+ {
+ if ((valp != NULL) && (i < buf_size - 1))
+ valp[i++] = *cp;
+ ++cp;
+ }
+ if (i == 0 || i >= buf_size)
+ return NULL;
+ valp[i] = '\0';
+ return cp;
+}
+
+static inline int
+maps_next (struct map_iterator *mi,
+ unsigned long *low, unsigned long *high, unsigned long *offset)
+{
+ char perm[16], dash = 0, colon = 0, *cp;
+ unsigned long major, minor, inum;
+ ssize_t i, nread;
+
+ if (mi->fd < 0)
+ return 0;
+
+ while (1)
+ {
+ ssize_t bytes_left = mi->buf_end - mi->buf;
+ char *eol = NULL;
+
+ for (i = 0; i < bytes_left; ++i)
+ {
+ if (mi->buf[i] == '\n')
+ {
+ eol = mi->buf + i;
+ break;
+ }
+ else if (mi->buf[i] == '\0')
+ break;
+ }
+ if (!eol)
+ {
+ /* copy down the remaining bytes, if any */
+ if (bytes_left > 0)
+ memmove (mi->buf_end - mi->buf_size, mi->buf, bytes_left);
+
+ mi->buf = mi->buf_end - mi->buf_size;
+ nread = read (mi->fd, mi->buf + bytes_left,
+ mi->buf_size - bytes_left);
+ if (nread <= 0)
+ return 0;
+ else if ((size_t) (nread + bytes_left) < mi->buf_size)
+ {
+ /* Move contents to the end of the buffer so we
+ maintain the invariant that all bytes between
+ mi->buf and mi->buf_end are valid. */
+ memmove (mi->buf_end - nread - bytes_left, mi->buf,
+ nread + bytes_left);
+ mi->buf = mi->buf_end - nread - bytes_left;
+ }
+
+ eol = mi->buf + bytes_left + nread - 1;
+
+ for (i = bytes_left; i < bytes_left + nread; ++i)
+ if (mi->buf[i] == '\n')
+ {
+ eol = mi->buf + i;
+ break;
+ }
+ }
+ cp = mi->buf;
+ mi->buf = eol + 1;
+ *eol = '\0';
+
+ /* scan: "LOW-HIGH PERM OFFSET MAJOR:MINOR INUM PATH" */
+ cp = scan_hex (cp, low);
+ cp = scan_char (cp, &dash);
+ cp = scan_hex (cp, high);
+ cp = scan_string (cp, perm, sizeof (perm));
+ cp = scan_hex (cp, offset);
+ cp = scan_hex (cp, &major);
+ cp = scan_char (cp, &colon);
+ cp = scan_hex (cp, &minor);
+ cp = scan_dec (cp, &inum);
+ cp = mi->path = skip_whitespace (cp);
+ if (!cp)
+ continue;
+ cp = scan_string (cp, NULL, 0);
+ if (dash != '-' || colon != ':')
+ continue; /* skip line with unknown or bad format */
+ return 1;
+ }
+ return 0;
+}
+
+static inline void
+maps_close (struct map_iterator *mi)
+{
+ if (mi->fd < 0)
+ return;
+ close (mi->fd);
+ mi->fd = -1;
+ if (mi->buf)
+ {
+ munmap (mi->buf_end - mi->buf_size, mi->buf_size);
+ mi->buf = mi->buf_end = NULL;
+ }
+}
+
+#endif /* os_linux_h */
diff --git a/src/pal/src/libunwind/src/os-qnx.c b/src/pal/src/libunwind/src/os-qnx.c
new file mode 100644
index 0000000000..4a76c7cda4
--- /dev/null
+++ b/src/pal/src/libunwind/src/os-qnx.c
@@ -0,0 +1,117 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2013 Garmin International
+ Contributed by Matt Fischer <matt.fischer@garmin.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <string.h>
+
+#include "libunwind_i.h"
+
+struct cb_info
+{
+ unw_word_t ip;
+ unsigned long segbase;
+ unsigned long offset;
+ const char *path;
+};
+
+static int callback(const struct dl_phdr_info *info, size_t size, void *data)
+{
+ int i;
+ struct cb_info *cbi = (struct cb_info*)data;
+ for(i=0; i<info->dlpi_phnum; i++) {
+ int segbase = info->dlpi_addr + info->dlpi_phdr[i].p_vaddr;
+ if(cbi->ip >= segbase && cbi->ip < segbase + info->dlpi_phdr[i].p_memsz)
+ {
+ cbi->path = info->dlpi_name;
+ cbi->offset = info->dlpi_phdr[i].p_offset;
+ cbi->segbase = segbase;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int
+tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
+ unsigned long *segbase, unsigned long *mapoff,
+ char *path, size_t pathlen)
+{
+ struct cb_info cbi;
+ int ret = -1;
+ cbi.ip = ip;
+ cbi.segbase = 0;
+ cbi.offset = 0;
+ cbi.path = NULL;
+
+ /* QNX's support for accessing symbol maps is severely broken. There is
+ a devctl() call that can be made on a proc node (DCMD_PROC_MAPDEBUG)
+ which returns information similar to Linux's /proc/<pid>/maps
+ node, however the filename that is returned by this call is not an
+ absolute path, and there is no foolproof way to map the filename
+ back to the file that it came from.
+
+ Therefore, the normal approach for implementing this function,
+ which works equally well for both local and remote unwinding,
+ will not work here. The only type of image lookup which works
+ reliably is locally, using dl_iterate_phdr(). However, the only
+ time that this function is required to look up a remote image is for
+ ptrace support, which doesn't work on QNX anyway. Local unwinding,
+ which is the main case that makes use of this function, will work
+ fine with dl_iterate_phdr(). Therefore, in lieu of any better
+ platform support for remote image lookup, this function has just
+ been implemented in terms of dl_iterate_phdr().
+ */
+
+ if (pid != getpid())
+ {
+ /* Return an error if an attempt is made to perform remote image lookup */
+ return -1;
+ }
+
+ if (dl_iterate_phdr (callback, &cbi) != 0)
+ {
+ if (path)
+ {
+ strncpy (path, cbi.path, pathlen);
+ }
+
+ *mapoff = cbi.offset;
+ *segbase = cbi.segbase;
+
+ ret = elf_map_image (ei, cbi.path);
+ }
+
+ return ret;
+}
+
+#ifndef UNW_REMOTE_ONLY
+
+void
+tdep_get_exe_image_path (char *path)
+{
+ path[0] = 0; /* XXX */
+}
+
+#endif
diff --git a/src/pal/src/libunwind/src/ppc/Gapply_reg_state.c b/src/pal/src/libunwind/src/ppc/Gapply_reg_state.c
new file mode 100644
index 0000000000..82f056da67
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc/Gapply_reg_state.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+ void *reg_states_data)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
diff --git a/src/pal/src/libunwind/src/ppc/Gget_proc_info.c b/src/pal/src/libunwind/src/ppc/Gget_proc_info.c
new file mode 100644
index 0000000000..7dfb6d4e42
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc/Gget_proc_info.c
@@ -0,0 +1,41 @@
+/* libunwind - a platform-independent unwind library
+
+ Copied from src/x86_64/, modified slightly (or made empty stubs) for
+ building frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <libunwind_i.h>
+
+int
+unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ ret = dwarf_make_proc_info (&c->dwarf);
+ if (ret < 0)
+ return ret;
+
+ *pi = c->dwarf.pi;
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/ppc/Gget_save_loc.c b/src/pal/src/libunwind/src/ppc/Gget_save_loc.c
new file mode 100644
index 0000000000..5343fa4c7f
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc/Gget_save_loc.c
@@ -0,0 +1,34 @@
+/* libunwind - a platform-independent unwind library
+
+ Copied from src/x86_64/, modified slightly (or made empty stubs) for
+ building frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <libunwind_i.h>
+
+int
+unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
+{
+ /* XXX: empty stub. */
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/ppc/Ginit_local.c b/src/pal/src/libunwind/src/ppc/Ginit_local.c
new file mode 100644
index 0000000000..366cf5bdaf
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc/Ginit_local.c
@@ -0,0 +1,88 @@
+/* libunwind - a platform-independent unwind library
+
+ Copied from src/x86_64/, modified slightly (or made empty stubs) for
+ building frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <libunwind_i.h>
+
+#ifdef UNW_TARGET_PPC64
+#include "../ppc64/init.h"
+#else
+#include "../ppc32/init.h"
+#endif
+
+#ifdef UNW_REMOTE_ONLY
+
+int
+unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+{
+ /* XXX: empty stub. */
+ return -UNW_EINVAL;
+}
+
+#else /* !UNW_REMOTE_ONLY */
+
+static int
+unw_init_local_common(unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->dwarf.as = unw_local_addr_space;
+ c->dwarf.as_arg = uc;
+ #ifdef UNW_TARGET_PPC64
+ return common_init_ppc64 (c, use_prev_instr);
+ #else
+ return common_init_ppc32 (c, use_prev_instr);
+ #endif
+}
+
+int
+unw_init_local(unw_cursor_t *cursor, ucontext_t *uc)
+{
+ return unw_init_local_common(cursor, uc, 1);
+}
+
+int
+unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
+{
+ if (!flag)
+ {
+ return unw_init_local_common(cursor, uc, 1);
+ }
+ else if (flag == UNW_INIT_SIGNAL_FRAME)
+ {
+ return unw_init_local_common(cursor, uc, 0);
+ }
+ else
+ {
+ return -UNW_EINVAL;
+ }
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/ppc/Ginit_remote.c b/src/pal/src/libunwind/src/ppc/Ginit_remote.c
new file mode 100644
index 0000000000..ed85be8971
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc/Ginit_remote.c
@@ -0,0 +1,60 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <libunwind_i.h>
+
+#ifdef UNW_TARGET_PPC64
+#include "../ppc64/init.h"
+#else
+#include "../ppc32/init.h"
+#endif
+
+int
+unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
+{
+#ifdef UNW_LOCAL_ONLY
+ return -UNW_EINVAL;
+#else /* !UNW_LOCAL_ONLY */
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->dwarf.as = as;
+ c->dwarf.as_arg = as_arg;
+
+ #ifdef UNW_TARGET_PPC64
+ return common_init_ppc64 (c, 0);
+ #elif UNW_TARGET_PPC32
+ return common_init_ppc32 (c, 0);
+ #else
+ #error init_remote :: NO VALID PPC ARCH!
+ #endif
+#endif /* !UNW_LOCAL_ONLY */
+}
diff --git a/src/pal/src/libunwind/src/ppc/Gis_signal_frame.c b/src/pal/src/libunwind/src/ppc/Gis_signal_frame.c
new file mode 100644
index 0000000000..6184dd5d41
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc/Gis_signal_frame.c
@@ -0,0 +1,78 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <libunwind_i.h>
+
+int
+unw_is_signal_frame (unw_cursor_t * cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ unw_word_t w0, w1, i0, i1, i2, ip;
+ unw_addr_space_t as;
+ unw_accessors_t *a;
+ void *arg;
+ int ret;
+
+ as = c->dwarf.as;
+ as->validate = 1; /* Don't trust the ip */
+ arg = c->dwarf.as_arg;
+
+ /* Check if return address points at sigreturn sequence.
+ on ppc64 Linux that is (see libc.so):
+ 0x38210080 addi r1, r1, 128 // pop the stack
+ 0x380000ac li r0, 172 // invoke system service 172
+ 0x44000002 sc
+ */
+
+ ip = c->dwarf.ip;
+ if (ip == 0)
+ return 0;
+
+ /* Read up two 8-byte words at the IP. We are only looking at 3
+ consecutive 32-bit words, so the second 8-byte word needs to be
+ shifted right by 32 bits (think big-endian) */
+
+ a = unw_get_accessors_int (as);
+ if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0
+ || (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0)
+ return 0;
+
+ if (tdep_big_endian (as))
+ {
+ i0 = w0 >> 32;
+ i1 = w0 & 0xffffffffUL;
+ i2 = w1 >> 32;
+ }
+ else
+ {
+ i0 = w0 & 0xffffffffUL;
+ i1 = w0 >> 32;
+ i2 = w1 & 0xffffffffUL;
+ }
+
+ return (i0 == 0x38210080 && i1 == 0x380000ac && i2 == 0x44000002);
+}
diff --git a/src/pal/src/libunwind/src/ppc/Greg_states_iterate.c b/src/pal/src/libunwind/src/ppc/Greg_states_iterate.c
new file mode 100644
index 0000000000..a17dc1b561
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc/Greg_states_iterate.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+ unw_reg_states_callback cb, void *token)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
diff --git a/src/pal/src/libunwind/src/ppc/Lapply_reg_state.c b/src/pal/src/libunwind/src/ppc/Lapply_reg_state.c
new file mode 100644
index 0000000000..7ebada480e
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc/Lapply_reg_state.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc/Lget_proc_info.c b/src/pal/src/libunwind/src/ppc/Lget_proc_info.c
new file mode 100644
index 0000000000..69028b019f
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc/Lget_proc_info.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_proc_info.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc/Lget_save_loc.c b/src/pal/src/libunwind/src/ppc/Lget_save_loc.c
new file mode 100644
index 0000000000..9ea048a907
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc/Lget_save_loc.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_save_loc.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc/Linit_local.c b/src/pal/src/libunwind/src/ppc/Linit_local.c
new file mode 100644
index 0000000000..68a1687e85
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc/Linit_local.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_local.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc/Linit_remote.c b/src/pal/src/libunwind/src/ppc/Linit_remote.c
new file mode 100644
index 0000000000..58cb04ab7c
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc/Linit_remote.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_remote.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc/Lis_signal_frame.c b/src/pal/src/libunwind/src/ppc/Lis_signal_frame.c
new file mode 100644
index 0000000000..b9a7c4f51a
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc/Lis_signal_frame.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gis_signal_frame.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc/Lreg_states_iterate.c b/src/pal/src/libunwind/src/ppc/Lreg_states_iterate.c
new file mode 100644
index 0000000000..f1eb1e79dc
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc/Lreg_states_iterate.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc/longjmp.S b/src/pal/src/libunwind/src/ppc/longjmp.S
new file mode 100644
index 0000000000..d363aef222
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc/longjmp.S
@@ -0,0 +1,36 @@
+/* libunwind - a platform-independent unwind library
+
+ Copied from src/x86_64/, modified slightly (or made empty stubs) for
+ building frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+ .globl _UI_longjmp_cont
+
+ .type _UI_longjmp_cont, @function
+_UI_longjmp_cont:
+ .size _UI_longjmp_cont, .-_UI_longjmp_cont
+
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/src/ppc/siglongjmp.S b/src/pal/src/libunwind/src/ppc/siglongjmp.S
new file mode 100644
index 0000000000..64be36ce17
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc/siglongjmp.S
@@ -0,0 +1,31 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+ .globl _UI_siglongjmp_cont
+
+ _UI_siglongjmp_cont:
+
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/src/ppc32/Gapply_reg_state.c b/src/pal/src/libunwind/src/ppc32/Gapply_reg_state.c
new file mode 100644
index 0000000000..82f056da67
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/Gapply_reg_state.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+ void *reg_states_data)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
diff --git a/src/pal/src/libunwind/src/ppc32/Gcreate_addr_space.c b/src/pal/src/libunwind/src/ppc32/Gcreate_addr_space.c
new file mode 100644
index 0000000000..aaa68bb354
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/Gcreate_addr_space.c
@@ -0,0 +1,56 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+
+#include <libunwind_i.h>
+
+unw_addr_space_t
+unw_create_addr_space (unw_accessors_t *a, int byte_order)
+{
+#ifdef UNW_LOCAL_ONLY
+ return NULL;
+#else
+ unw_addr_space_t as;
+
+ /*
+ * We support only big-endian on Linux ppc32.
+ */
+ if (byte_order != 0 && byte_order != __BIG_ENDIAN)
+ return NULL;
+
+ as = malloc (sizeof (*as));
+ if (!as)
+ return NULL;
+
+ memset (as, 0, sizeof (*as));
+
+ as->acc = *a;
+
+ return as;
+#endif
+}
diff --git a/src/pal/src/libunwind/src/ppc32/Gglobal.c b/src/pal/src/libunwind/src/ppc32/Gglobal.c
new file mode 100644
index 0000000000..a0f80beec6
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/Gglobal.c
@@ -0,0 +1,135 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "dwarf_i.h"
+
+HIDDEN define_lock (ppc32_lock);
+HIDDEN int tdep_init_done;
+
+/* The API register numbers are exactly the same as the .eh_frame
+ registers, for now at least. */
+HIDDEN const uint8_t dwarf_to_unw_regnum_map[DWARF_REGNUM_MAP_LENGTH] =
+ {
+ [UNW_PPC32_R0]=UNW_PPC32_R0,
+ [UNW_PPC32_R1]=UNW_PPC32_R1,
+ [UNW_PPC32_R2]=UNW_PPC32_R2,
+ [UNW_PPC32_R3]=UNW_PPC32_R3,
+ [UNW_PPC32_R4]=UNW_PPC32_R4,
+ [UNW_PPC32_R5]=UNW_PPC32_R5,
+ [UNW_PPC32_R6]=UNW_PPC32_R6,
+ [UNW_PPC32_R7]=UNW_PPC32_R7,
+ [UNW_PPC32_R8]=UNW_PPC32_R8,
+ [UNW_PPC32_R9]=UNW_PPC32_R9,
+ [UNW_PPC32_R10]=UNW_PPC32_R10,
+ [UNW_PPC32_R11]=UNW_PPC32_R11,
+ [UNW_PPC32_R12]=UNW_PPC32_R12,
+ [UNW_PPC32_R13]=UNW_PPC32_R13,
+ [UNW_PPC32_R14]=UNW_PPC32_R14,
+ [UNW_PPC32_R15]=UNW_PPC32_R15,
+ [UNW_PPC32_R16]=UNW_PPC32_R16,
+ [UNW_PPC32_R17]=UNW_PPC32_R17,
+ [UNW_PPC32_R18]=UNW_PPC32_R18,
+ [UNW_PPC32_R19]=UNW_PPC32_R19,
+ [UNW_PPC32_R20]=UNW_PPC32_R20,
+ [UNW_PPC32_R21]=UNW_PPC32_R21,
+ [UNW_PPC32_R22]=UNW_PPC32_R22,
+ [UNW_PPC32_R23]=UNW_PPC32_R23,
+ [UNW_PPC32_R24]=UNW_PPC32_R24,
+ [UNW_PPC32_R25]=UNW_PPC32_R25,
+ [UNW_PPC32_R26]=UNW_PPC32_R26,
+ [UNW_PPC32_R27]=UNW_PPC32_R27,
+ [UNW_PPC32_R28]=UNW_PPC32_R28,
+ [UNW_PPC32_R29]=UNW_PPC32_R29,
+ [UNW_PPC32_R30]=UNW_PPC32_R30,
+ [UNW_PPC32_R31]=UNW_PPC32_R31,
+
+ [UNW_PPC32_CTR]=UNW_PPC32_CTR,
+ [UNW_PPC32_XER]=UNW_PPC32_XER,
+ [UNW_PPC32_CCR]=UNW_PPC32_CCR,
+ [UNW_PPC32_LR]=UNW_PPC32_LR,
+ [UNW_PPC32_FPSCR]=UNW_PPC32_FPSCR,
+
+ [UNW_PPC32_F0]=UNW_PPC32_F0,
+ [UNW_PPC32_F1]=UNW_PPC32_F1,
+ [UNW_PPC32_F2]=UNW_PPC32_F2,
+ [UNW_PPC32_F3]=UNW_PPC32_F3,
+ [UNW_PPC32_F4]=UNW_PPC32_F4,
+ [UNW_PPC32_F5]=UNW_PPC32_F5,
+ [UNW_PPC32_F6]=UNW_PPC32_F6,
+ [UNW_PPC32_F7]=UNW_PPC32_F7,
+ [UNW_PPC32_F8]=UNW_PPC32_F8,
+ [UNW_PPC32_F9]=UNW_PPC32_F9,
+ [UNW_PPC32_F10]=UNW_PPC32_F10,
+ [UNW_PPC32_F11]=UNW_PPC32_F11,
+ [UNW_PPC32_F12]=UNW_PPC32_F12,
+ [UNW_PPC32_F13]=UNW_PPC32_F13,
+ [UNW_PPC32_F14]=UNW_PPC32_F14,
+ [UNW_PPC32_F15]=UNW_PPC32_F15,
+ [UNW_PPC32_F16]=UNW_PPC32_F16,
+ [UNW_PPC32_F17]=UNW_PPC32_F17,
+ [UNW_PPC32_F18]=UNW_PPC32_F18,
+ [UNW_PPC32_F19]=UNW_PPC32_F19,
+ [UNW_PPC32_F20]=UNW_PPC32_F20,
+ [UNW_PPC32_F21]=UNW_PPC32_F21,
+ [UNW_PPC32_F22]=UNW_PPC32_F22,
+ [UNW_PPC32_F23]=UNW_PPC32_F23,
+ [UNW_PPC32_F24]=UNW_PPC32_F24,
+ [UNW_PPC32_F25]=UNW_PPC32_F25,
+ [UNW_PPC32_F26]=UNW_PPC32_F26,
+ [UNW_PPC32_F27]=UNW_PPC32_F27,
+ [UNW_PPC32_F28]=UNW_PPC32_F28,
+ [UNW_PPC32_F29]=UNW_PPC32_F29,
+ [UNW_PPC32_F30]=UNW_PPC32_F30,
+ [UNW_PPC32_F31]=UNW_PPC32_F31,
+};
+
+HIDDEN void
+tdep_init (void)
+{
+ intrmask_t saved_mask;
+
+ sigfillset (&unwi_full_mask);
+
+ lock_acquire (&ppc32_lock, saved_mask);
+ {
+ if (tdep_init_done)
+ /* another thread else beat us to it... */
+ goto out;
+
+ mi_init ();
+
+ dwarf_init ();
+
+#ifndef UNW_REMOTE_ONLY
+ ppc32_local_addr_space_init ();
+#endif
+ tdep_init_done = 1; /* signal that we're initialized... */
+ }
+ out:
+ lock_release (&ppc32_lock, saved_mask);
+}
diff --git a/src/pal/src/libunwind/src/ppc32/Ginit.c b/src/pal/src/libunwind/src/ppc32/Ginit.c
new file mode 100644
index 0000000000..ba302448a3
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/Ginit.c
@@ -0,0 +1,216 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "ucontext_i.h"
+#include "unwind_i.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+/* unw_local_addr_space is a NULL pointer in this case. */
+unw_addr_space_t unw_local_addr_space;
+
+#else /* !UNW_REMOTE_ONLY */
+
+static struct unw_addr_space local_addr_space;
+
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
+
+static void *
+uc_addr (ucontext_t *uc, int reg)
+{
+ void *addr;
+
+ if ((unsigned) (reg - UNW_PPC32_R0) < 32)
+ addr = &uc->uc_mcontext.uc_regs->gregs[reg - UNW_PPC32_R0];
+
+ else
+ if ( ((unsigned) (reg - UNW_PPC32_F0) < 32) &&
+ ((unsigned) (reg - UNW_PPC32_F0) >= 0) )
+ addr = &uc->uc_mcontext.uc_regs->fpregs.fpregs[reg - UNW_PPC32_F0];
+
+ else
+ {
+ unsigned gregs_idx;
+
+ switch (reg)
+ {
+ case UNW_PPC32_CTR:
+ gregs_idx = CTR_IDX;
+ break;
+ case UNW_PPC32_LR:
+ gregs_idx = LINK_IDX;
+ break;
+ case UNW_PPC32_XER:
+ gregs_idx = XER_IDX;
+ break;
+ case UNW_PPC32_CCR:
+ gregs_idx = CCR_IDX;
+ break;
+ default:
+ return NULL;
+ }
+ addr = &uc->uc_mcontext.uc_regs->gregs[gregs_idx];
+ }
+ return addr;
+}
+
+# ifdef UNW_LOCAL_ONLY
+
+HIDDEN void *
+tdep_uc_addr (ucontext_t *uc, int reg)
+{
+ return uc_addr (uc, reg);
+}
+
+# endif /* UNW_LOCAL_ONLY */
+
+HIDDEN unw_dyn_info_list_t _U_dyn_info_list;
+
+
+static void
+put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
+{
+ /* it's a no-op */
+}
+
+static int
+get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
+ void *arg)
+{
+ *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list;
+ return 0;
+}
+
+static int
+access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
+ void *arg)
+{
+ if (write)
+ {
+ Debug (12, "mem[%lx] <- %lx\n", addr, *val);
+ *(unw_word_t *) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_word_t *) addr;
+ Debug (12, "mem[%lx] -> %lx\n", addr, *val);
+ }
+ return 0;
+}
+
+static int
+access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val,
+ int write, void *arg)
+{
+ unw_word_t *addr;
+ ucontext_t *uc = arg;
+
+ if ( ((unsigned int) (reg - UNW_PPC32_F0) < 32) &&
+ ((unsigned int) (reg - UNW_PPC32_F0) >= 0))
+ goto badreg;
+
+ addr = uc_addr (uc, reg);
+ if (!addr)
+ goto badreg;
+
+ if (write)
+ {
+ *(unw_word_t *) addr = *val;
+ Debug (12, "%s <- %lx\n", unw_regname (reg), *val);
+ }
+ else
+ {
+ *val = *(unw_word_t *) addr;
+ Debug (12, "%s -> %lx\n", unw_regname (reg), *val);
+ }
+ return 0;
+
+badreg:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+}
+
+static int
+access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
+ int write, void *arg)
+{
+ ucontext_t *uc = arg;
+ unw_fpreg_t *addr;
+
+ if ((unsigned) (reg - UNW_PPC32_F0) < 0)
+ goto badreg;
+
+ addr = uc_addr (uc, reg);
+ if (!addr)
+ goto badreg;
+
+ if (write)
+ {
+ Debug (12, "%s <- %016Lf\n", unw_regname (reg), *val);
+ *(unw_fpreg_t *) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_fpreg_t *) addr;
+ Debug (12, "%s -> %016Lf\n", unw_regname (reg), *val);
+ }
+ return 0;
+
+badreg:
+ Debug (1, "bad register number %u\n", reg);
+ /* attempt to access a non-preserved register */
+ return -UNW_EBADREG;
+}
+
+static int
+get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
+ char *buf, size_t buf_len, unw_word_t *offp,
+ void *arg)
+{
+ return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
+}
+
+HIDDEN void
+ppc32_local_addr_space_init (void)
+{
+ memset (&local_addr_space, 0, sizeof (local_addr_space));
+ local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
+ local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
+ local_addr_space.acc.put_unwind_info = put_unwind_info;
+ local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
+ local_addr_space.acc.access_mem = access_mem;
+ local_addr_space.acc.access_reg = access_reg;
+ local_addr_space.acc.access_fpreg = access_fpreg;
+ local_addr_space.acc.resume = ppc32_local_resume;
+ local_addr_space.acc.get_proc_name = get_static_proc_name;
+ unw_flush_cache (&local_addr_space, 0, 0);
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/ppc32/Greg_states_iterate.c b/src/pal/src/libunwind/src/ppc32/Greg_states_iterate.c
new file mode 100644
index 0000000000..a17dc1b561
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/Greg_states_iterate.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+ unw_reg_states_callback cb, void *token)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
diff --git a/src/pal/src/libunwind/src/ppc32/Gregs.c b/src/pal/src/libunwind/src/ppc32/Gregs.c
new file mode 100644
index 0000000000..9344455e6c
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/Gregs.c
@@ -0,0 +1,90 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+HIDDEN int
+tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
+ int write)
+{
+ struct dwarf_loc loc;
+
+ switch (reg)
+ {
+ case UNW_TDEP_IP:
+ if (write)
+ {
+ c->dwarf.ip = *valp; /* update the IP cache */
+ if (c->dwarf.pi_valid && (*valp < c->dwarf.pi.start_ip
+ || *valp >= c->dwarf.pi.end_ip))
+ c->dwarf.pi_valid = 0; /* new IP outside of current proc */
+ }
+ else
+ *valp = c->dwarf.ip;
+ return 0;
+
+ case UNW_TDEP_SP:
+ if (write)
+ return -UNW_EREADONLYREG;
+ *valp = c->dwarf.cfa;
+ return 0;
+
+
+ default:
+ break;
+ }
+
+ /* make sure it's not an FP or VR register */
+ if ((((unsigned) (reg - UNW_PPC32_F0)) <= 31))
+ return -UNW_EBADREG;
+
+ loc = c->dwarf.loc[reg];
+
+ if (write)
+ return dwarf_put (&c->dwarf, loc, *valp);
+ else
+ return dwarf_get (&c->dwarf, loc, valp);
+}
+
+HIDDEN int
+tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
+ int write)
+{
+ struct dwarf_loc loc;
+
+ if ((unsigned) (reg - UNW_PPC32_F0) < 32)
+ {
+ loc = c->dwarf.loc[reg];
+ if (write)
+ return dwarf_putfp (&c->dwarf, loc, *valp);
+ else
+ return dwarf_getfp (&c->dwarf, loc, valp);
+ }
+
+ return -UNW_EBADREG;
+}
+
diff --git a/src/pal/src/libunwind/src/ppc32/Gresume.c b/src/pal/src/libunwind/src/ppc32/Gresume.c
new file mode 100644
index 0000000000..c0f95837b3
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/Gresume.c
@@ -0,0 +1,77 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford cjashfor@us.ibm.com
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+
+#include "unwind_i.h"
+
+#ifndef UNW_REMOTE_ONLY
+
+#include <sys/syscall.h>
+
+/* sigreturn() is a no-op on x86_64 glibc. */
+
+static NORETURN inline long
+my_rt_sigreturn (void *new_sp)
+{
+ /* XXX: empty stub. */
+ abort ();
+}
+
+HIDDEN inline int
+ppc32_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
+{
+ /* XXX: empty stub. */
+ return -UNW_EINVAL;
+}
+
+#endif /* !UNW_REMOTE_ONLY */
+
+/* This routine is responsible for copying the register values in
+ cursor C and establishing them as the current machine state. */
+
+static inline int
+establish_machine_state (struct cursor *c)
+{
+ /* XXX: empty stub. */
+ return 0;
+}
+
+int
+unw_resume (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ if ((ret = establish_machine_state (c)) < 0)
+ return ret;
+
+ return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c,
+ c->dwarf.as_arg);
+}
diff --git a/src/pal/src/libunwind/src/ppc32/Gstep.c b/src/pal/src/libunwind/src/ppc32/Gstep.c
new file mode 100644
index 0000000000..478d3a6c1b
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/Gstep.c
@@ -0,0 +1,309 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "ucontext_i.h"
+#include <signal.h>
+
+/* This definition originates in /usr/include/asm-ppc64/ptrace.h, but is
+ defined there only when __KERNEL__ is defined. We reproduce it here for
+ our use at the user level in order to locate the ucontext record, which
+ appears to be at this offset relative to the stack pointer when in the
+ context of the signal handler return trampoline code -
+ __kernel_sigtramp_rt64. */
+#define __SIGNAL_FRAMESIZE 128
+
+/* This definition comes from the document "64-bit PowerPC ELF Application
+ Binary Interface Supplement 1.9", section 3.2.2.
+ http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK */
+
+typedef struct
+{
+ long unsigned back_chain;
+ long unsigned lr_save;
+ /* many more fields here, but they are unused by this code */
+} stack_frame_t;
+
+
+int
+unw_step (unw_cursor_t * cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ stack_frame_t dummy;
+ unw_word_t back_chain_offset, lr_save_offset;
+ struct dwarf_loc back_chain_loc, lr_save_loc, sp_loc, ip_loc;
+ int ret;
+
+ Debug (1, "(cursor=%p, ip=0x%016lx)\n", c, (unsigned long) c->dwarf.ip);
+
+ if (c->dwarf.ip == 0)
+ {
+ /* Unless the cursor or stack is corrupt or uninitialized,
+ we've most likely hit the top of the stack */
+ return 0;
+ }
+
+ /* Try DWARF-based unwinding... */
+
+ ret = dwarf_step (&c->dwarf);
+
+ if (ret < 0 && ret != -UNW_ENOINFO)
+ {
+ Debug (2, "returning %d\n", ret);
+ return ret;
+ }
+
+ if (unlikely (ret < 0))
+ {
+ if (likely (unw_is_signal_frame (cursor) <= 0))
+ {
+ /* DWARF unwinding failed. As of 09/26/2006, gcc in 64-bit mode
+ produces the mandatory level of traceback record in the code, but
+ I get the impression that this is transitory, that eventually gcc
+ will not produce any traceback records at all. So, for now, we
+ won't bother to try to find and use these records.
+
+ We can, however, attempt to unwind the frame by using the callback
+ chain. This is very crude, however, and won't be able to unwind
+ any registers besides the IP, SP, and LR . */
+
+ back_chain_offset = ((void *) &dummy.back_chain - (void *) &dummy);
+ lr_save_offset = ((void *) &dummy.lr_save - (void *) &dummy);
+
+ back_chain_loc = DWARF_LOC (c->dwarf.cfa + back_chain_offset, 0);
+
+ if ((ret =
+ dwarf_get (&c->dwarf, back_chain_loc, &c->dwarf.cfa)) < 0)
+ {
+ Debug (2,
+ "Unable to retrieve CFA from back chain in stack frame - %d\n",
+ ret);
+ return ret;
+ }
+ if (c->dwarf.cfa == 0)
+ /* Unless the cursor or stack is corrupt or uninitialized we've most
+ likely hit the top of the stack */
+ return 0;
+
+ lr_save_loc = DWARF_LOC (c->dwarf.cfa + lr_save_offset, 0);
+
+ if ((ret = dwarf_get (&c->dwarf, lr_save_loc, &c->dwarf.ip)) < 0)
+ {
+ Debug (2,
+ "Unable to retrieve IP from lr save in stack frame - %d\n",
+ ret);
+ return ret;
+ }
+ ret = 1;
+ }
+ else
+ {
+ /* Find the sigcontext record by taking the CFA and adjusting by
+ the dummy signal frame size.
+
+ Note that there isn't any way to determined if SA_SIGINFO was
+ set in the sa_flags parameter to sigaction when the signal
+ handler was established. If it was not set, the ucontext
+ record is not required to be on the stack, in which case the
+ following code will likely cause a seg fault or other crash
+ condition. */
+
+ unw_word_t ucontext = c->dwarf.cfa + __SIGNAL_FRAMESIZE;
+
+ Debug (1, "signal frame, skip over trampoline\n");
+
+ c->sigcontext_format = PPC_SCF_LINUX_RT_SIGFRAME;
+ c->sigcontext_addr = ucontext;
+
+ sp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0);
+ ip_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_LINK, 0);
+
+ ret = dwarf_get (&c->dwarf, sp_loc, &c->dwarf.cfa);
+ if (ret < 0)
+ {
+ Debug (2, "returning %d\n", ret);
+ return ret;
+ }
+ ret = dwarf_get (&c->dwarf, ip_loc, &c->dwarf.ip);
+ if (ret < 0)
+ {
+ Debug (2, "returning %d\n", ret);
+ return ret;
+ }
+
+ /* Instead of just restoring the non-volatile registers, do all
+ of the registers for now. This will incur a performance hit,
+ but it's rare enough not to cause too much of a problem, and
+ might be useful in some cases. */
+ c->dwarf.loc[UNW_PPC32_R0] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R0, 0);
+ c->dwarf.loc[UNW_PPC32_R1] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0);
+ c->dwarf.loc[UNW_PPC32_R2] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R2, 0);
+ c->dwarf.loc[UNW_PPC32_R3] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R3, 0);
+ c->dwarf.loc[UNW_PPC32_R4] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R4, 0);
+ c->dwarf.loc[UNW_PPC32_R5] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R5, 0);
+ c->dwarf.loc[UNW_PPC32_R6] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R6, 0);
+ c->dwarf.loc[UNW_PPC32_R7] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R7, 0);
+ c->dwarf.loc[UNW_PPC32_R8] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0);
+ c->dwarf.loc[UNW_PPC32_R9] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0);
+ c->dwarf.loc[UNW_PPC32_R10] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0);
+ c->dwarf.loc[UNW_PPC32_R11] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0);
+ c->dwarf.loc[UNW_PPC32_R12] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0);
+ c->dwarf.loc[UNW_PPC32_R13] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0);
+ c->dwarf.loc[UNW_PPC32_R14] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0);
+ c->dwarf.loc[UNW_PPC32_R15] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0);
+ c->dwarf.loc[UNW_PPC32_R16] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R16, 0);
+ c->dwarf.loc[UNW_PPC32_R17] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R17, 0);
+ c->dwarf.loc[UNW_PPC32_R18] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R18, 0);
+ c->dwarf.loc[UNW_PPC32_R19] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R19, 0);
+ c->dwarf.loc[UNW_PPC32_R20] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R20, 0);
+ c->dwarf.loc[UNW_PPC32_R21] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R21, 0);
+ c->dwarf.loc[UNW_PPC32_R22] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R22, 0);
+ c->dwarf.loc[UNW_PPC32_R23] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R23, 0);
+ c->dwarf.loc[UNW_PPC32_R24] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R24, 0);
+ c->dwarf.loc[UNW_PPC32_R25] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R25, 0);
+ c->dwarf.loc[UNW_PPC32_R26] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R26, 0);
+ c->dwarf.loc[UNW_PPC32_R27] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R27, 0);
+ c->dwarf.loc[UNW_PPC32_R28] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R28, 0);
+ c->dwarf.loc[UNW_PPC32_R29] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R29, 0);
+ c->dwarf.loc[UNW_PPC32_R30] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R30, 0);
+ c->dwarf.loc[UNW_PPC32_R31] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R31, 0);
+
+ c->dwarf.loc[UNW_PPC32_LR] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_LINK, 0);
+ c->dwarf.loc[UNW_PPC32_CTR] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CTR, 0);
+
+ /* This CR0 assignment is probably wrong. There are 8 dwarf columns
+ assigned to the CR registers, but only one CR register in the
+ mcontext structure */
+ c->dwarf.loc[UNW_PPC32_CCR] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CCR, 0);
+ c->dwarf.loc[UNW_PPC32_XER] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_XER, 0);
+
+ c->dwarf.loc[UNW_PPC32_F0] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R0, 0);
+ c->dwarf.loc[UNW_PPC32_F1] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R1, 0);
+ c->dwarf.loc[UNW_PPC32_F2] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R2, 0);
+ c->dwarf.loc[UNW_PPC32_F3] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R3, 0);
+ c->dwarf.loc[UNW_PPC32_F4] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R4, 0);
+ c->dwarf.loc[UNW_PPC32_F5] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R5, 0);
+ c->dwarf.loc[UNW_PPC32_F6] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R6, 0);
+ c->dwarf.loc[UNW_PPC32_F7] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R7, 0);
+ c->dwarf.loc[UNW_PPC32_F8] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R8, 0);
+ c->dwarf.loc[UNW_PPC32_F9] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R9, 0);
+ c->dwarf.loc[UNW_PPC32_F10] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R10, 0);
+ c->dwarf.loc[UNW_PPC32_F11] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R11, 0);
+ c->dwarf.loc[UNW_PPC32_F12] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R12, 0);
+ c->dwarf.loc[UNW_PPC32_F13] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R13, 0);
+ c->dwarf.loc[UNW_PPC32_F14] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R14, 0);
+ c->dwarf.loc[UNW_PPC32_F15] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R15, 0);
+ c->dwarf.loc[UNW_PPC32_F16] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R16, 0);
+ c->dwarf.loc[UNW_PPC32_F17] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R17, 0);
+ c->dwarf.loc[UNW_PPC32_F18] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R18, 0);
+ c->dwarf.loc[UNW_PPC32_F19] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R19, 0);
+ c->dwarf.loc[UNW_PPC32_F20] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R20, 0);
+ c->dwarf.loc[UNW_PPC32_F21] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R21, 0);
+ c->dwarf.loc[UNW_PPC32_F22] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R22, 0);
+ c->dwarf.loc[UNW_PPC32_F23] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R23, 0);
+ c->dwarf.loc[UNW_PPC32_F24] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R24, 0);
+ c->dwarf.loc[UNW_PPC32_F25] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R25, 0);
+ c->dwarf.loc[UNW_PPC32_F26] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R26, 0);
+ c->dwarf.loc[UNW_PPC32_F27] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R27, 0);
+ c->dwarf.loc[UNW_PPC32_F28] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R28, 0);
+ c->dwarf.loc[UNW_PPC32_F29] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R29, 0);
+ c->dwarf.loc[UNW_PPC32_F30] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R30, 0);
+ c->dwarf.loc[UNW_PPC32_F31] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R31, 0);
+
+ ret = 1;
+ }
+ }
+ return ret;
+}
diff --git a/src/pal/src/libunwind/src/ppc32/Lapply_reg_state.c b/src/pal/src/libunwind/src/ppc32/Lapply_reg_state.c
new file mode 100644
index 0000000000..7ebada480e
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/Lapply_reg_state.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc32/Lcreate_addr_space.c b/src/pal/src/libunwind/src/ppc32/Lcreate_addr_space.c
new file mode 100644
index 0000000000..0f2dc6be90
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/Lcreate_addr_space.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gcreate_addr_space.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc32/Lglobal.c b/src/pal/src/libunwind/src/ppc32/Lglobal.c
new file mode 100644
index 0000000000..6d7b489e14
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/Lglobal.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gglobal.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc32/Linit.c b/src/pal/src/libunwind/src/ppc32/Linit.c
new file mode 100644
index 0000000000..e9abfdd46a
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/Linit.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc32/Lreg_states_iterate.c b/src/pal/src/libunwind/src/ppc32/Lreg_states_iterate.c
new file mode 100644
index 0000000000..f1eb1e79dc
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/Lreg_states_iterate.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc32/Lregs.c b/src/pal/src/libunwind/src/ppc32/Lregs.c
new file mode 100644
index 0000000000..2c9c75cd7d
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/Lregs.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gregs.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc32/Lresume.c b/src/pal/src/libunwind/src/ppc32/Lresume.c
new file mode 100644
index 0000000000..41a8cf003d
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/Lresume.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gresume.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc32/Lstep.c b/src/pal/src/libunwind/src/ppc32/Lstep.c
new file mode 100644
index 0000000000..c1ac3c7547
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/Lstep.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gstep.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc32/Make-arch.in b/src/pal/src/libunwind/src/ppc32/Make-arch.in
new file mode 100644
index 0000000000..947dd5fa03
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/Make-arch.in
@@ -0,0 +1,11 @@
+# Word size.
+ELFW = 64
+# Does use dwarf2 unwind info.
+dwarf_target = true
+
+libunwind_setjmp_OBJS += \
+ $(arch)/longjmp.o \
+ $(arch)/siglongjmp.o
+
+libunwind_OBJS_common += \
+ $(arch)/is_fpreg.o
diff --git a/src/pal/src/libunwind/src/ppc32/get_func_addr.c b/src/pal/src/libunwind/src/ppc32/get_func_addr.c
new file mode 100644
index 0000000000..66ff795fe7
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/get_func_addr.c
@@ -0,0 +1,36 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+tdep_get_func_addr (unw_addr_space_t as, unw_word_t symbol_val_addr,
+ unw_word_t *real_func_addr)
+{
+ *real_func_addr = symbol_val_addr;
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/ppc32/init.h b/src/pal/src/libunwind/src/ppc32/init.h
new file mode 100644
index 0000000000..87a69b1450
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/init.h
@@ -0,0 +1,72 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+/* Here is the "common" init, for remote and local debuging" */
+
+static inline int
+common_init_ppc32 (struct cursor *c, unsigned use_prev_instr)
+{
+ int ret;
+ int i;
+
+ for (i = UNW_PPC32_R0; i <= UNW_PPC32_R31; i++) {
+ c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, i);
+ }
+ for (i = UNW_PPC32_F0; i <= UNW_PPC32_F31; i++) {
+ c->dwarf.loc[i] = DWARF_FPREG_LOC (&c->dwarf, i);
+ }
+
+ c->dwarf.loc[UNW_PPC32_CTR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC32_CTR);
+ c->dwarf.loc[UNW_PPC32_XER] = DWARF_REG_LOC (&c->dwarf, UNW_PPC32_XER);
+ c->dwarf.loc[UNW_PPC32_CCR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC32_CCR);
+ c->dwarf.loc[UNW_PPC32_LR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC32_LR);
+ c->dwarf.loc[UNW_PPC32_FPSCR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC32_FPSCR);
+
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_PPC32_LR], &c->dwarf.ip);
+ if (ret < 0)
+ return ret;
+
+ ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_PPC32_R1),
+ &c->dwarf.cfa);
+ if (ret < 0)
+ return ret;
+
+ c->sigcontext_format = PPC_SCF_NONE;
+ c->sigcontext_addr = 0;
+
+ c->dwarf.args_size = 0;
+ c->dwarf.stash_frames = 0;
+ c->dwarf.use_prev_instr = use_prev_instr;
+ c->dwarf.pi_valid = 0;
+ c->dwarf.pi_is_dynamic = 0;
+ c->dwarf.hint = 0;
+ c->dwarf.prev_rs = 0;
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/ppc32/is_fpreg.c b/src/pal/src/libunwind/src/ppc32/is_fpreg.c
new file mode 100644
index 0000000000..646ff2379c
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/is_fpreg.c
@@ -0,0 +1,34 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+int
+unw_is_fpreg (int regnum)
+{
+ return (regnum >= UNW_PPC32_F0 && regnum <= UNW_PPC32_F31);
+}
diff --git a/src/pal/src/libunwind/src/ppc32/regname.c b/src/pal/src/libunwind/src/ppc32/regname.c
new file mode 100644
index 0000000000..459b83a4e5
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/regname.c
@@ -0,0 +1,112 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+static const char *regname[] =
+ {
+ [UNW_PPC32_R0]="GPR0",
+ [UNW_PPC32_R1]="GPR1",
+ [UNW_PPC32_R2]="GPR2",
+ [UNW_PPC32_R3]="GPR3",
+ [UNW_PPC32_R4]="GPR4",
+ [UNW_PPC32_R5]="GPR5",
+ [UNW_PPC32_R6]="GPR6",
+ [UNW_PPC32_R7]="GPR7",
+ [UNW_PPC32_R8]="GPR8",
+ [UNW_PPC32_R9]="GPR9",
+ [UNW_PPC32_R10]="GPR10",
+ [UNW_PPC32_R11]="GPR11",
+ [UNW_PPC32_R12]="GPR12",
+ [UNW_PPC32_R13]="GPR13",
+ [UNW_PPC32_R14]="GPR14",
+ [UNW_PPC32_R15]="GPR15",
+ [UNW_PPC32_R16]="GPR16",
+ [UNW_PPC32_R17]="GPR17",
+ [UNW_PPC32_R18]="GPR18",
+ [UNW_PPC32_R19]="GPR19",
+ [UNW_PPC32_R20]="GPR20",
+ [UNW_PPC32_R21]="GPR21",
+ [UNW_PPC32_R22]="GPR22",
+ [UNW_PPC32_R23]="GPR23",
+ [UNW_PPC32_R24]="GPR24",
+ [UNW_PPC32_R25]="GPR25",
+ [UNW_PPC32_R26]="GPR26",
+ [UNW_PPC32_R27]="GPR27",
+ [UNW_PPC32_R28]="GPR28",
+ [UNW_PPC32_R29]="GPR29",
+ [UNW_PPC32_R30]="GPR30",
+ [UNW_PPC32_R31]="GPR31",
+
+ [UNW_PPC32_CTR]="CTR",
+ [UNW_PPC32_XER]="XER",
+ [UNW_PPC32_CCR]="CCR",
+ [UNW_PPC32_LR]="LR",
+ [UNW_PPC32_FPSCR]="FPSCR",
+
+ [UNW_PPC32_F0]="FPR0",
+ [UNW_PPC32_F1]="FPR1",
+ [UNW_PPC32_F2]="FPR2",
+ [UNW_PPC32_F3]="FPR3",
+ [UNW_PPC32_F4]="FPR4",
+ [UNW_PPC32_F5]="FPR5",
+ [UNW_PPC32_F6]="FPR6",
+ [UNW_PPC32_F7]="FPR7",
+ [UNW_PPC32_F8]="FPR8",
+ [UNW_PPC32_F9]="FPR9",
+ [UNW_PPC32_F10]="FPR10",
+ [UNW_PPC32_F11]="FPR11",
+ [UNW_PPC32_F12]="FPR12",
+ [UNW_PPC32_F13]="FPR13",
+ [UNW_PPC32_F14]="FPR14",
+ [UNW_PPC32_F15]="FPR15",
+ [UNW_PPC32_F16]="FPR16",
+ [UNW_PPC32_F17]="FPR17",
+ [UNW_PPC32_F18]="FPR18",
+ [UNW_PPC32_F19]="FPR19",
+ [UNW_PPC32_F20]="FPR20",
+ [UNW_PPC32_F21]="FPR21",
+ [UNW_PPC32_F22]="FPR22",
+ [UNW_PPC32_F23]="FPR23",
+ [UNW_PPC32_F24]="FPR24",
+ [UNW_PPC32_F25]="FPR25",
+ [UNW_PPC32_F26]="FPR26",
+ [UNW_PPC32_F27]="FPR27",
+ [UNW_PPC32_F28]="FPR28",
+ [UNW_PPC32_F29]="FPR29",
+ [UNW_PPC32_F30]="FPR30",
+ [UNW_PPC32_F31]="FPR31"
+};
+
+const char *
+unw_regname (unw_regnum_t reg)
+{
+ if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
+ return regname[reg];
+ else
+ return "???";
+}
diff --git a/src/pal/src/libunwind/src/ppc32/setcontext.S b/src/pal/src/libunwind/src/ppc32/setcontext.S
new file mode 100644
index 0000000000..b54378a9dc
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/setcontext.S
@@ -0,0 +1,9 @@
+ .global _UI_setcontext
+
+_UI_setcontext:
+ retq
+
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/src/ppc32/ucontext_i.h b/src/pal/src/libunwind/src/ppc32/ucontext_i.h
new file mode 100644
index 0000000000..c6ba806a00
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/ucontext_i.h
@@ -0,0 +1,128 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef ucontext_i_h
+#define ucontext_i_h
+
+#include "compiler.h"
+#include <ucontext.h>
+
+/* These values were derived by reading
+ /usr/src/linux-2.6.18-1.8/arch/um/include/sysdep-ppc/ptrace.h and
+ /usr/src/linux-2.6.18-1.8/arch/powerpc/kernel/ppc32.h
+*/
+
+//#define NIP_IDX 32
+#define CTR_IDX 32
+#define XER_IDX 33
+#define CCR_IDX 34
+#define MSR_IDX 35
+//#define MQ_IDX 36
+#define LINK_IDX 36
+
+/* These are dummy structures used only for obtaining the offsets of the
+ various structure members. */
+static ucontext_t dmy_ctxt UNUSED;
+
+#define UC_MCONTEXT_GREGS_R0 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[0] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R1 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[1] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R2 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[2] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R3 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[3] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R4 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[4] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R5 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[5] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R6 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[6] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R7 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[7] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R8 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[8] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R9 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[9] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R10 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[10] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R11 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[11] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R12 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[12] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R13 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[13] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R14 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[14] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R15 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[15] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R16 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[16] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R17 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[17] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R18 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[18] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R19 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[19] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R20 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[20] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R21 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[21] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R22 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[22] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R23 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[23] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R24 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[24] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R25 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[25] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R26 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[26] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R27 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[27] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R28 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[28] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R29 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[29] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R30 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[30] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R31 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[31] - (void *)&dmy_ctxt)
+
+#define UC_MCONTEXT_GREGS_MSR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[MSR_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_ORIG_GPR3 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[ORIG_GPR3_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_CTR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[CTR_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_LINK ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[LINK_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_XER ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[XER_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_CCR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[CCR_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_SOFTE ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[SOFTE_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_TRAP ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[TRAP_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_DAR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[DAR_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_DSISR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[DSISR_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_RESULT ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[RESULT_IDX] - (void *)&dmy_ctxt)
+
+#define UC_MCONTEXT_FREGS_R0 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[0] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R1 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[1] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R2 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[2] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R3 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[3] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R4 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[4] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R5 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[5] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R6 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[6] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R7 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[7] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R8 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[8] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R9 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[9] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R10 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[10] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R11 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[11] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R12 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[12] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R13 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[13] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R14 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[14] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R15 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[15] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R16 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[16] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R17 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[17] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R18 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[18] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R19 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[19] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R20 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[20] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R21 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[21] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R22 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[22] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R23 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[23] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R24 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[24] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R25 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[25] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R26 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[26] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R27 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[27] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R28 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[28] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R29 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[29] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R30 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[30] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R31 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[31] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_FPSCR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[32] - (void *)&dmy_ctxt)
+
+#endif
diff --git a/src/pal/src/libunwind/src/ppc32/unwind_i.h b/src/pal/src/libunwind/src/ppc32/unwind_i.h
new file mode 100644
index 0000000000..ad32d05654
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc32/unwind_i.h
@@ -0,0 +1,46 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef unwind_i_h
+#define unwind_i_h
+
+#include <stdint.h>
+
+#include <libunwind-ppc32.h>
+
+#include <libunwind_i.h>
+#include <sys/ucontext.h>
+
+#define ppc32_lock UNW_OBJ(lock)
+#define ppc32_local_resume UNW_OBJ(local_resume)
+#define ppc32_local_addr_space_init UNW_OBJ(local_addr_space_init)
+
+extern void ppc32_local_addr_space_init (void);
+extern int ppc32_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
+ void *arg);
+
+#endif /* unwind_i_h */
diff --git a/src/pal/src/libunwind/src/ppc64/Gapply_reg_state.c b/src/pal/src/libunwind/src/ppc64/Gapply_reg_state.c
new file mode 100644
index 0000000000..82f056da67
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/Gapply_reg_state.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+ void *reg_states_data)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
diff --git a/src/pal/src/libunwind/src/ppc64/Gcreate_addr_space.c b/src/pal/src/libunwind/src/ppc64/Gcreate_addr_space.c
new file mode 100644
index 0000000000..bd48555d4e
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/Gcreate_addr_space.c
@@ -0,0 +1,71 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+
+#include <libunwind_i.h>
+
+unw_addr_space_t
+unw_create_addr_space (unw_accessors_t *a, int byte_order)
+{
+#ifdef UNW_LOCAL_ONLY
+ return NULL;
+#else
+ unw_addr_space_t as;
+
+ /*
+ * We support both big- and little-endian on Linux ppc64.
+ */
+ if (byte_order != 0
+ && byte_order != __LITTLE_ENDIAN
+ && byte_order != __BIG_ENDIAN)
+ return NULL;
+
+ as = malloc (sizeof (*as));
+ if (!as)
+ return NULL;
+
+ memset (as, 0, sizeof (*as));
+
+ as->acc = *a;
+
+ if (byte_order == 0)
+ /* use host default: */
+ as->big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
+ else
+ as->big_endian = (byte_order == __BIG_ENDIAN);
+
+ /* FIXME! There is no way to specify the ABI.
+ Default to ELFv1 on big-endian and ELFv2 on little-endian. */
+ if (as->big_endian)
+ as->abi = UNW_PPC64_ABI_ELFv1;
+ else
+ as->abi = UNW_PPC64_ABI_ELFv2;
+
+ return as;
+#endif
+}
diff --git a/src/pal/src/libunwind/src/ppc64/Gglobal.c b/src/pal/src/libunwind/src/ppc64/Gglobal.c
new file mode 100644
index 0000000000..9d0b0f55a6
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/Gglobal.c
@@ -0,0 +1,182 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "dwarf_i.h"
+
+HIDDEN define_lock (ppc64_lock);
+HIDDEN int tdep_init_done;
+
+/* The API register numbers are exactly the same as the .eh_frame
+ registers, for now at least. */
+HIDDEN const uint8_t dwarf_to_unw_regnum_map[DWARF_REGNUM_MAP_LENGTH] =
+ {
+ [UNW_PPC64_R0]=UNW_PPC64_R0,
+ [UNW_PPC64_R1]=UNW_PPC64_R1,
+ [UNW_PPC64_R2]=UNW_PPC64_R2,
+ [UNW_PPC64_R3]=UNW_PPC64_R3,
+ [UNW_PPC64_R4]=UNW_PPC64_R4,
+ [UNW_PPC64_R5]=UNW_PPC64_R5,
+ [UNW_PPC64_R6]=UNW_PPC64_R6,
+ [UNW_PPC64_R7]=UNW_PPC64_R7,
+ [UNW_PPC64_R8]=UNW_PPC64_R8,
+ [UNW_PPC64_R9]=UNW_PPC64_R9,
+ [UNW_PPC64_R10]=UNW_PPC64_R10,
+ [UNW_PPC64_R11]=UNW_PPC64_R11,
+ [UNW_PPC64_R12]=UNW_PPC64_R12,
+ [UNW_PPC64_R13]=UNW_PPC64_R13,
+ [UNW_PPC64_R14]=UNW_PPC64_R14,
+ [UNW_PPC64_R15]=UNW_PPC64_R15,
+ [UNW_PPC64_R16]=UNW_PPC64_R16,
+ [UNW_PPC64_R17]=UNW_PPC64_R17,
+ [UNW_PPC64_R18]=UNW_PPC64_R18,
+ [UNW_PPC64_R19]=UNW_PPC64_R19,
+ [UNW_PPC64_R20]=UNW_PPC64_R20,
+ [UNW_PPC64_R21]=UNW_PPC64_R21,
+ [UNW_PPC64_R22]=UNW_PPC64_R22,
+ [UNW_PPC64_R23]=UNW_PPC64_R23,
+ [UNW_PPC64_R24]=UNW_PPC64_R24,
+ [UNW_PPC64_R25]=UNW_PPC64_R25,
+ [UNW_PPC64_R26]=UNW_PPC64_R26,
+ [UNW_PPC64_R27]=UNW_PPC64_R27,
+ [UNW_PPC64_R28]=UNW_PPC64_R28,
+ [UNW_PPC64_R29]=UNW_PPC64_R29,
+ [UNW_PPC64_R30]=UNW_PPC64_R30,
+ [UNW_PPC64_R31]=UNW_PPC64_R31,
+
+ [UNW_PPC64_F0]=UNW_PPC64_F0,
+ [UNW_PPC64_F1]=UNW_PPC64_F1,
+ [UNW_PPC64_F2]=UNW_PPC64_F2,
+ [UNW_PPC64_F3]=UNW_PPC64_F3,
+ [UNW_PPC64_F4]=UNW_PPC64_F4,
+ [UNW_PPC64_F5]=UNW_PPC64_F5,
+ [UNW_PPC64_F6]=UNW_PPC64_F6,
+ [UNW_PPC64_F7]=UNW_PPC64_F7,
+ [UNW_PPC64_F8]=UNW_PPC64_F8,
+ [UNW_PPC64_F9]=UNW_PPC64_F9,
+ [UNW_PPC64_F10]=UNW_PPC64_F10,
+ [UNW_PPC64_F11]=UNW_PPC64_F11,
+ [UNW_PPC64_F12]=UNW_PPC64_F12,
+ [UNW_PPC64_F13]=UNW_PPC64_F13,
+ [UNW_PPC64_F14]=UNW_PPC64_F14,
+ [UNW_PPC64_F15]=UNW_PPC64_F15,
+ [UNW_PPC64_F16]=UNW_PPC64_F16,
+ [UNW_PPC64_F17]=UNW_PPC64_F17,
+ [UNW_PPC64_F18]=UNW_PPC64_F18,
+ [UNW_PPC64_F19]=UNW_PPC64_F19,
+ [UNW_PPC64_F20]=UNW_PPC64_F20,
+ [UNW_PPC64_F21]=UNW_PPC64_F21,
+ [UNW_PPC64_F22]=UNW_PPC64_F22,
+ [UNW_PPC64_F23]=UNW_PPC64_F23,
+ [UNW_PPC64_F24]=UNW_PPC64_F24,
+ [UNW_PPC64_F25]=UNW_PPC64_F25,
+ [UNW_PPC64_F26]=UNW_PPC64_F26,
+ [UNW_PPC64_F27]=UNW_PPC64_F27,
+ [UNW_PPC64_F28]=UNW_PPC64_F28,
+ [UNW_PPC64_F29]=UNW_PPC64_F29,
+ [UNW_PPC64_F30]=UNW_PPC64_F30,
+ [UNW_PPC64_F31]=UNW_PPC64_F31,
+
+ [UNW_PPC64_LR]=UNW_PPC64_LR,
+ [UNW_PPC64_CTR]=UNW_PPC64_CTR,
+ [UNW_PPC64_ARG_POINTER]=UNW_PPC64_ARG_POINTER,
+
+ [UNW_PPC64_CR0]=UNW_PPC64_CR0,
+ [UNW_PPC64_CR1]=UNW_PPC64_CR1,
+ [UNW_PPC64_CR2]=UNW_PPC64_CR2,
+ [UNW_PPC64_CR3]=UNW_PPC64_CR3,
+ [UNW_PPC64_CR4]=UNW_PPC64_CR4,
+ [UNW_PPC64_CR5]=UNW_PPC64_CR5,
+ [UNW_PPC64_CR6]=UNW_PPC64_CR6,
+ [UNW_PPC64_CR7]=UNW_PPC64_CR7,
+
+ [UNW_PPC64_XER]=UNW_PPC64_XER,
+
+ [UNW_PPC64_V0]=UNW_PPC64_V0,
+ [UNW_PPC64_V1]=UNW_PPC64_V1,
+ [UNW_PPC64_V2]=UNW_PPC64_V2,
+ [UNW_PPC64_V3]=UNW_PPC64_V3,
+ [UNW_PPC64_V4]=UNW_PPC64_V4,
+ [UNW_PPC64_V5]=UNW_PPC64_V5,
+ [UNW_PPC64_V6]=UNW_PPC64_V6,
+ [UNW_PPC64_V7]=UNW_PPC64_V7,
+ [UNW_PPC64_V8]=UNW_PPC64_V8,
+ [UNW_PPC64_V9]=UNW_PPC64_V9,
+ [UNW_PPC64_V10]=UNW_PPC64_V10,
+ [UNW_PPC64_V11]=UNW_PPC64_V11,
+ [UNW_PPC64_V12]=UNW_PPC64_V12,
+ [UNW_PPC64_V13]=UNW_PPC64_V13,
+ [UNW_PPC64_V14]=UNW_PPC64_V14,
+ [UNW_PPC64_V15]=UNW_PPC64_V15,
+ [UNW_PPC64_V16]=UNW_PPC64_V16,
+ [UNW_PPC64_V17]=UNW_PPC64_V17,
+ [UNW_PPC64_V18]=UNW_PPC64_V18,
+ [UNW_PPC64_V19]=UNW_PPC64_V19,
+ [UNW_PPC64_V20]=UNW_PPC64_V20,
+ [UNW_PPC64_V21]=UNW_PPC64_V21,
+ [UNW_PPC64_V22]=UNW_PPC64_V22,
+ [UNW_PPC64_V23]=UNW_PPC64_V23,
+ [UNW_PPC64_V24]=UNW_PPC64_V24,
+ [UNW_PPC64_V25]=UNW_PPC64_V25,
+ [UNW_PPC64_V26]=UNW_PPC64_V26,
+ [UNW_PPC64_V27]=UNW_PPC64_V27,
+ [UNW_PPC64_V28]=UNW_PPC64_V28,
+ [UNW_PPC64_V29]=UNW_PPC64_V29,
+ [UNW_PPC64_V30]=UNW_PPC64_V30,
+ [UNW_PPC64_V31]=UNW_PPC64_V31,
+
+ [UNW_PPC64_VRSAVE]=UNW_PPC64_VRSAVE,
+ [UNW_PPC64_VSCR]=UNW_PPC64_VSCR,
+ [UNW_PPC64_SPE_ACC]=UNW_PPC64_SPE_ACC,
+ [UNW_PPC64_SPEFSCR]=UNW_PPC64_SPEFSCR,
+ };
+
+HIDDEN void
+tdep_init (void)
+{
+ intrmask_t saved_mask;
+
+ sigfillset (&unwi_full_mask);
+
+ lock_acquire (&ppc64_lock, saved_mask);
+ {
+ if (tdep_init_done)
+ /* another thread else beat us to it... */
+ goto out;
+
+ mi_init ();
+
+ dwarf_init ();
+
+#ifndef UNW_REMOTE_ONLY
+ ppc64_local_addr_space_init ();
+#endif
+ tdep_init_done = 1; /* signal that we're initialized... */
+ }
+ out:
+ lock_release (&ppc64_lock, saved_mask);
+}
diff --git a/src/pal/src/libunwind/src/ppc64/Ginit.c b/src/pal/src/libunwind/src/ppc64/Ginit.c
new file mode 100644
index 0000000000..4c88cd6e77
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/Ginit.c
@@ -0,0 +1,229 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "ucontext_i.h"
+#include "unwind_i.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+/* unw_local_addr_space is a NULL pointer in this case. */
+unw_addr_space_t unw_local_addr_space;
+
+#else /* !UNW_REMOTE_ONLY */
+
+static struct unw_addr_space local_addr_space;
+
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
+
+static void *
+uc_addr (ucontext_t *uc, int reg)
+{
+ void *addr;
+
+ if ((unsigned) (reg - UNW_PPC64_R0) < 32)
+ addr = &uc->uc_mcontext.gp_regs[reg - UNW_PPC64_R0];
+
+ else if ((unsigned) (reg - UNW_PPC64_F0) < 32)
+ addr = &uc->uc_mcontext.fp_regs[reg - UNW_PPC64_F0];
+
+ else if ((unsigned) (reg - UNW_PPC64_V0) < 32)
+ addr = (uc->uc_mcontext.v_regs == 0) ? NULL : &uc->uc_mcontext.v_regs->vrregs[reg - UNW_PPC64_V0][0];
+
+ else
+ {
+ unsigned gregs_idx;
+
+ switch (reg)
+ {
+ case UNW_PPC64_NIP:
+ gregs_idx = NIP_IDX;
+ break;
+ case UNW_PPC64_CTR:
+ gregs_idx = CTR_IDX;
+ break;
+ case UNW_PPC64_LR:
+ gregs_idx = LINK_IDX;
+ break;
+ case UNW_PPC64_XER:
+ gregs_idx = XER_IDX;
+ break;
+ case UNW_PPC64_CR0:
+ gregs_idx = CCR_IDX;
+ break;
+ default:
+ return NULL;
+ }
+ addr = &uc->uc_mcontext.gp_regs[gregs_idx];
+ }
+ return addr;
+}
+
+# ifdef UNW_LOCAL_ONLY
+
+HIDDEN void *
+tdep_uc_addr (ucontext_t *uc, int reg)
+{
+ return uc_addr (uc, reg);
+}
+
+# endif /* UNW_LOCAL_ONLY */
+
+HIDDEN unw_dyn_info_list_t _U_dyn_info_list;
+
+
+static void
+put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
+{
+ /* it's a no-op */
+}
+
+static int
+get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
+ void *arg)
+{
+ *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list;
+ return 0;
+}
+
+static int
+access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
+ void *arg)
+{
+ if (write)
+ {
+ Debug (12, "mem[%lx] <- %lx\n", addr, *val);
+ *(unw_word_t *) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_word_t *) addr;
+ Debug (12, "mem[%lx] -> %lx\n", addr, *val);
+ }
+ return 0;
+}
+
+static int
+access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val,
+ int write, void *arg)
+{
+ unw_word_t *addr;
+ ucontext_t *uc = arg;
+
+ if (UNW_PPC64_F0 <= reg && reg <= UNW_PPC64_F31)
+ goto badreg;
+ if (UNW_PPC64_V0 <= reg && reg <= UNW_PPC64_V31)
+ goto badreg;
+
+ addr = uc_addr (uc, reg);
+ if (!addr)
+ goto badreg;
+
+ if (write)
+ {
+ *(unw_word_t *) addr = *val;
+ Debug (12, "%s <- %lx\n", unw_regname (reg), *val);
+ }
+ else
+ {
+ *val = *(unw_word_t *) addr;
+ Debug (12, "%s -> %lx\n", unw_regname (reg), *val);
+ }
+ return 0;
+
+badreg:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+}
+
+static int
+access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
+ int write, void *arg)
+{
+ ucontext_t *uc = arg;
+ unw_fpreg_t *addr;
+
+ /* Allow only 32 fregs and 32 vregs */
+ if (!(((unsigned) (reg - UNW_PPC64_F0) < 32)
+ ||((unsigned) (reg - UNW_PPC64_V0) < 32)))
+ goto badreg;
+
+ addr = uc_addr (uc, reg);
+ if (!addr)
+ goto badreg;
+
+ if (write)
+ {
+ Debug (12, "%s <- %016Lf\n", unw_regname (reg), *val);
+ *(unw_fpreg_t *) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_fpreg_t *) addr;
+ Debug (12, "%s -> %016Lf\n", unw_regname (reg), *val);
+ }
+ return 0;
+
+badreg:
+ Debug (1, "bad register number %u\n", reg);
+ /* attempt to access a non-preserved register */
+ return -UNW_EBADREG;
+}
+
+static int
+get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
+ char *buf, size_t buf_len, unw_word_t *offp,
+ void *arg)
+{
+ return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
+}
+
+HIDDEN void
+ppc64_local_addr_space_init (void)
+{
+ memset (&local_addr_space, 0, sizeof (local_addr_space));
+ local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
+#if _CALL_ELF == 2
+ local_addr_space.abi = UNW_PPC64_ABI_ELFv2;
+#else
+ local_addr_space.abi = UNW_PPC64_ABI_ELFv1;
+#endif
+ local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
+ local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
+ local_addr_space.acc.put_unwind_info = put_unwind_info;
+ local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
+ local_addr_space.acc.access_mem = access_mem;
+ local_addr_space.acc.access_reg = access_reg;
+ local_addr_space.acc.access_fpreg = access_fpreg;
+ local_addr_space.acc.resume = ppc64_local_resume;
+ local_addr_space.acc.get_proc_name = get_static_proc_name;
+ unw_flush_cache (&local_addr_space, 0, 0);
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/ppc64/Greg_states_iterate.c b/src/pal/src/libunwind/src/ppc64/Greg_states_iterate.c
new file mode 100644
index 0000000000..a17dc1b561
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/Greg_states_iterate.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+ unw_reg_states_callback cb, void *token)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
diff --git a/src/pal/src/libunwind/src/ppc64/Gregs.c b/src/pal/src/libunwind/src/ppc64/Gregs.c
new file mode 100644
index 0000000000..1cb5d9dc65
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/Gregs.c
@@ -0,0 +1,141 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+HIDDEN int
+tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
+ int write)
+{
+ struct dwarf_loc loc;
+
+ switch (reg)
+ {
+ case UNW_PPC64_R0:
+ case UNW_PPC64_R2:
+ case UNW_PPC64_R3:
+ case UNW_PPC64_R4:
+ case UNW_PPC64_R5:
+ case UNW_PPC64_R6:
+ case UNW_PPC64_R7:
+ case UNW_PPC64_R8:
+ case UNW_PPC64_R9:
+ case UNW_PPC64_R10:
+ case UNW_PPC64_R11:
+ case UNW_PPC64_R12:
+ case UNW_PPC64_R13:
+ case UNW_PPC64_R14:
+ case UNW_PPC64_R15:
+ case UNW_PPC64_R16:
+ case UNW_PPC64_R17:
+ case UNW_PPC64_R18:
+ case UNW_PPC64_R19:
+ case UNW_PPC64_R20:
+ case UNW_PPC64_R21:
+ case UNW_PPC64_R22:
+ case UNW_PPC64_R23:
+ case UNW_PPC64_R24:
+ case UNW_PPC64_R25:
+ case UNW_PPC64_R26:
+ case UNW_PPC64_R27:
+ case UNW_PPC64_R28:
+ case UNW_PPC64_R29:
+ case UNW_PPC64_R30:
+ case UNW_PPC64_R31:
+ case UNW_PPC64_LR:
+ case UNW_PPC64_CTR:
+ case UNW_PPC64_CR0:
+ case UNW_PPC64_CR1:
+ case UNW_PPC64_CR2:
+ case UNW_PPC64_CR3:
+ case UNW_PPC64_CR4:
+ case UNW_PPC64_CR5:
+ case UNW_PPC64_CR6:
+ case UNW_PPC64_CR7:
+ case UNW_PPC64_VRSAVE:
+ case UNW_PPC64_VSCR:
+ case UNW_PPC64_SPE_ACC:
+ case UNW_PPC64_SPEFSCR:
+ loc = c->dwarf.loc[reg];
+ break;
+
+ case UNW_TDEP_IP:
+ if (write)
+ {
+ c->dwarf.ip = *valp; /* update the IP cache */
+ if (c->dwarf.pi_valid && (*valp < c->dwarf.pi.start_ip
+ || *valp >= c->dwarf.pi.end_ip))
+ c->dwarf.pi_valid = 0; /* new IP outside of current proc */
+ }
+ else
+ *valp = c->dwarf.ip;
+ return 0;
+
+ case UNW_TDEP_SP:
+ if (write)
+ return -UNW_EREADONLYREG;
+ *valp = c->dwarf.cfa;
+ return 0;
+
+ default:
+ return -UNW_EBADREG;
+ break;
+ }
+
+ if (write)
+ return dwarf_put (&c->dwarf, loc, *valp);
+ else
+ return dwarf_get (&c->dwarf, loc, valp);
+}
+
+HIDDEN int
+tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
+ int write)
+{
+ struct dwarf_loc loc;
+
+ if ((unsigned) (reg - UNW_PPC64_F0) < 32)
+ {
+ loc = c->dwarf.loc[reg];
+ if (write)
+ return dwarf_putfp (&c->dwarf, loc, *valp);
+ else
+ return dwarf_getfp (&c->dwarf, loc, valp);
+ }
+ else
+ if ((unsigned) (reg - UNW_PPC64_V0) < 32)
+ {
+ loc = c->dwarf.loc[reg];
+ if (write)
+ return dwarf_putvr (&c->dwarf, loc, *valp);
+ else
+ return dwarf_getvr (&c->dwarf, loc, valp);
+ }
+
+ return -UNW_EBADREG;
+}
+
diff --git a/src/pal/src/libunwind/src/ppc64/Gresume.c b/src/pal/src/libunwind/src/ppc64/Gresume.c
new file mode 100644
index 0000000000..0d832d0d97
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/Gresume.c
@@ -0,0 +1,111 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford cjashfor@us.ibm.com
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+
+#include "unwind_i.h"
+
+#ifndef UNW_REMOTE_ONLY
+
+#include <sys/syscall.h>
+
+/* sigreturn() is a no-op on x86_64 glibc. */
+
+static NORETURN inline long
+my_rt_sigreturn (void *new_sp)
+{
+ /* XXX: empty stub. */
+ abort ();
+}
+
+HIDDEN inline int
+ppc64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ ucontext_t *uc = (ucontext_t *)c->dwarf.as_arg;
+
+ if (unlikely (c->sigcontext_format != PPC_SCF_NONE))
+ {
+ my_rt_sigreturn(cursor);
+ abort();
+ }
+ else
+ {
+ Debug (8, "resuming at ip=%llx via setcontext()\n",
+ (unsigned long long) c->dwarf.ip);
+ setcontext (uc);
+ }
+ return -UNW_EINVAL;
+}
+
+#endif /* !UNW_REMOTE_ONLY */
+
+/* This routine is responsible for copying the register values in
+ cursor C and establishing them as the current machine state. */
+
+static inline int
+establish_machine_state (struct cursor *c)
+{
+ unw_addr_space_t as = c->dwarf.as;
+ void *arg = c->dwarf.as_arg;
+ unw_fpreg_t fpval;
+ unw_word_t val;
+ int reg;
+
+ Debug (8, "copying out cursor state\n");
+
+ for (reg = 0; reg <= UNW_REG_LAST; ++reg)
+ {
+ Debug (16, "copying %s %d\n", unw_regname (reg), reg);
+ if (unw_is_fpreg (reg))
+ {
+ if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0)
+ as->acc.access_fpreg (as, reg, &fpval, 1, arg);
+ }
+ else
+ {
+ if (tdep_access_reg (c, reg, &val, 0) >= 0)
+ as->acc.access_reg (as, reg, &val, 1, arg);
+ }
+ }
+ return 0;
+}
+
+int
+unw_resume (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ if ((ret = establish_machine_state (c)) < 0)
+ return ret;
+
+ return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c,
+ c->dwarf.as_arg);
+}
diff --git a/src/pal/src/libunwind/src/ppc64/Gstep.c b/src/pal/src/libunwind/src/ppc64/Gstep.c
new file mode 100644
index 0000000000..f44e959105
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/Gstep.c
@@ -0,0 +1,466 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "ucontext_i.h"
+#include "remote.h"
+#include <signal.h>
+
+/* This definition originates in /usr/include/asm-ppc64/ptrace.h, but is
+ defined there only when __KERNEL__ is defined. We reproduce it here for
+ our use at the user level in order to locate the ucontext record, which
+ appears to be at this offset relative to the stack pointer when in the
+ context of the signal handler return trampoline code -
+ __kernel_sigtramp_rt64. */
+#define __SIGNAL_FRAMESIZE 128
+
+/* This definition comes from the document "64-bit PowerPC ELF Application
+ Binary Interface Supplement 1.9", section 3.2.2.
+ http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK */
+
+typedef struct
+{
+ long unsigned back_chain;
+ long unsigned cr_save;
+ long unsigned lr_save;
+ /* many more fields here, but they are unused by this code */
+} stack_frame_t;
+
+
+int
+unw_step (unw_cursor_t * cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ stack_frame_t dummy;
+ unw_word_t back_chain_offset, lr_save_offset, v_regs_ptr;
+ struct dwarf_loc back_chain_loc, lr_save_loc, sp_loc, ip_loc, v_regs_loc;
+ int ret, i;
+
+ Debug (1, "(cursor=%p, ip=0x%016lx)\n", c, (unsigned long) c->dwarf.ip);
+
+ /* Try DWARF-based unwinding... */
+
+ ret = dwarf_step (&c->dwarf);
+
+ if (ret < 0 && ret != -UNW_ENOINFO)
+ {
+ Debug (2, "returning %d\n", ret);
+ return ret;
+ }
+
+ if (unlikely (ret < 0))
+ {
+ if (likely (unw_is_signal_frame (cursor) <= 0))
+ {
+ /* DWARF unwinding failed. As of 09/26/2006, gcc in 64-bit mode
+ produces the mandatory level of traceback record in the code, but
+ I get the impression that this is transitory, that eventually gcc
+ will not produce any traceback records at all. So, for now, we
+ won't bother to try to find and use these records.
+
+ We can, however, attempt to unwind the frame by using the callback
+ chain. This is very crude, however, and won't be able to unwind
+ any registers besides the IP, SP, and LR . */
+
+ back_chain_offset = ((void *) &dummy.back_chain - (void *) &dummy);
+ lr_save_offset = ((void *) &dummy.lr_save - (void *) &dummy);
+
+ back_chain_loc = DWARF_LOC (c->dwarf.cfa + back_chain_offset, 0);
+
+ if ((ret =
+ dwarf_get (&c->dwarf, back_chain_loc, &c->dwarf.cfa)) < 0)
+ {
+ Debug (2,
+ "Unable to retrieve CFA from back chain in stack frame - %d\n",
+ ret);
+ return ret;
+ }
+ if (c->dwarf.cfa == 0)
+ /* Unless the cursor or stack is corrupt or uninitialized we've most
+ likely hit the top of the stack */
+ return 0;
+
+ lr_save_loc = DWARF_LOC (c->dwarf.cfa + lr_save_offset, 0);
+
+ if ((ret = dwarf_get (&c->dwarf, lr_save_loc, &c->dwarf.ip)) < 0)
+ {
+ Debug (2,
+ "Unable to retrieve IP from lr save in stack frame - %d\n",
+ ret);
+ return ret;
+ }
+
+ /* Mark all registers unsaved */
+ for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
+ c->dwarf.loc[i] = DWARF_NULL_LOC;
+
+ ret = 1;
+ }
+ else
+ {
+ /* Find the sigcontext record by taking the CFA and adjusting by
+ the dummy signal frame size.
+
+ Note that there isn't any way to determined if SA_SIGINFO was
+ set in the sa_flags parameter to sigaction when the signal
+ handler was established. If it was not set, the ucontext
+ record is not required to be on the stack, in which case the
+ following code will likely cause a seg fault or other crash
+ condition. */
+
+ unw_word_t ucontext = c->dwarf.cfa + __SIGNAL_FRAMESIZE;
+
+ Debug (1, "signal frame, skip over trampoline\n");
+
+ c->sigcontext_format = PPC_SCF_LINUX_RT_SIGFRAME;
+ c->sigcontext_addr = ucontext;
+
+ sp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0);
+ ip_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_NIP, 0);
+
+ ret = dwarf_get (&c->dwarf, sp_loc, &c->dwarf.cfa);
+ if (ret < 0)
+ {
+ Debug (2, "returning %d\n", ret);
+ return ret;
+ }
+ ret = dwarf_get (&c->dwarf, ip_loc, &c->dwarf.ip);
+ if (ret < 0)
+ {
+ Debug (2, "returning %d\n", ret);
+ return ret;
+ }
+
+ /* Instead of just restoring the non-volatile registers, do all
+ of the registers for now. This will incur a performance hit,
+ but it's rare enough not to cause too much of a problem, and
+ might be useful in some cases. */
+ c->dwarf.loc[UNW_PPC64_R0] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R0, 0);
+ c->dwarf.loc[UNW_PPC64_R1] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0);
+ c->dwarf.loc[UNW_PPC64_R2] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R2, 0);
+ c->dwarf.loc[UNW_PPC64_R3] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R3, 0);
+ c->dwarf.loc[UNW_PPC64_R4] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R4, 0);
+ c->dwarf.loc[UNW_PPC64_R5] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R5, 0);
+ c->dwarf.loc[UNW_PPC64_R6] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R6, 0);
+ c->dwarf.loc[UNW_PPC64_R7] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R7, 0);
+ c->dwarf.loc[UNW_PPC64_R8] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0);
+ c->dwarf.loc[UNW_PPC64_R9] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0);
+ c->dwarf.loc[UNW_PPC64_R10] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0);
+ c->dwarf.loc[UNW_PPC64_R11] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0);
+ c->dwarf.loc[UNW_PPC64_R12] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0);
+ c->dwarf.loc[UNW_PPC64_R13] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0);
+ c->dwarf.loc[UNW_PPC64_R14] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0);
+ c->dwarf.loc[UNW_PPC64_R15] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0);
+ c->dwarf.loc[UNW_PPC64_R16] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R16, 0);
+ c->dwarf.loc[UNW_PPC64_R17] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R17, 0);
+ c->dwarf.loc[UNW_PPC64_R18] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R18, 0);
+ c->dwarf.loc[UNW_PPC64_R19] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R19, 0);
+ c->dwarf.loc[UNW_PPC64_R20] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R20, 0);
+ c->dwarf.loc[UNW_PPC64_R21] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R21, 0);
+ c->dwarf.loc[UNW_PPC64_R22] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R22, 0);
+ c->dwarf.loc[UNW_PPC64_R23] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R23, 0);
+ c->dwarf.loc[UNW_PPC64_R24] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R24, 0);
+ c->dwarf.loc[UNW_PPC64_R25] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R25, 0);
+ c->dwarf.loc[UNW_PPC64_R26] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R26, 0);
+ c->dwarf.loc[UNW_PPC64_R27] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R27, 0);
+ c->dwarf.loc[UNW_PPC64_R28] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R28, 0);
+ c->dwarf.loc[UNW_PPC64_R29] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R29, 0);
+ c->dwarf.loc[UNW_PPC64_R30] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R30, 0);
+ c->dwarf.loc[UNW_PPC64_R31] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R31, 0);
+
+ c->dwarf.loc[UNW_PPC64_LR] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_LINK, 0);
+ c->dwarf.loc[UNW_PPC64_CTR] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CTR, 0);
+ /* This CR0 assignment is probably wrong. There are 8 dwarf columns
+ assigned to the CR registers, but only one CR register in the
+ mcontext structure */
+ c->dwarf.loc[UNW_PPC64_CR0] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CCR, 0);
+ c->dwarf.loc[UNW_PPC64_XER] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_XER, 0);
+ c->dwarf.loc[UNW_PPC64_NIP] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_NIP, 0);
+
+ /* TODO: Is there a way of obtaining the value of the
+ pseudo frame pointer (which is sp + some fixed offset, I
+ assume), based on the contents of the ucontext record
+ structure? For now, set this loc to null. */
+ c->dwarf.loc[UNW_PPC64_FRAME_POINTER] = DWARF_NULL_LOC;
+
+ c->dwarf.loc[UNW_PPC64_F0] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R0, 0);
+ c->dwarf.loc[UNW_PPC64_F1] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R1, 0);
+ c->dwarf.loc[UNW_PPC64_F2] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R2, 0);
+ c->dwarf.loc[UNW_PPC64_F3] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R3, 0);
+ c->dwarf.loc[UNW_PPC64_F4] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R4, 0);
+ c->dwarf.loc[UNW_PPC64_F5] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R5, 0);
+ c->dwarf.loc[UNW_PPC64_F6] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R6, 0);
+ c->dwarf.loc[UNW_PPC64_F7] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R7, 0);
+ c->dwarf.loc[UNW_PPC64_F8] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R8, 0);
+ c->dwarf.loc[UNW_PPC64_F9] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R9, 0);
+ c->dwarf.loc[UNW_PPC64_F10] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R10, 0);
+ c->dwarf.loc[UNW_PPC64_F11] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R11, 0);
+ c->dwarf.loc[UNW_PPC64_F12] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R12, 0);
+ c->dwarf.loc[UNW_PPC64_F13] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R13, 0);
+ c->dwarf.loc[UNW_PPC64_F14] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R14, 0);
+ c->dwarf.loc[UNW_PPC64_F15] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R15, 0);
+ c->dwarf.loc[UNW_PPC64_F16] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R16, 0);
+ c->dwarf.loc[UNW_PPC64_F17] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R17, 0);
+ c->dwarf.loc[UNW_PPC64_F18] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R18, 0);
+ c->dwarf.loc[UNW_PPC64_F19] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R19, 0);
+ c->dwarf.loc[UNW_PPC64_F20] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R20, 0);
+ c->dwarf.loc[UNW_PPC64_F21] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R21, 0);
+ c->dwarf.loc[UNW_PPC64_F22] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R22, 0);
+ c->dwarf.loc[UNW_PPC64_F23] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R23, 0);
+ c->dwarf.loc[UNW_PPC64_F24] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R24, 0);
+ c->dwarf.loc[UNW_PPC64_F25] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R25, 0);
+ c->dwarf.loc[UNW_PPC64_F26] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R26, 0);
+ c->dwarf.loc[UNW_PPC64_F27] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R27, 0);
+ c->dwarf.loc[UNW_PPC64_F28] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R28, 0);
+ c->dwarf.loc[UNW_PPC64_F29] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R29, 0);
+ c->dwarf.loc[UNW_PPC64_F30] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R30, 0);
+ c->dwarf.loc[UNW_PPC64_F31] =
+ DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R31, 0);
+ /* Note that there is no .eh_section register column for the
+ FPSCR register. I don't know why this is. */
+
+ v_regs_loc = DWARF_LOC (ucontext + UC_MCONTEXT_V_REGS, 0);
+ ret = dwarf_get (&c->dwarf, v_regs_loc, &v_regs_ptr);
+ if (ret < 0)
+ {
+ Debug (2, "returning %d\n", ret);
+ return ret;
+ }
+ if (v_regs_ptr != 0)
+ {
+ /* The v_regs_ptr is not null. Set all of the AltiVec locs */
+
+ c->dwarf.loc[UNW_PPC64_V0] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R0, 0);
+ c->dwarf.loc[UNW_PPC64_V1] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R1, 0);
+ c->dwarf.loc[UNW_PPC64_V2] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R2, 0);
+ c->dwarf.loc[UNW_PPC64_V3] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R3, 0);
+ c->dwarf.loc[UNW_PPC64_V4] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R4, 0);
+ c->dwarf.loc[UNW_PPC64_V5] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R5, 0);
+ c->dwarf.loc[UNW_PPC64_V6] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R6, 0);
+ c->dwarf.loc[UNW_PPC64_V7] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R7, 0);
+ c->dwarf.loc[UNW_PPC64_V8] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R8, 0);
+ c->dwarf.loc[UNW_PPC64_V9] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R9, 0);
+ c->dwarf.loc[UNW_PPC64_V10] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R10, 0);
+ c->dwarf.loc[UNW_PPC64_V11] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R11, 0);
+ c->dwarf.loc[UNW_PPC64_V12] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R12, 0);
+ c->dwarf.loc[UNW_PPC64_V13] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R13, 0);
+ c->dwarf.loc[UNW_PPC64_V14] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R14, 0);
+ c->dwarf.loc[UNW_PPC64_V15] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R15, 0);
+ c->dwarf.loc[UNW_PPC64_V16] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R16, 0);
+ c->dwarf.loc[UNW_PPC64_V17] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R17, 0);
+ c->dwarf.loc[UNW_PPC64_V18] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R18, 0);
+ c->dwarf.loc[UNW_PPC64_V19] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R19, 0);
+ c->dwarf.loc[UNW_PPC64_V20] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R20, 0);
+ c->dwarf.loc[UNW_PPC64_V21] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R21, 0);
+ c->dwarf.loc[UNW_PPC64_V22] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R22, 0);
+ c->dwarf.loc[UNW_PPC64_V23] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R23, 0);
+ c->dwarf.loc[UNW_PPC64_V24] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R24, 0);
+ c->dwarf.loc[UNW_PPC64_V25] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R25, 0);
+ c->dwarf.loc[UNW_PPC64_V26] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R26, 0);
+ c->dwarf.loc[UNW_PPC64_V27] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R27, 0);
+ c->dwarf.loc[UNW_PPC64_V28] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R28, 0);
+ c->dwarf.loc[UNW_PPC64_V29] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R29, 0);
+ c->dwarf.loc[UNW_PPC64_V30] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R30, 0);
+ c->dwarf.loc[UNW_PPC64_V31] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R31, 0);
+ c->dwarf.loc[UNW_PPC64_VRSAVE] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_VRSAVE, 0);
+ c->dwarf.loc[UNW_PPC64_VSCR] =
+ DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_VSCR, 0);
+ }
+ else
+ {
+ c->dwarf.loc[UNW_PPC64_V0] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V1] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V2] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V3] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V4] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V5] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V6] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V7] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V8] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V9] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V10] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V11] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V12] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V13] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V14] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V15] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V16] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V17] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V18] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V19] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V20] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V21] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V22] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V23] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V24] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V25] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V26] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V27] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V28] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V29] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V30] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_V31] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_VRSAVE] = DWARF_NULL_LOC;
+ c->dwarf.loc[UNW_PPC64_VSCR] = DWARF_NULL_LOC;
+ }
+ ret = 1;
+ }
+ }
+
+ if (c->dwarf.ip == 0)
+ {
+ /* Unless the cursor or stack is corrupt or uninitialized,
+ we've most likely hit the top of the stack */
+ Debug (2, "returning 0\n");
+ return 0;
+ }
+
+ // on ppc64, R2 register is used as pointer to TOC
+ // section which is used for symbol lookup in PIC code
+ // ppc64 linker generates "ld r2, 40(r1)" (ELFv1) or
+ // "ld r2, 24(r1)" (ELFv2) instruction after each
+ // @plt call. We need restore R2, but only for @plt calls
+ {
+ unw_word_t ip = c->dwarf.ip;
+ unw_addr_space_t as = c->dwarf.as;
+ unw_accessors_t *a = unw_get_accessors_int (as);
+ void *arg = c->dwarf.as_arg;
+ uint32_t toc_save = (as->abi == UNW_PPC64_ABI_ELFv2)? 24 : 40;
+ int32_t inst;
+
+ if (fetch32 (as, a, &ip, &inst, arg) >= 0
+ && (uint32_t)inst == (0xE8410000U + toc_save))
+ {
+ // @plt call, restoring R2 from CFA+toc_save
+ c->dwarf.loc[UNW_PPC64_R2] = DWARF_LOC(c->dwarf.cfa + toc_save, 0);
+ }
+ }
+
+ Debug (2, "returning %d with last return statement\n", ret);
+ return ret;
+}
diff --git a/src/pal/src/libunwind/src/ppc64/Lapply_reg_state.c b/src/pal/src/libunwind/src/ppc64/Lapply_reg_state.c
new file mode 100644
index 0000000000..7ebada480e
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/Lapply_reg_state.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc64/Lcreate_addr_space.c b/src/pal/src/libunwind/src/ppc64/Lcreate_addr_space.c
new file mode 100644
index 0000000000..0f2dc6be90
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/Lcreate_addr_space.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gcreate_addr_space.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc64/Lglobal.c b/src/pal/src/libunwind/src/ppc64/Lglobal.c
new file mode 100644
index 0000000000..6d7b489e14
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/Lglobal.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gglobal.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc64/Linit.c b/src/pal/src/libunwind/src/ppc64/Linit.c
new file mode 100644
index 0000000000..e9abfdd46a
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/Linit.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc64/Lreg_states_iterate.c b/src/pal/src/libunwind/src/ppc64/Lreg_states_iterate.c
new file mode 100644
index 0000000000..f1eb1e79dc
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/Lreg_states_iterate.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc64/Lregs.c b/src/pal/src/libunwind/src/ppc64/Lregs.c
new file mode 100644
index 0000000000..2c9c75cd7d
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/Lregs.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gregs.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc64/Lresume.c b/src/pal/src/libunwind/src/ppc64/Lresume.c
new file mode 100644
index 0000000000..41a8cf003d
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/Lresume.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gresume.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc64/Lstep.c b/src/pal/src/libunwind/src/ppc64/Lstep.c
new file mode 100644
index 0000000000..c1ac3c7547
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/Lstep.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gstep.c"
+#endif
diff --git a/src/pal/src/libunwind/src/ppc64/get_func_addr.c b/src/pal/src/libunwind/src/ppc64/get_func_addr.c
new file mode 100644
index 0000000000..80a58fa1f8
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/get_func_addr.c
@@ -0,0 +1,51 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+tdep_get_func_addr (unw_addr_space_t as, unw_word_t addr,
+ unw_word_t *entry_point)
+{
+ if (as->abi == UNW_PPC64_ABI_ELFv1)
+ {
+ unw_accessors_t *a;
+ int ret;
+
+ a = unw_get_accessors_int (as);
+ /* Entry-point is stored in the 1st word of the function descriptor.
+ In case that changes in the future, we'd have to update the line
+ below and read the word at addr + offset: */
+ ret = (*a->access_mem) (as, addr, entry_point, 0, NULL);
+ if (ret < 0)
+ return ret;
+ }
+ else
+ *entry_point = addr;
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/ppc64/init.h b/src/pal/src/libunwind/src/ppc64/init.h
new file mode 100644
index 0000000000..9b8139343d
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/init.h
@@ -0,0 +1,82 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+static inline int
+common_init_ppc64 (struct cursor *c, unsigned use_prev_instr)
+{
+ int ret;
+ int i;
+
+ for (i = UNW_PPC64_R0; i <= UNW_PPC64_R31; i++) {
+ c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, i);
+ }
+ for (i = UNW_PPC64_F0; i <= UNW_PPC64_F31; i++) {
+ c->dwarf.loc[i] = DWARF_FPREG_LOC (&c->dwarf, i);
+ }
+ for (i = UNW_PPC64_V0; i <= UNW_PPC64_V31; i++) {
+ c->dwarf.loc[i] = DWARF_VREG_LOC (&c->dwarf, i);
+ }
+
+ for (i = UNW_PPC64_CR0; i <= UNW_PPC64_CR7; i++) {
+ c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, i);
+ }
+ c->dwarf.loc[UNW_PPC64_ARG_POINTER] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_ARG_POINTER);
+ c->dwarf.loc[UNW_PPC64_CTR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_CTR);
+ c->dwarf.loc[UNW_PPC64_VSCR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_VSCR);
+
+ c->dwarf.loc[UNW_PPC64_XER] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_XER);
+ c->dwarf.loc[UNW_PPC64_LR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_LR);
+ c->dwarf.loc[UNW_PPC64_VRSAVE] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_VRSAVE);
+ c->dwarf.loc[UNW_PPC64_SPEFSCR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_SPEFSCR);
+ c->dwarf.loc[UNW_PPC64_SPE_ACC] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_SPE_ACC);
+
+ c->dwarf.loc[UNW_PPC64_NIP] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_NIP);
+
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_PPC64_NIP], &c->dwarf.ip);
+ if (ret < 0)
+ return ret;
+
+ ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_PPC64_R1),
+ &c->dwarf.cfa);
+ if (ret < 0)
+ return ret;
+
+ c->sigcontext_format = PPC_SCF_NONE;
+ c->sigcontext_addr = 0;
+
+ c->dwarf.args_size = 0;
+ c->dwarf.stash_frames = 0;
+ c->dwarf.use_prev_instr = use_prev_instr;
+ c->dwarf.pi_valid = 0;
+ c->dwarf.pi_is_dynamic = 0;
+ c->dwarf.hint = 0;
+ c->dwarf.prev_rs = 0;
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/ppc64/is_fpreg.c b/src/pal/src/libunwind/src/ppc64/is_fpreg.c
new file mode 100644
index 0000000000..653964a7da
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/is_fpreg.c
@@ -0,0 +1,34 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+int
+unw_is_fpreg (int regnum)
+{
+ return (regnum >= UNW_PPC64_F0 && regnum <= UNW_PPC64_F31);
+}
diff --git a/src/pal/src/libunwind/src/ppc64/regname.c b/src/pal/src/libunwind/src/ppc64/regname.c
new file mode 100644
index 0000000000..58c6fa6d87
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/regname.c
@@ -0,0 +1,164 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+static const char *regname[] =
+ {
+ [UNW_PPC64_R0]="GPR0",
+ [UNW_PPC64_R1]="GPR1",
+ [UNW_PPC64_R2]="GPR2",
+ [UNW_PPC64_R3]="GPR3",
+ [UNW_PPC64_R4]="GPR4",
+ [UNW_PPC64_R5]="GPR5",
+ [UNW_PPC64_R6]="GPR6",
+ [UNW_PPC64_R7]="GPR7",
+ [UNW_PPC64_R8]="GPR8",
+ [UNW_PPC64_R9]="GPR9",
+ [UNW_PPC64_R10]="GPR10",
+ [UNW_PPC64_R11]="GPR11",
+ [UNW_PPC64_R12]="GPR12",
+ [UNW_PPC64_R13]="GPR13",
+ [UNW_PPC64_R14]="GPR14",
+ [UNW_PPC64_R15]="GPR15",
+ [UNW_PPC64_R16]="GPR16",
+ [UNW_PPC64_R17]="GPR17",
+ [UNW_PPC64_R18]="GPR18",
+ [UNW_PPC64_R19]="GPR19",
+ [UNW_PPC64_R20]="GPR20",
+ [UNW_PPC64_R21]="GPR21",
+ [UNW_PPC64_R22]="GPR22",
+ [UNW_PPC64_R23]="GPR23",
+ [UNW_PPC64_R24]="GPR24",
+ [UNW_PPC64_R25]="GPR25",
+ [UNW_PPC64_R26]="GPR26",
+ [UNW_PPC64_R27]="GPR27",
+ [UNW_PPC64_R28]="GPR28",
+ [UNW_PPC64_R29]="GPR29",
+ [UNW_PPC64_R30]="GPR30",
+ [UNW_PPC64_R31]="GPR31",
+
+ [UNW_PPC64_F0]="FPR0",
+ [UNW_PPC64_F1]="FPR1",
+ [UNW_PPC64_F2]="FPR2",
+ [UNW_PPC64_F3]="FPR3",
+ [UNW_PPC64_F4]="FPR4",
+ [UNW_PPC64_F5]="FPR5",
+ [UNW_PPC64_F6]="FPR6",
+ [UNW_PPC64_F7]="FPR7",
+ [UNW_PPC64_F8]="FPR8",
+ [UNW_PPC64_F9]="FPR9",
+ [UNW_PPC64_F10]="FPR10",
+ [UNW_PPC64_F11]="FPR11",
+ [UNW_PPC64_F12]="FPR12",
+ [UNW_PPC64_F13]="FPR13",
+ [UNW_PPC64_F14]="FPR14",
+ [UNW_PPC64_F15]="FPR15",
+ [UNW_PPC64_F16]="FPR16",
+ [UNW_PPC64_F17]="FPR17",
+ [UNW_PPC64_F18]="FPR18",
+ [UNW_PPC64_F19]="FPR19",
+ [UNW_PPC64_F20]="FPR20",
+ [UNW_PPC64_F21]="FPR21",
+ [UNW_PPC64_F22]="FPR22",
+ [UNW_PPC64_F23]="FPR23",
+ [UNW_PPC64_F24]="FPR24",
+ [UNW_PPC64_F25]="FPR25",
+ [UNW_PPC64_F26]="FPR26",
+ [UNW_PPC64_F27]="FPR27",
+ [UNW_PPC64_F28]="FPR28",
+ [UNW_PPC64_F29]="FPR29",
+ [UNW_PPC64_F30]="FPR30",
+ [UNW_PPC64_F31]="FPR31",
+
+ [UNW_PPC64_LR]="LR",
+ [UNW_PPC64_CTR]="CTR",
+ [UNW_PPC64_ARG_POINTER]="ARG_POINTER",
+
+ [UNW_PPC64_CR0]="CR0",
+ [UNW_PPC64_CR1]="CR1",
+ [UNW_PPC64_CR2]="CR2",
+ [UNW_PPC64_CR3]="CR3",
+ [UNW_PPC64_CR4]="CR4",
+ [UNW_PPC64_CR5]="CR5",
+ [UNW_PPC64_CR6]="CR6",
+ [UNW_PPC64_CR7]="CR7",
+
+ [UNW_PPC64_XER]="XER",
+
+ [UNW_PPC64_V0]="VR0",
+ [UNW_PPC64_V1]="VR1",
+ [UNW_PPC64_V2]="VR2",
+ [UNW_PPC64_V3]="VR3",
+ [UNW_PPC64_V4]="VR4",
+ [UNW_PPC64_V5]="VR5",
+ [UNW_PPC64_V6]="VR6",
+ [UNW_PPC64_V7]="VR7",
+ [UNW_PPC64_V8]="VR8",
+ [UNW_PPC64_V9]="VR9",
+ [UNW_PPC64_V10]="VR10",
+ [UNW_PPC64_V11]="VR11",
+ [UNW_PPC64_V12]="VR12",
+ [UNW_PPC64_V13]="VR13",
+ [UNW_PPC64_V14]="VR14",
+ [UNW_PPC64_V15]="VR15",
+ [UNW_PPC64_V16]="VR16",
+ [UNW_PPC64_V17]="VR17",
+ [UNW_PPC64_V18]="VR18",
+ [UNW_PPC64_V19]="VR19",
+ [UNW_PPC64_V20]="VR20",
+ [UNW_PPC64_V21]="VR21",
+ [UNW_PPC64_V22]="VR22",
+ [UNW_PPC64_V23]="VR23",
+ [UNW_PPC64_V24]="VR24",
+ [UNW_PPC64_V25]="VR25",
+ [UNW_PPC64_V26]="VR26",
+ [UNW_PPC64_V27]="VR27",
+ [UNW_PPC64_V28]="VR28",
+ [UNW_PPC64_V29]="VR29",
+ [UNW_PPC64_V30]="VR30",
+ [UNW_PPC64_V31]="VR31",
+
+ [UNW_PPC64_VSCR]="VSCR",
+
+ [UNW_PPC64_VRSAVE]="VRSAVE",
+ [UNW_PPC64_SPE_ACC]="SPE_ACC",
+ [UNW_PPC64_SPEFSCR]="SPEFSCR",
+
+ [UNW_PPC64_FRAME_POINTER]="FRAME_POINTER",
+ [UNW_PPC64_NIP]="NIP",
+
+ };
+
+const char *
+unw_regname (unw_regnum_t reg)
+{
+ if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
+ return regname[reg];
+ else
+ return "???";
+}
diff --git a/src/pal/src/libunwind/src/ppc64/setcontext.S b/src/pal/src/libunwind/src/ppc64/setcontext.S
new file mode 100644
index 0000000000..ffc2500a51
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/setcontext.S
@@ -0,0 +1,9 @@
+ .global _UI_setcontext
+
+_UI_setcontext:
+ blr
+
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/src/ppc64/ucontext_i.h b/src/pal/src/libunwind/src/ppc64/ucontext_i.h
new file mode 100644
index 0000000000..2ddfdb865a
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/ucontext_i.h
@@ -0,0 +1,173 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef ucontext_i_h
+#define ucontext_i_h
+
+#include <ucontext.h>
+
+/* These values were derived by reading
+ /usr/src/linux-2.6.18-1.8/arch/um/include/sysdep-ppc/ptrace.h and
+ /usr/src/linux-2.6.18-1.8/arch/powerpc/kernel/ppc32.h
+*/
+
+#define NIP_IDX 32
+#define MSR_IDX 33
+#define ORIG_GPR3_IDX 34
+#define CTR_IDX 35
+#define LINK_IDX 36
+#define XER_IDX 37
+#define CCR_IDX 38
+#define SOFTE_IDX 39
+#define TRAP_IDX 40
+#define DAR_IDX 41
+#define DSISR_IDX 42
+#define RESULT_IDX 43
+
+#define VSCR_IDX 32
+#define VRSAVE_IDX 33
+
+/* These are dummy structures used only for obtaining the offsets of the
+ various structure members. */
+static ucontext_t dmy_ctxt;
+static vrregset_t dmy_vrregset;
+
+#define UC_MCONTEXT_GREGS_R0 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[0] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R1 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[1] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R2 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[2] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R3 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[3] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R4 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[4] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R5 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[5] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R6 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[6] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R7 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[7] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R8 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[8] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R9 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[9] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R10 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[10] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R11 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[11] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R12 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[12] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R13 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[13] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R14 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[14] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R15 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[15] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R16 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[16] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R17 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[17] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R18 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[18] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R19 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[19] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R20 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[20] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R21 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[21] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R22 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[22] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R23 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[23] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R24 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[24] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R25 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[25] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R26 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[26] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R27 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[27] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R28 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[28] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R29 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[29] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R30 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[30] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_R31 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[31] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_NIP ((void *)&dmy_ctxt.uc_mcontext.gp_regs[NIP_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_MSR ((void *)&dmy_ctxt.uc_mcontext.gp_regs[MSR_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_ORIG_GPR3 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[ORIG_GPR3_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_CTR ((void *)&dmy_ctxt.uc_mcontext.gp_regs[CTR_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_LINK ((void *)&dmy_ctxt.uc_mcontext.gp_regs[LINK_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_XER ((void *)&dmy_ctxt.uc_mcontext.gp_regs[XER_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_CCR ((void *)&dmy_ctxt.uc_mcontext.gp_regs[CCR_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_SOFTE ((void *)&dmy_ctxt.uc_mcontext.gp_regs[SOFTE_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_TRAP ((void *)&dmy_ctxt.uc_mcontext.gp_regs[TRAP_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_DAR ((void *)&dmy_ctxt.uc_mcontext.gp_regs[DAR_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_DSISR ((void *)&dmy_ctxt.uc_mcontext.gp_regs[DSISR_IDX] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_GREGS_RESULT ((void *)&dmy_ctxt.uc_mcontext.gp_regs[RESULT_IDX] - (void *)&dmy_ctxt)
+
+#define UC_MCONTEXT_FREGS_R0 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[0] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R1 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[1] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R2 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[2] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R3 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[3] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R4 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[4] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R5 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[5] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R6 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[6] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R7 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[7] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R8 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[8] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R9 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[9] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R10 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[10] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R11 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[11] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R12 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[12] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R13 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[13] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R14 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[14] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R15 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[15] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R16 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[16] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R17 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[17] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R18 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[18] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R19 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[19] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R20 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[20] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R21 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[21] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R22 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[22] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R23 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[23] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R24 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[24] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R25 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[25] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R26 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[26] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R27 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[27] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R28 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[28] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R29 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[29] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R30 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[30] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_R31 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[31] - (void *)&dmy_ctxt)
+#define UC_MCONTEXT_FREGS_FPSCR ((void *)&dmy_ctxt.uc_mcontext.fp_regs[32] - (void *)&dmy_ctxt)
+
+#define UC_MCONTEXT_V_REGS ((void *)&dmy_ctxt.uc_mcontext.v_regs - (void *)&dmy_ctxt)
+
+#define UC_MCONTEXT_VREGS_R0 ((void *)&dmy_vrregset.vrregs[0] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R1 ((void *)&dmy_vrregset.vrregs[1] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R2 ((void *)&dmy_vrregset.vrregs[2] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R3 ((void *)&dmy_vrregset.vrregs[3] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R4 ((void *)&dmy_vrregset.vrregs[4] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R5 ((void *)&dmy_vrregset.vrregs[5] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R6 ((void *)&dmy_vrregset.vrregs[6] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R7 ((void *)&dmy_vrregset.vrregs[7] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R8 ((void *)&dmy_vrregset.vrregs[8] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R9 ((void *)&dmy_vrregset.vrregs[9] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R10 ((void *)&dmy_vrregset.vrregs[10] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R11 ((void *)&dmy_vrregset.vrregs[11] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R12 ((void *)&dmy_vrregset.vrregs[12] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R13 ((void *)&dmy_vrregset.vrregs[13] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R14 ((void *)&dmy_vrregset.vrregs[14] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R15 ((void *)&dmy_vrregset.vrregs[15] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R16 ((void *)&dmy_vrregset.vrregs[16] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R17 ((void *)&dmy_vrregset.vrregs[17] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R18 ((void *)&dmy_vrregset.vrregs[18] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R19 ((void *)&dmy_vrregset.vrregs[19] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R20 ((void *)&dmy_vrregset.vrregs[20] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R21 ((void *)&dmy_vrregset.vrregs[21] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R22 ((void *)&dmy_vrregset.vrregs[22] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R23 ((void *)&dmy_vrregset.vrregs[23] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R24 ((void *)&dmy_vrregset.vrregs[24] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R25 ((void *)&dmy_vrregset.vrregs[25] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R26 ((void *)&dmy_vrregset.vrregs[26] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R27 ((void *)&dmy_vrregset.vrregs[27] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R28 ((void *)&dmy_vrregset.vrregs[28] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R29 ((void *)&dmy_vrregset.vrregs[29] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R30 ((void *)&dmy_vrregset.vrregs[30] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_R31 ((void *)&dmy_vrregset.vrregs[31] - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_VSCR ((void *)&dmy_vrregset.vscr - (void *)&dmy_vrregset)
+#define UC_MCONTEXT_VREGS_VRSAVE ((void *)&dmy_vrregset.vrsave - (void *)&dmy_vrregset)
+
+#endif
diff --git a/src/pal/src/libunwind/src/ppc64/unwind_i.h b/src/pal/src/libunwind/src/ppc64/unwind_i.h
new file mode 100644
index 0000000000..26bbc2df83
--- /dev/null
+++ b/src/pal/src/libunwind/src/ppc64/unwind_i.h
@@ -0,0 +1,52 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <cjashfor@us.ibm.com>
+ Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef unwind_i_h
+#define unwind_i_h
+
+#include <stdint.h>
+
+#include <libunwind-ppc64.h>
+
+#include <libunwind_i.h>
+#include <sys/ucontext.h>
+
+#define ppc64_lock UNW_OBJ(lock)
+#define ppc64_local_resume UNW_OBJ(local_resume)
+#define ppc64_local_addr_space_init UNW_OBJ(local_addr_space_init)
+#if 0
+#define ppc64_scratch_loc UNW_OBJ(scratch_loc)
+#endif
+
+extern void ppc64_local_addr_space_init (void);
+extern int ppc64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
+ void *arg);
+#if 0
+extern dwarf_loc_t ppc64_scratch_loc (struct cursor *c, unw_regnum_t reg);
+#endif
+
+#endif /* unwind_i_h */
diff --git a/src/pal/src/libunwind/src/ptrace/_UPT_access_fpreg.c b/src/pal/src/libunwind/src/ptrace/_UPT_access_fpreg.c
new file mode 100644
index 0000000000..2b92462fa9
--- /dev/null
+++ b/src/pal/src/libunwind/src/ptrace/_UPT_access_fpreg.c
@@ -0,0 +1,121 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+ Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UPT_internal.h"
+
+#if HAVE_DECL_PTRACE_POKEUSER || HAVE_TTRACE
+int
+_UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
+ int write, void *arg)
+{
+ unw_word_t *wp = (unw_word_t *) val;
+ struct UPT_info *ui = arg;
+ pid_t pid = ui->pid;
+ int i;
+
+ if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset))
+ return -UNW_EBADREG;
+
+ errno = 0;
+ if (write)
+ for (i = 0; i < (int) (sizeof (*val) / sizeof (wp[i])); ++i)
+ {
+#ifdef HAVE_TTRACE
+# warning No support for ttrace() yet.
+#else
+ ptrace (PTRACE_POKEUSER, pid, _UPT_reg_offset[reg] + i * sizeof(wp[i]),
+ wp[i]);
+#endif
+ if (errno)
+ return -UNW_EBADREG;
+ }
+ else
+ for (i = 0; i < (int) (sizeof (*val) / sizeof (wp[i])); ++i)
+ {
+#ifdef HAVE_TTRACE
+# warning No support for ttrace() yet.
+#else
+ wp[i] = ptrace (PTRACE_PEEKUSER, pid,
+ _UPT_reg_offset[reg] + i * sizeof(wp[i]), 0);
+#endif
+ if (errno)
+ return -UNW_EBADREG;
+ }
+ return 0;
+}
+#elif HAVE_DECL_PT_GETFPREGS
+int
+_UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
+ int write, void *arg)
+{
+ struct UPT_info *ui = arg;
+ pid_t pid = ui->pid;
+ fpregset_t fpreg;
+
+#if defined(__amd64__)
+ if (1) /* XXXKIB */
+ return -UNW_EBADREG;
+#elif defined(__i386__)
+ if ((unsigned) reg < UNW_X86_ST0 || (unsigned) reg > UNW_X86_ST7)
+ return -UNW_EBADREG;
+#elif defined(__arm__)
+ if ((unsigned) reg < UNW_ARM_F0 || (unsigned) reg > UNW_ARM_F7)
+ return -UNW_EBADREG;
+#else
+#error Fix me
+#endif
+ if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset))
+ return -UNW_EBADREG;
+
+ if (ptrace(PT_GETFPREGS, pid, (caddr_t)&fpreg, 0) == -1)
+ return -UNW_EBADREG;
+ if (write) {
+#if defined(__amd64__)
+ memcpy(&fpreg.fpr_xacc[reg], val, sizeof(unw_fpreg_t));
+#elif defined(__i386__)
+ memcpy(&fpreg.fpr_acc[reg], val, sizeof(unw_fpreg_t));
+#elif defined(__arm__)
+ memcpy(&fpreg.fpr[reg], val, sizeof(unw_fpreg_t));
+#else
+#error Fix me
+#endif
+ if (ptrace(PT_SETFPREGS, pid, (caddr_t)&fpreg, 0) == -1)
+ return -UNW_EBADREG;
+ } else
+#if defined(__amd64__)
+ memcpy(val, &fpreg.fpr_xacc[reg], sizeof(unw_fpreg_t));
+#elif defined(__i386__)
+ memcpy(val, &fpreg.fpr_acc[reg], sizeof(unw_fpreg_t));
+#elif defined(__arm__)
+ memcpy(val, &fpreg.fpr[reg], sizeof(unw_fpreg_t));
+#else
+#error Fix me
+#endif
+ return 0;
+}
+#else
+#error Fix me
+#endif
diff --git a/src/pal/src/libunwind/src/ptrace/_UPT_access_mem.c b/src/pal/src/libunwind/src/ptrace/_UPT_access_mem.c
new file mode 100644
index 0000000000..79bde25dff
--- /dev/null
+++ b/src/pal/src/libunwind/src/ptrace/_UPT_access_mem.c
@@ -0,0 +1,123 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+ Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UPT_internal.h"
+
+#if HAVE_DECL_PTRACE_POKEDATA || HAVE_TTRACE
+int
+_UPT_access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
+ int write, void *arg)
+{
+ struct UPT_info *ui = arg;
+ int i, end;
+ unw_word_t tmp_val;
+
+ if (!ui)
+ return -UNW_EINVAL;
+
+ pid_t pid = ui->pid;
+
+ // Some 32-bit archs have to define a 64-bit unw_word_t.
+ // Callers of this function therefore expect a 64-bit
+ // return value, but ptrace only returns a 32-bit value
+ // in such cases.
+ if (sizeof(long) == 4 && sizeof(unw_word_t) == 8)
+ end = 2;
+ else
+ end = 1;
+
+ for (i = 0; i < end; i++)
+ {
+ unw_word_t tmp_addr = i == 0 ? addr : addr + 4;
+
+ errno = 0;
+ if (write)
+ {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ tmp_val = i == 0 ? *val : *val >> 32;
+#else
+ tmp_val = i == 0 && end == 2 ? *val >> 32 : *val;
+#endif
+
+ Debug (16, "mem[%lx] <- %lx\n", (long) tmp_addr, (long) tmp_val);
+#ifdef HAVE_TTRACE
+# warning No support for ttrace() yet.
+#else
+ ptrace (PTRACE_POKEDATA, pid, tmp_addr, tmp_val);
+ if (errno)
+ return -UNW_EINVAL;
+#endif
+ }
+ else
+ {
+#ifdef HAVE_TTRACE
+# warning No support for ttrace() yet.
+#else
+ tmp_val = (unsigned long) ptrace (PTRACE_PEEKDATA, pid, tmp_addr, 0);
+
+ if (i == 0)
+ *val = 0;
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ *val |= tmp_val << (i * 32);
+#else
+ *val |= i == 0 && end == 2 ? tmp_val << 32 : tmp_val;
+#endif
+
+ if (errno)
+ return -UNW_EINVAL;
+#endif
+ Debug (16, "mem[%lx] -> %lx\n", (long) tmp_addr, (long) tmp_val);
+ }
+ }
+ return 0;
+}
+#elif HAVE_DECL_PT_IO
+int
+_UPT_access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
+ int write, void *arg)
+{
+ struct UPT_info *ui = arg;
+ if (!ui)
+ return -UNW_EINVAL;
+ pid_t pid = ui->pid;
+ struct ptrace_io_desc iod;
+
+ iod.piod_offs = (void *)addr;
+ iod.piod_addr = val;
+ iod.piod_len = sizeof(*val);
+ iod.piod_op = write ? PIOD_WRITE_D : PIOD_READ_D;
+ if (write)
+ Debug (16, "mem[%lx] <- %lx\n", (long) addr, (long) *val);
+ if (ptrace(PT_IO, pid, (caddr_t)&iod, 0) == -1)
+ return -UNW_EINVAL;
+ if (!write)
+ Debug (16, "mem[%lx] -> %lx\n", (long) addr, (long) *val);
+ return 0;
+}
+#else
+#error Fix me
+#endif
diff --git a/src/pal/src/libunwind/src/ptrace/_UPT_access_reg.c b/src/pal/src/libunwind/src/ptrace/_UPT_access_reg.c
new file mode 100644
index 0000000000..ce25c783b0
--- /dev/null
+++ b/src/pal/src/libunwind/src/ptrace/_UPT_access_reg.c
@@ -0,0 +1,352 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+ Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UPT_internal.h"
+
+#if UNW_TARGET_IA64
+# include <elf.h>
+# ifdef HAVE_ASM_PTRACE_OFFSETS_H
+# include <asm/ptrace_offsets.h>
+# endif
+# include "tdep-ia64/rse.h"
+#endif
+
+#if HAVE_DECL_PTRACE_SETREGSET
+#include <sys/uio.h>
+int
+_UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val,
+ int write, void *arg)
+{
+ struct UPT_info *ui = arg;
+ pid_t pid = ui->pid;
+ gregset_t regs;
+ char *r;
+ struct iovec loc;
+
+#if UNW_DEBUG
+ Debug(16, "using getregset: reg: %s [%u], val: %lx, write: %u\n",
+ unw_regname(reg), (unsigned) reg, (long) val, write);
+
+ if (write)
+ Debug (16, "%s [%u] <- %lx\n", unw_regname (reg), (unsigned) reg, (long) *val);
+#endif
+ if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset))
+ {
+ errno = EINVAL;
+ goto badreg;
+ }
+
+ loc.iov_base = &regs;
+ loc.iov_len = sizeof(regs);
+
+ r = (char *)&regs + _UPT_reg_offset[reg];
+ if (ptrace (PTRACE_GETREGSET, pid, NT_PRSTATUS, &loc) == -1)
+ goto badreg;
+ if (write) {
+ memcpy(r, val, sizeof(unw_word_t));
+ if (ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &loc) == -1)
+ goto badreg;
+ } else
+ memcpy(val, r, sizeof(unw_word_t));
+ return 0;
+
+badreg:
+ Debug (1, "bad register %s [%u] (error: %s)\n", unw_regname(reg), reg, strerror (errno));
+ return -UNW_EBADREG;
+}
+#elif HAVE_DECL_PTRACE_POKEUSER || HAVE_TTRACE
+int
+_UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val,
+ int write, void *arg)
+{
+ struct UPT_info *ui = arg;
+ pid_t pid = ui->pid;
+
+#if UNW_DEBUG
+ Debug(16, "using pokeuser: reg: %s [%u], val: %lx, write: %d\n", unw_regname(reg), (unsigned) reg, (long) val, write);
+
+ if (write)
+ Debug (16, "%s <- %lx\n", unw_regname (reg), (long) *val);
+#endif
+
+#if UNW_TARGET_IA64
+ if ((unsigned) reg - UNW_IA64_NAT < 32)
+ {
+ unsigned long nat_bits, mask;
+
+ /* The Linux ptrace represents the statc NaT bits as a single word. */
+ mask = ((unw_word_t) 1) << (reg - UNW_IA64_NAT);
+ errno = 0;
+#ifdef HAVE_TTRACE
+# warning No support for ttrace() yet.
+#else
+ nat_bits = ptrace (PTRACE_PEEKUSER, pid, PT_NAT_BITS, 0);
+ if (errno)
+ goto badreg;
+#endif
+
+ if (write)
+ {
+ if (*val)
+ nat_bits |= mask;
+ else
+ nat_bits &= ~mask;
+#ifdef HAVE_TTRACE
+# warning No support for ttrace() yet.
+#else
+ errno = 0;
+ ptrace (PTRACE_POKEUSER, pid, PT_NAT_BITS, nat_bits);
+ if (errno)
+ goto badreg;
+#endif
+ }
+ goto out;
+ }
+ else
+ switch (reg)
+ {
+ case UNW_IA64_GR + 0:
+ if (write)
+ goto badreg;
+ *val = 0;
+ return 0;
+
+ case UNW_REG_IP:
+ {
+ unsigned long ip, psr;
+
+ /* distribute bundle-addr. & slot-number across PT_IIP & PT_IPSR. */
+#ifdef HAVE_TTRACE
+# warning No support for ttrace() yet.
+#else
+ errno = 0;
+ psr = ptrace (PTRACE_PEEKUSER, pid, PT_CR_IPSR, 0);
+ if (errno)
+ goto badreg;
+#endif
+ if (write)
+ {
+ ip = *val & ~0xfUL;
+ psr = (psr & ~0x3UL << 41) | (*val & 0x3);
+#ifdef HAVE_TTRACE
+# warning No support for ttrace() yet.
+#else
+ errno = 0;
+ ptrace (PTRACE_POKEUSER, pid, PT_CR_IIP, ip);
+ ptrace (PTRACE_POKEUSER, pid, PT_CR_IPSR, psr);
+ if (errno)
+ goto badreg;
+#endif
+ }
+ else
+ {
+#ifdef HAVE_TTRACE
+# warning No support for ttrace() yet.
+#else
+ errno = 0;
+ ip = ptrace (PTRACE_PEEKUSER, pid, PT_CR_IIP, 0);
+ if (errno)
+ goto badreg;
+#endif
+ *val = ip + ((psr >> 41) & 0x3);
+ }
+ goto out;
+ }
+
+ case UNW_IA64_AR_BSPSTORE:
+ reg = UNW_IA64_AR_BSP;
+ break;
+
+ case UNW_IA64_AR_BSP:
+ case UNW_IA64_BSP:
+ {
+ unsigned long sof, cfm, bsp;
+
+#ifdef HAVE_TTRACE
+# warning No support for ttrace() yet.
+#else
+ /* Account for the fact that ptrace() expects bsp to point
+ _after_ the current register frame. */
+ errno = 0;
+ cfm = ptrace (PTRACE_PEEKUSER, pid, PT_CFM, 0);
+ if (errno)
+ goto badreg;
+#endif
+ sof = (cfm & 0x7f);
+
+ if (write)
+ {
+ bsp = rse_skip_regs (*val, sof);
+#ifdef HAVE_TTRACE
+# warning No support for ttrace() yet.
+#else
+ errno = 0;
+ ptrace (PTRACE_POKEUSER, pid, PT_AR_BSP, bsp);
+ if (errno)
+ goto badreg;
+#endif
+ }
+ else
+ {
+#ifdef HAVE_TTRACE
+# warning No support for ttrace() yet.
+#else
+ errno = 0;
+ bsp = ptrace (PTRACE_PEEKUSER, pid, PT_AR_BSP, 0);
+ if (errno)
+ goto badreg;
+#endif
+ *val = rse_skip_regs (bsp, -sof);
+ }
+ goto out;
+ }
+
+ case UNW_IA64_CFM:
+ /* If we change CFM, we need to adjust ptrace's notion of bsp
+ accordingly, so that the real bsp remains unchanged. */
+ if (write)
+ {
+ unsigned long new_sof, old_sof, cfm, bsp;
+
+#ifdef HAVE_TTRACE
+# warning No support for ttrace() yet.
+#else
+ errno = 0;
+ bsp = ptrace (PTRACE_PEEKUSER, pid, PT_AR_BSP, 0);
+ cfm = ptrace (PTRACE_PEEKUSER, pid, PT_CFM, 0);
+#endif
+ if (errno)
+ goto badreg;
+ old_sof = (cfm & 0x7f);
+ new_sof = (*val & 0x7f);
+ if (old_sof != new_sof)
+ {
+ bsp = rse_skip_regs (bsp, -old_sof + new_sof);
+#ifdef HAVE_TTRACE
+# warning No support for ttrace() yet.
+#else
+ errno = 0;
+ ptrace (PTRACE_POKEUSER, pid, PT_AR_BSP, 0);
+ if (errno)
+ goto badreg;
+#endif
+ }
+#ifdef HAVE_TTRACE
+# warning No support for ttrace() yet.
+#else
+ errno = 0;
+ ptrace (PTRACE_POKEUSER, pid, PT_CFM, *val);
+ if (errno)
+ goto badreg;
+#endif
+ goto out;
+ }
+ break;
+ }
+#endif /* End of IA64 */
+
+ if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset))
+ {
+#if UNW_DEBUG
+ Debug(2, "register out of range: >= %zu / %zu\n", sizeof(_UPT_reg_offset), sizeof(_UPT_reg_offset[0]));
+#endif
+ errno = EINVAL;
+ goto badreg;
+ }
+
+#ifdef HAVE_TTRACE
+# warning No support for ttrace() yet.
+#else
+ errno = 0;
+ if (write)
+ ptrace (PTRACE_POKEUSER, pid, _UPT_reg_offset[reg], *val);
+ else {
+#if UNW_DEBUG
+ Debug(16, "ptrace PEEKUSER pid: %lu , reg: %lu , offs: %lu\n", (unsigned long)pid, (unsigned long)reg,
+ (unsigned long)_UPT_reg_offset[reg]);
+#endif
+ *val = ptrace (PTRACE_PEEKUSER, pid, _UPT_reg_offset[reg], 0);
+ }
+ if (errno) {
+#if UNW_DEBUG
+ Debug(2, "ptrace failure\n");
+#endif
+ goto badreg;
+ }
+#endif
+
+#ifdef UNW_TARGET_IA64
+ out:
+#endif
+#if UNW_DEBUG
+ if (!write)
+ Debug (16, "%s[%u] -> %lx\n", unw_regname (reg), (unsigned) reg, (long) *val);
+#endif
+ return 0;
+
+ badreg:
+ Debug (1, "bad register %s [%u] (error: %s)\n", unw_regname(reg), reg, strerror (errno));
+ return -UNW_EBADREG;
+}
+#elif HAVE_DECL_PT_GETREGS
+int
+_UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val,
+ int write, void *arg)
+{
+ struct UPT_info *ui = arg;
+ pid_t pid = ui->pid;
+ gregset_t regs;
+ char *r;
+
+#if UNW_DEBUG
+ Debug(16, "using getregs: reg: %s [%u], val: %lx, write: %u\n", unw_regname(reg), (unsigned) reg, (long) val, write);
+
+ if (write)
+ Debug (16, "%s [%u] <- %lx\n", unw_regname (reg), (unsigned) reg, (long) *val);
+#endif
+ if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset))
+ {
+ errno = EINVAL;
+ goto badreg;
+ }
+ r = (char *)&regs + _UPT_reg_offset[reg];
+ if (ptrace(PT_GETREGS, pid, (caddr_t)&regs, 0) == -1)
+ goto badreg;
+ if (write) {
+ memcpy(r, val, sizeof(unw_word_t));
+ if (ptrace(PT_SETREGS, pid, (caddr_t)&regs, 0) == -1)
+ goto badreg;
+ } else
+ memcpy(val, r, sizeof(unw_word_t));
+ return 0;
+
+ badreg:
+ Debug (1, "bad register %s [%u] (error: %s)\n", unw_regname(reg), reg, strerror (errno));
+ return -UNW_EBADREG;
+}
+#else
+#error Port me
+#endif
diff --git a/src/pal/src/libunwind/src/ptrace/_UPT_accessors.c b/src/pal/src/libunwind/src/ptrace/_UPT_accessors.c
new file mode 100644
index 0000000000..4724360bb9
--- /dev/null
+++ b/src/pal/src/libunwind/src/ptrace/_UPT_accessors.c
@@ -0,0 +1,38 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UPT_internal.h"
+
+unw_accessors_t _UPT_accessors =
+ {
+ .find_proc_info = _UPT_find_proc_info,
+ .put_unwind_info = _UPT_put_unwind_info,
+ .get_dyn_info_list_addr = _UPT_get_dyn_info_list_addr,
+ .access_mem = _UPT_access_mem,
+ .access_reg = _UPT_access_reg,
+ .access_fpreg = _UPT_access_fpreg,
+ .resume = _UPT_resume,
+ .get_proc_name = _UPT_get_proc_name
+ };
diff --git a/src/pal/src/libunwind/src/ptrace/_UPT_create.c b/src/pal/src/libunwind/src/ptrace/_UPT_create.c
new file mode 100644
index 0000000000..dd59e974a7
--- /dev/null
+++ b/src/pal/src/libunwind/src/ptrace/_UPT_create.c
@@ -0,0 +1,46 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <string.h>
+
+#include "_UPT_internal.h"
+
+void *
+_UPT_create (pid_t pid)
+{
+ struct UPT_info *ui = malloc (sizeof (struct UPT_info));
+
+ if (!ui)
+ return NULL;
+
+ memset (ui, 0, sizeof (*ui));
+ ui->pid = pid;
+ ui->edi.di_cache.format = -1;
+ ui->edi.di_debug.format = -1;
+#if UNW_TARGET_IA64
+ ui->edi.ktab.format = -1;
+#endif
+ return ui;
+}
diff --git a/src/pal/src/libunwind/src/ptrace/_UPT_destroy.c b/src/pal/src/libunwind/src/ptrace/_UPT_destroy.c
new file mode 100644
index 0000000000..edb664ce12
--- /dev/null
+++ b/src/pal/src/libunwind/src/ptrace/_UPT_destroy.c
@@ -0,0 +1,34 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UPT_internal.h"
+
+void
+_UPT_destroy (void *ptr)
+{
+ struct UPT_info *ui = (struct UPT_info *) ptr;
+ invalidate_edi (&ui->edi);
+ free (ptr);
+}
diff --git a/src/pal/src/libunwind/src/ptrace/_UPT_elf.c b/src/pal/src/libunwind/src/ptrace/_UPT_elf.c
new file mode 100644
index 0000000000..efc43b578b
--- /dev/null
+++ b/src/pal/src/libunwind/src/ptrace/_UPT_elf.c
@@ -0,0 +1,5 @@
+/* We need to get a separate copy of the ELF-code into
+ libunwind-ptrace since it cannot (and must not) have any ELF
+ dependencies on libunwind. */
+#include "libunwind_i.h" /* get ELFCLASS defined */
+#include "../elfxx.c"
diff --git a/src/pal/src/libunwind/src/ptrace/_UPT_find_proc_info.c b/src/pal/src/libunwind/src/ptrace/_UPT_find_proc_info.c
new file mode 100644
index 0000000000..b3209f451e
--- /dev/null
+++ b/src/pal/src/libunwind/src/ptrace/_UPT_find_proc_info.c
@@ -0,0 +1,145 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <elf.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+
+#include "_UPT_internal.h"
+
+static int
+get_unwind_info (struct elf_dyn_info *edi, pid_t pid, unw_addr_space_t as, unw_word_t ip)
+{
+ unsigned long segbase, mapoff;
+ char path[PATH_MAX];
+
+#if UNW_TARGET_IA64 && defined(__linux)
+ if (!edi->ktab.start_ip && _Uia64_get_kernel_table (&edi->ktab) < 0)
+ return -UNW_ENOINFO;
+
+ if (edi->ktab.format != -1 && ip >= edi->ktab.start_ip && ip < edi->ktab.end_ip)
+ return 0;
+#endif
+
+ if ((edi->di_cache.format != -1
+ && ip >= edi->di_cache.start_ip && ip < edi->di_cache.end_ip)
+#if UNW_TARGET_ARM
+ || (edi->di_debug.format != -1
+ && ip >= edi->di_arm.start_ip && ip < edi->di_arm.end_ip)
+#endif
+ || (edi->di_debug.format != -1
+ && ip >= edi->di_debug.start_ip && ip < edi->di_debug.end_ip))
+ return 0;
+
+ invalidate_edi(edi);
+
+ if (tdep_get_elf_image (&edi->ei, pid, ip, &segbase, &mapoff, path,
+ sizeof(path)) < 0)
+ return -UNW_ENOINFO;
+
+ /* Here, SEGBASE is the starting-address of the (mmap'ped) segment
+ which covers the IP we're looking for. */
+ if (tdep_find_unwind_table (edi, as, path, segbase, mapoff, ip) < 0)
+ return -UNW_ENOINFO;
+
+ /* This can happen in corner cases where dynamically generated
+ code falls into the same page that contains the data-segment
+ and the page-offset of the code is within the first page of
+ the executable. */
+ if (edi->di_cache.format != -1
+ && (ip < edi->di_cache.start_ip || ip >= edi->di_cache.end_ip))
+ edi->di_cache.format = -1;
+
+ if (edi->di_debug.format != -1
+ && (ip < edi->di_debug.start_ip || ip >= edi->di_debug.end_ip))
+ edi->di_debug.format = -1;
+
+ if (edi->di_cache.format == -1
+#if UNW_TARGET_ARM
+ && edi->di_arm.format == -1
+#endif
+ && edi->di_debug.format == -1)
+ return -UNW_ENOINFO;
+
+ return 0;
+}
+
+int
+_UPT_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg)
+{
+ struct UPT_info *ui = arg;
+ int ret = -UNW_ENOINFO;
+
+ if (get_unwind_info (&ui->edi, ui->pid, as, ip) < 0)
+ return -UNW_ENOINFO;
+
+#if UNW_TARGET_IA64
+ if (ui->edi.ktab.format != -1)
+ {
+ /* The kernel unwind table resides in local memory, so we have
+ to use the local address space to search it. Since
+ _UPT_put_unwind_info() has no easy way of detecting this
+ case, we simply make a copy of the unwind-info, so
+ _UPT_put_unwind_info() can always free() the unwind-info
+ without ill effects. */
+ ret = tdep_search_unwind_table (unw_local_addr_space, ip, &ui->edi.ktab, pi,
+ need_unwind_info, arg);
+ if (ret >= 0)
+ {
+ if (!need_unwind_info)
+ pi->unwind_info = NULL;
+ else
+ {
+ void *mem = malloc (pi->unwind_info_size);
+
+ if (!mem)
+ return -UNW_ENOMEM;
+ memcpy (mem, pi->unwind_info, pi->unwind_info_size);
+ pi->unwind_info = mem;
+ }
+ }
+ }
+#endif
+
+ if (ret == -UNW_ENOINFO && ui->edi.di_cache.format != -1)
+ ret = tdep_search_unwind_table (as, ip, &ui->edi.di_cache,
+ pi, need_unwind_info, arg);
+
+ if (ret == -UNW_ENOINFO && ui->edi.di_debug.format != -1)
+ ret = tdep_search_unwind_table (as, ip, &ui->edi.di_debug, pi,
+ need_unwind_info, arg);
+
+#if UNW_TARGET_ARM
+ if (ret == -UNW_ENOINFO && ui->edi.di_arm.format != -1)
+ ret = tdep_search_unwind_table (as, ip, &ui->edi.di_arm, pi,
+ need_unwind_info, arg);
+#endif
+
+ return ret;
+}
diff --git a/src/pal/src/libunwind/src/ptrace/_UPT_get_dyn_info_list_addr.c b/src/pal/src/libunwind/src/ptrace/_UPT_get_dyn_info_list_addr.c
new file mode 100644
index 0000000000..cc5ed04418
--- /dev/null
+++ b/src/pal/src/libunwind/src/ptrace/_UPT_get_dyn_info_list_addr.c
@@ -0,0 +1,105 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UPT_internal.h"
+
+#if UNW_TARGET_IA64 && defined(__linux)
+# include "elf64.h"
+# include "os-linux.h"
+
+static inline int
+get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg,
+ int *countp)
+{
+ unsigned long lo, hi, off;
+ struct UPT_info *ui = arg;
+ struct map_iterator mi;
+ char path[PATH_MAX];
+ unw_word_t res;
+ int count = 0;
+
+ maps_init (&mi, ui->pid);
+ while (maps_next (&mi, &lo, &hi, &off))
+ {
+ if (off)
+ continue;
+
+ invalidate_edi(&ui->edi);
+
+ if (elf_map_image (&ui->edi.ei, path) < 0)
+ /* ignore unmappable stuff like "/SYSV00001b58 (deleted)" */
+ continue;
+
+ Debug (16, "checking object %s\n", path);
+
+ if (tdep_find_unwind_table (&ui->edi, as, path, lo, off, 0) > 0)
+ {
+ res = _Uia64_find_dyn_list (as, &ui->edi.di_cache, arg);
+ if (res && count++ == 0)
+ {
+ Debug (12, "dyn_info_list_addr = 0x%lx\n", (long) res);
+ *dil_addr = res;
+ }
+ }
+ }
+ maps_close (&mi);
+ *countp = count;
+ return 0;
+}
+
+#else
+
+static inline int
+get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg,
+ int *countp)
+{
+# warning Implement get_list_addr(), please.
+ *countp = 0;
+ return 0;
+}
+
+#endif
+
+int
+_UPT_get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dil_addr,
+ void *arg)
+{
+ int count, ret;
+
+ Debug (12, "looking for dyn_info list\n");
+
+ if ((ret = get_list_addr (as, dil_addr, arg, &count)) < 0)
+ return ret;
+
+ /* If multiple dynamic-info list addresses are found, we would have
+ to determine which was is the one actually in use (since the
+ dynamic name resolution algorithm will pick one "winner").
+ Perhaps we'd have to track them all until we find one that's
+ non-empty. Hopefully, this case simply will never arise, since
+ only libunwind defines the dynamic info list head. */
+ assert (count <= 1);
+
+ return (count > 0) ? 0 : -UNW_ENOINFO;
+}
diff --git a/src/pal/src/libunwind/src/ptrace/_UPT_get_proc_name.c b/src/pal/src/libunwind/src/ptrace/_UPT_get_proc_name.c
new file mode 100644
index 0000000000..79c1f38e25
--- /dev/null
+++ b/src/pal/src/libunwind/src/ptrace/_UPT_get_proc_name.c
@@ -0,0 +1,42 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Copyright (C) 2007 David Mosberger-Tang
+ Contributed by David Mosberger-Tang <dmosberger@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UPT_internal.h"
+
+int
+_UPT_get_proc_name (unw_addr_space_t as, unw_word_t ip,
+ char *buf, size_t buf_len, unw_word_t *offp, void *arg)
+{
+ struct UPT_info *ui = arg;
+
+#if ELF_CLASS == ELFCLASS64
+ return _Uelf64_get_proc_name (as, ui->pid, ip, buf, buf_len, offp);
+#elif ELF_CLASS == ELFCLASS32
+ return _Uelf32_get_proc_name (as, ui->pid, ip, buf, buf_len, offp);
+#else
+ return -UNW_ENOINFO;
+#endif
+}
diff --git a/src/pal/src/libunwind/src/ptrace/_UPT_internal.h b/src/pal/src/libunwind/src/ptrace/_UPT_internal.h
new file mode 100644
index 0000000000..5cef2573ee
--- /dev/null
+++ b/src/pal/src/libunwind/src/ptrace/_UPT_internal.h
@@ -0,0 +1,59 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003, 2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _UPT_internal_h
+#define _UPT_internal_h
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_PTRACE_H
+#include <sys/ptrace.h>
+#endif
+#ifdef HAVE_SYS_PROCFS_H
+#include <sys/procfs.h>
+#endif
+
+#include <errno.h>
+#include <libunwind-ptrace.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "libunwind_i.h"
+
+struct UPT_info
+ {
+ pid_t pid; /* the process-id of the child we're unwinding */
+ struct elf_dyn_info edi;
+ };
+
+extern const int _UPT_reg_offset[UNW_REG_LAST + 1];
+
+#endif /* _UPT_internal_h */
diff --git a/src/pal/src/libunwind/src/ptrace/_UPT_put_unwind_info.c b/src/pal/src/libunwind/src/ptrace/_UPT_put_unwind_info.c
new file mode 100644
index 0000000000..d4b8463147
--- /dev/null
+++ b/src/pal/src/libunwind/src/ptrace/_UPT_put_unwind_info.c
@@ -0,0 +1,35 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UPT_internal.h"
+
+void
+_UPT_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg)
+{
+ if (!pi->unwind_info)
+ return;
+ free (pi->unwind_info);
+ pi->unwind_info = NULL;
+}
diff --git a/src/pal/src/libunwind/src/ptrace/_UPT_reg_offset.c b/src/pal/src/libunwind/src/ptrace/_UPT_reg_offset.c
new file mode 100644
index 0000000000..c82d1c9887
--- /dev/null
+++ b/src/pal/src/libunwind/src/ptrace/_UPT_reg_offset.c
@@ -0,0 +1,638 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+ Copyright (C) 2013 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UPT_internal.h"
+
+#include <stddef.h>
+
+#ifdef HAVE_ASM_PTRACE_OFFSETS_H
+# include <asm/ptrace_offsets.h>
+#endif
+
+const int _UPT_reg_offset[UNW_REG_LAST + 1] =
+ {
+#ifdef HAVE_ASM_PTRACE_OFFSETS_H
+# ifndef PT_AR_CSD
+# define PT_AR_CSD -1 /* this was introduced with rev 2.1 of ia64 */
+# endif
+
+ [UNW_IA64_GR + 0] = -1, [UNW_IA64_GR + 1] = PT_R1,
+ [UNW_IA64_GR + 2] = PT_R2, [UNW_IA64_GR + 3] = PT_R3,
+ [UNW_IA64_GR + 4] = PT_R4, [UNW_IA64_GR + 5] = PT_R5,
+ [UNW_IA64_GR + 6] = PT_R6, [UNW_IA64_GR + 7] = PT_R7,
+ [UNW_IA64_GR + 8] = PT_R8, [UNW_IA64_GR + 9] = PT_R9,
+ [UNW_IA64_GR + 10] = PT_R10, [UNW_IA64_GR + 11] = PT_R11,
+ [UNW_IA64_GR + 12] = PT_R12, [UNW_IA64_GR + 13] = PT_R13,
+ [UNW_IA64_GR + 14] = PT_R14, [UNW_IA64_GR + 15] = PT_R15,
+ [UNW_IA64_GR + 16] = PT_R16, [UNW_IA64_GR + 17] = PT_R17,
+ [UNW_IA64_GR + 18] = PT_R18, [UNW_IA64_GR + 19] = PT_R19,
+ [UNW_IA64_GR + 20] = PT_R20, [UNW_IA64_GR + 21] = PT_R21,
+ [UNW_IA64_GR + 22] = PT_R22, [UNW_IA64_GR + 23] = PT_R23,
+ [UNW_IA64_GR + 24] = PT_R24, [UNW_IA64_GR + 25] = PT_R25,
+ [UNW_IA64_GR + 26] = PT_R26, [UNW_IA64_GR + 27] = PT_R27,
+ [UNW_IA64_GR + 28] = PT_R28, [UNW_IA64_GR + 29] = PT_R29,
+ [UNW_IA64_GR + 30] = PT_R30, [UNW_IA64_GR + 31] = PT_R31,
+
+ [UNW_IA64_NAT+ 0] = -1, [UNW_IA64_NAT+ 1] = PT_NAT_BITS,
+ [UNW_IA64_NAT+ 2] = PT_NAT_BITS, [UNW_IA64_NAT+ 3] = PT_NAT_BITS,
+ [UNW_IA64_NAT+ 4] = PT_NAT_BITS, [UNW_IA64_NAT+ 5] = PT_NAT_BITS,
+ [UNW_IA64_NAT+ 6] = PT_NAT_BITS, [UNW_IA64_NAT+ 7] = PT_NAT_BITS,
+ [UNW_IA64_NAT+ 8] = PT_NAT_BITS, [UNW_IA64_NAT+ 9] = PT_NAT_BITS,
+ [UNW_IA64_NAT+ 10] = PT_NAT_BITS, [UNW_IA64_NAT+ 11] = PT_NAT_BITS,
+ [UNW_IA64_NAT+ 12] = PT_NAT_BITS, [UNW_IA64_NAT+ 13] = PT_NAT_BITS,
+ [UNW_IA64_NAT+ 14] = PT_NAT_BITS, [UNW_IA64_NAT+ 15] = PT_NAT_BITS,
+ [UNW_IA64_NAT+ 16] = PT_NAT_BITS, [UNW_IA64_NAT+ 17] = PT_NAT_BITS,
+ [UNW_IA64_NAT+ 18] = PT_NAT_BITS, [UNW_IA64_NAT+ 19] = PT_NAT_BITS,
+ [UNW_IA64_NAT+ 20] = PT_NAT_BITS, [UNW_IA64_NAT+ 21] = PT_NAT_BITS,
+ [UNW_IA64_NAT+ 22] = PT_NAT_BITS, [UNW_IA64_NAT+ 23] = PT_NAT_BITS,
+ [UNW_IA64_NAT+ 24] = PT_NAT_BITS, [UNW_IA64_NAT+ 25] = PT_NAT_BITS,
+ [UNW_IA64_NAT+ 26] = PT_NAT_BITS, [UNW_IA64_NAT+ 27] = PT_NAT_BITS,
+ [UNW_IA64_NAT+ 28] = PT_NAT_BITS, [UNW_IA64_NAT+ 29] = PT_NAT_BITS,
+ [UNW_IA64_NAT+ 30] = PT_NAT_BITS, [UNW_IA64_NAT+ 31] = PT_NAT_BITS,
+
+ [UNW_IA64_FR + 0] = -1, [UNW_IA64_FR + 1] = -1,
+ [UNW_IA64_FR + 2] = PT_F2, [UNW_IA64_FR + 3] = PT_F3,
+ [UNW_IA64_FR + 4] = PT_F4, [UNW_IA64_FR + 5] = PT_F5,
+ [UNW_IA64_FR + 6] = PT_F6, [UNW_IA64_FR + 7] = PT_F7,
+ [UNW_IA64_FR + 8] = PT_F8, [UNW_IA64_FR + 9] = PT_F9,
+ [UNW_IA64_FR + 10] = PT_F10, [UNW_IA64_FR + 11] = PT_F11,
+ [UNW_IA64_FR + 12] = PT_F12, [UNW_IA64_FR + 13] = PT_F13,
+ [UNW_IA64_FR + 14] = PT_F14, [UNW_IA64_FR + 15] = PT_F15,
+ [UNW_IA64_FR + 16] = PT_F16, [UNW_IA64_FR + 17] = PT_F17,
+ [UNW_IA64_FR + 18] = PT_F18, [UNW_IA64_FR + 19] = PT_F19,
+ [UNW_IA64_FR + 20] = PT_F20, [UNW_IA64_FR + 21] = PT_F21,
+ [UNW_IA64_FR + 22] = PT_F22, [UNW_IA64_FR + 23] = PT_F23,
+ [UNW_IA64_FR + 24] = PT_F24, [UNW_IA64_FR + 25] = PT_F25,
+ [UNW_IA64_FR + 26] = PT_F26, [UNW_IA64_FR + 27] = PT_F27,
+ [UNW_IA64_FR + 28] = PT_F28, [UNW_IA64_FR + 29] = PT_F29,
+ [UNW_IA64_FR + 30] = PT_F30, [UNW_IA64_FR + 31] = PT_F31,
+ [UNW_IA64_FR + 32] = PT_F32, [UNW_IA64_FR + 33] = PT_F33,
+ [UNW_IA64_FR + 34] = PT_F34, [UNW_IA64_FR + 35] = PT_F35,
+ [UNW_IA64_FR + 36] = PT_F36, [UNW_IA64_FR + 37] = PT_F37,
+ [UNW_IA64_FR + 38] = PT_F38, [UNW_IA64_FR + 39] = PT_F39,
+ [UNW_IA64_FR + 40] = PT_F40, [UNW_IA64_FR + 41] = PT_F41,
+ [UNW_IA64_FR + 42] = PT_F42, [UNW_IA64_FR + 43] = PT_F43,
+ [UNW_IA64_FR + 44] = PT_F44, [UNW_IA64_FR + 45] = PT_F45,
+ [UNW_IA64_FR + 46] = PT_F46, [UNW_IA64_FR + 47] = PT_F47,
+ [UNW_IA64_FR + 48] = PT_F48, [UNW_IA64_FR + 49] = PT_F49,
+ [UNW_IA64_FR + 50] = PT_F50, [UNW_IA64_FR + 51] = PT_F51,
+ [UNW_IA64_FR + 52] = PT_F52, [UNW_IA64_FR + 53] = PT_F53,
+ [UNW_IA64_FR + 54] = PT_F54, [UNW_IA64_FR + 55] = PT_F55,
+ [UNW_IA64_FR + 56] = PT_F56, [UNW_IA64_FR + 57] = PT_F57,
+ [UNW_IA64_FR + 58] = PT_F58, [UNW_IA64_FR + 59] = PT_F59,
+ [UNW_IA64_FR + 60] = PT_F60, [UNW_IA64_FR + 61] = PT_F61,
+ [UNW_IA64_FR + 62] = PT_F62, [UNW_IA64_FR + 63] = PT_F63,
+ [UNW_IA64_FR + 64] = PT_F64, [UNW_IA64_FR + 65] = PT_F65,
+ [UNW_IA64_FR + 66] = PT_F66, [UNW_IA64_FR + 67] = PT_F67,
+ [UNW_IA64_FR + 68] = PT_F68, [UNW_IA64_FR + 69] = PT_F69,
+ [UNW_IA64_FR + 70] = PT_F70, [UNW_IA64_FR + 71] = PT_F71,
+ [UNW_IA64_FR + 72] = PT_F72, [UNW_IA64_FR + 73] = PT_F73,
+ [UNW_IA64_FR + 74] = PT_F74, [UNW_IA64_FR + 75] = PT_F75,
+ [UNW_IA64_FR + 76] = PT_F76, [UNW_IA64_FR + 77] = PT_F77,
+ [UNW_IA64_FR + 78] = PT_F78, [UNW_IA64_FR + 79] = PT_F79,
+ [UNW_IA64_FR + 80] = PT_F80, [UNW_IA64_FR + 81] = PT_F81,
+ [UNW_IA64_FR + 82] = PT_F82, [UNW_IA64_FR + 83] = PT_F83,
+ [UNW_IA64_FR + 84] = PT_F84, [UNW_IA64_FR + 85] = PT_F85,
+ [UNW_IA64_FR + 86] = PT_F86, [UNW_IA64_FR + 87] = PT_F87,
+ [UNW_IA64_FR + 88] = PT_F88, [UNW_IA64_FR + 89] = PT_F89,
+ [UNW_IA64_FR + 90] = PT_F90, [UNW_IA64_FR + 91] = PT_F91,
+ [UNW_IA64_FR + 92] = PT_F92, [UNW_IA64_FR + 93] = PT_F93,
+ [UNW_IA64_FR + 94] = PT_F94, [UNW_IA64_FR + 95] = PT_F95,
+ [UNW_IA64_FR + 96] = PT_F96, [UNW_IA64_FR + 97] = PT_F97,
+ [UNW_IA64_FR + 98] = PT_F98, [UNW_IA64_FR + 99] = PT_F99,
+ [UNW_IA64_FR +100] = PT_F100, [UNW_IA64_FR +101] = PT_F101,
+ [UNW_IA64_FR +102] = PT_F102, [UNW_IA64_FR +103] = PT_F103,
+ [UNW_IA64_FR +104] = PT_F104, [UNW_IA64_FR +105] = PT_F105,
+ [UNW_IA64_FR +106] = PT_F106, [UNW_IA64_FR +107] = PT_F107,
+ [UNW_IA64_FR +108] = PT_F108, [UNW_IA64_FR +109] = PT_F109,
+ [UNW_IA64_FR +110] = PT_F110, [UNW_IA64_FR +111] = PT_F111,
+ [UNW_IA64_FR +112] = PT_F112, [UNW_IA64_FR +113] = PT_F113,
+ [UNW_IA64_FR +114] = PT_F114, [UNW_IA64_FR +115] = PT_F115,
+ [UNW_IA64_FR +116] = PT_F116, [UNW_IA64_FR +117] = PT_F117,
+ [UNW_IA64_FR +118] = PT_F118, [UNW_IA64_FR +119] = PT_F119,
+ [UNW_IA64_FR +120] = PT_F120, [UNW_IA64_FR +121] = PT_F121,
+ [UNW_IA64_FR +122] = PT_F122, [UNW_IA64_FR +123] = PT_F123,
+ [UNW_IA64_FR +124] = PT_F124, [UNW_IA64_FR +125] = PT_F125,
+ [UNW_IA64_FR +126] = PT_F126, [UNW_IA64_FR +127] = PT_F127,
+
+ [UNW_IA64_AR + 0] = -1, [UNW_IA64_AR + 1] = -1,
+ [UNW_IA64_AR + 2] = -1, [UNW_IA64_AR + 3] = -1,
+ [UNW_IA64_AR + 4] = -1, [UNW_IA64_AR + 5] = -1,
+ [UNW_IA64_AR + 6] = -1, [UNW_IA64_AR + 7] = -1,
+ [UNW_IA64_AR + 8] = -1, [UNW_IA64_AR + 9] = -1,
+ [UNW_IA64_AR + 10] = -1, [UNW_IA64_AR + 11] = -1,
+ [UNW_IA64_AR + 12] = -1, [UNW_IA64_AR + 13] = -1,
+ [UNW_IA64_AR + 14] = -1, [UNW_IA64_AR + 15] = -1,
+ [UNW_IA64_AR + 16] = PT_AR_RSC, [UNW_IA64_AR + 17] = PT_AR_BSP,
+ [UNW_IA64_AR + 18] = PT_AR_BSPSTORE,[UNW_IA64_AR + 19] = PT_AR_RNAT,
+ [UNW_IA64_AR + 20] = -1, [UNW_IA64_AR + 21] = -1,
+ [UNW_IA64_AR + 22] = -1, [UNW_IA64_AR + 23] = -1,
+ [UNW_IA64_AR + 24] = -1, [UNW_IA64_AR + 25] = PT_AR_CSD,
+ [UNW_IA64_AR + 26] = -1, [UNW_IA64_AR + 27] = -1,
+ [UNW_IA64_AR + 28] = -1, [UNW_IA64_AR + 29] = -1,
+ [UNW_IA64_AR + 30] = -1, [UNW_IA64_AR + 31] = -1,
+ [UNW_IA64_AR + 32] = PT_AR_CCV, [UNW_IA64_AR + 33] = -1,
+ [UNW_IA64_AR + 34] = -1, [UNW_IA64_AR + 35] = -1,
+ [UNW_IA64_AR + 36] = PT_AR_UNAT, [UNW_IA64_AR + 37] = -1,
+ [UNW_IA64_AR + 38] = -1, [UNW_IA64_AR + 39] = -1,
+ [UNW_IA64_AR + 40] = PT_AR_FPSR, [UNW_IA64_AR + 41] = -1,
+ [UNW_IA64_AR + 42] = -1, [UNW_IA64_AR + 43] = -1,
+ [UNW_IA64_AR + 44] = -1, [UNW_IA64_AR + 45] = -1,
+ [UNW_IA64_AR + 46] = -1, [UNW_IA64_AR + 47] = -1,
+ [UNW_IA64_AR + 48] = -1, [UNW_IA64_AR + 49] = -1,
+ [UNW_IA64_AR + 50] = -1, [UNW_IA64_AR + 51] = -1,
+ [UNW_IA64_AR + 52] = -1, [UNW_IA64_AR + 53] = -1,
+ [UNW_IA64_AR + 54] = -1, [UNW_IA64_AR + 55] = -1,
+ [UNW_IA64_AR + 56] = -1, [UNW_IA64_AR + 57] = -1,
+ [UNW_IA64_AR + 58] = -1, [UNW_IA64_AR + 59] = -1,
+ [UNW_IA64_AR + 60] = -1, [UNW_IA64_AR + 61] = -1,
+ [UNW_IA64_AR + 62] = -1, [UNW_IA64_AR + 63] = -1,
+ [UNW_IA64_AR + 64] = PT_AR_PFS, [UNW_IA64_AR + 65] = PT_AR_LC,
+ [UNW_IA64_AR + 66] = PT_AR_EC, [UNW_IA64_AR + 67] = -1,
+ [UNW_IA64_AR + 68] = -1, [UNW_IA64_AR + 69] = -1,
+ [UNW_IA64_AR + 70] = -1, [UNW_IA64_AR + 71] = -1,
+ [UNW_IA64_AR + 72] = -1, [UNW_IA64_AR + 73] = -1,
+ [UNW_IA64_AR + 74] = -1, [UNW_IA64_AR + 75] = -1,
+ [UNW_IA64_AR + 76] = -1, [UNW_IA64_AR + 77] = -1,
+ [UNW_IA64_AR + 78] = -1, [UNW_IA64_AR + 79] = -1,
+ [UNW_IA64_AR + 80] = -1, [UNW_IA64_AR + 81] = -1,
+ [UNW_IA64_AR + 82] = -1, [UNW_IA64_AR + 83] = -1,
+ [UNW_IA64_AR + 84] = -1, [UNW_IA64_AR + 85] = -1,
+ [UNW_IA64_AR + 86] = -1, [UNW_IA64_AR + 87] = -1,
+ [UNW_IA64_AR + 88] = -1, [UNW_IA64_AR + 89] = -1,
+ [UNW_IA64_AR + 90] = -1, [UNW_IA64_AR + 91] = -1,
+ [UNW_IA64_AR + 92] = -1, [UNW_IA64_AR + 93] = -1,
+ [UNW_IA64_AR + 94] = -1, [UNW_IA64_AR + 95] = -1,
+ [UNW_IA64_AR + 96] = -1, [UNW_IA64_AR + 97] = -1,
+ [UNW_IA64_AR + 98] = -1, [UNW_IA64_AR + 99] = -1,
+ [UNW_IA64_AR +100] = -1, [UNW_IA64_AR +101] = -1,
+ [UNW_IA64_AR +102] = -1, [UNW_IA64_AR +103] = -1,
+ [UNW_IA64_AR +104] = -1, [UNW_IA64_AR +105] = -1,
+ [UNW_IA64_AR +106] = -1, [UNW_IA64_AR +107] = -1,
+ [UNW_IA64_AR +108] = -1, [UNW_IA64_AR +109] = -1,
+ [UNW_IA64_AR +110] = -1, [UNW_IA64_AR +111] = -1,
+ [UNW_IA64_AR +112] = -1, [UNW_IA64_AR +113] = -1,
+ [UNW_IA64_AR +114] = -1, [UNW_IA64_AR +115] = -1,
+ [UNW_IA64_AR +116] = -1, [UNW_IA64_AR +117] = -1,
+ [UNW_IA64_AR +118] = -1, [UNW_IA64_AR +119] = -1,
+ [UNW_IA64_AR +120] = -1, [UNW_IA64_AR +121] = -1,
+ [UNW_IA64_AR +122] = -1, [UNW_IA64_AR +123] = -1,
+ [UNW_IA64_AR +124] = -1, [UNW_IA64_AR +125] = -1,
+ [UNW_IA64_AR +126] = -1, [UNW_IA64_AR +127] = -1,
+
+ [UNW_IA64_BR + 0] = PT_B0, [UNW_IA64_BR + 1] = PT_B1,
+ [UNW_IA64_BR + 2] = PT_B2, [UNW_IA64_BR + 3] = PT_B3,
+ [UNW_IA64_BR + 4] = PT_B4, [UNW_IA64_BR + 5] = PT_B5,
+ [UNW_IA64_BR + 6] = PT_B6, [UNW_IA64_BR + 7] = PT_B7,
+
+ [UNW_IA64_PR] = PT_PR,
+ [UNW_IA64_CFM] = PT_CFM,
+ [UNW_IA64_IP] = PT_CR_IIP
+#elif defined(HAVE_TTRACE)
+# warning No support for ttrace() yet.
+#elif defined(UNW_TARGET_HPPA)
+ [UNW_HPPA_GR + 0] = 0x000, [UNW_HPPA_GR + 1] = 0x004,
+ [UNW_HPPA_GR + 2] = 0x008, [UNW_HPPA_GR + 3] = 0x00c,
+ [UNW_HPPA_GR + 4] = 0x010, [UNW_HPPA_GR + 5] = 0x014,
+ [UNW_HPPA_GR + 6] = 0x018, [UNW_HPPA_GR + 7] = 0x01c,
+ [UNW_HPPA_GR + 8] = 0x020, [UNW_HPPA_GR + 9] = 0x024,
+ [UNW_HPPA_GR + 10] = 0x028, [UNW_HPPA_GR + 11] = 0x02c,
+ [UNW_HPPA_GR + 12] = 0x030, [UNW_HPPA_GR + 13] = 0x034,
+ [UNW_HPPA_GR + 14] = 0x038, [UNW_HPPA_GR + 15] = 0x03c,
+ [UNW_HPPA_GR + 16] = 0x040, [UNW_HPPA_GR + 17] = 0x044,
+ [UNW_HPPA_GR + 18] = 0x048, [UNW_HPPA_GR + 19] = 0x04c,
+ [UNW_HPPA_GR + 20] = 0x050, [UNW_HPPA_GR + 21] = 0x054,
+ [UNW_HPPA_GR + 22] = 0x058, [UNW_HPPA_GR + 23] = 0x05c,
+ [UNW_HPPA_GR + 24] = 0x060, [UNW_HPPA_GR + 25] = 0x064,
+ [UNW_HPPA_GR + 26] = 0x068, [UNW_HPPA_GR + 27] = 0x06c,
+ [UNW_HPPA_GR + 28] = 0x070, [UNW_HPPA_GR + 29] = 0x074,
+ [UNW_HPPA_GR + 30] = 0x078, [UNW_HPPA_GR + 31] = 0x07c,
+
+ [UNW_HPPA_FR + 0] = 0x080, [UNW_HPPA_FR + 1] = 0x088,
+ [UNW_HPPA_FR + 2] = 0x090, [UNW_HPPA_FR + 3] = 0x098,
+ [UNW_HPPA_FR + 4] = 0x0a0, [UNW_HPPA_FR + 5] = 0x0a8,
+ [UNW_HPPA_FR + 6] = 0x0b0, [UNW_HPPA_FR + 7] = 0x0b8,
+ [UNW_HPPA_FR + 8] = 0x0c0, [UNW_HPPA_FR + 9] = 0x0c8,
+ [UNW_HPPA_FR + 10] = 0x0d0, [UNW_HPPA_FR + 11] = 0x0d8,
+ [UNW_HPPA_FR + 12] = 0x0e0, [UNW_HPPA_FR + 13] = 0x0e8,
+ [UNW_HPPA_FR + 14] = 0x0f0, [UNW_HPPA_FR + 15] = 0x0f8,
+ [UNW_HPPA_FR + 16] = 0x100, [UNW_HPPA_FR + 17] = 0x108,
+ [UNW_HPPA_FR + 18] = 0x110, [UNW_HPPA_FR + 19] = 0x118,
+ [UNW_HPPA_FR + 20] = 0x120, [UNW_HPPA_FR + 21] = 0x128,
+ [UNW_HPPA_FR + 22] = 0x130, [UNW_HPPA_FR + 23] = 0x138,
+ [UNW_HPPA_FR + 24] = 0x140, [UNW_HPPA_FR + 25] = 0x148,
+ [UNW_HPPA_FR + 26] = 0x150, [UNW_HPPA_FR + 27] = 0x158,
+ [UNW_HPPA_FR + 28] = 0x160, [UNW_HPPA_FR + 29] = 0x168,
+ [UNW_HPPA_FR + 30] = 0x170, [UNW_HPPA_FR + 31] = 0x178,
+
+ [UNW_HPPA_IP] = 0x1a8 /* IAOQ[0] */
+#elif defined(UNW_TARGET_X86)
+#if defined __FreeBSD__
+#define UNW_R_OFF(R, r) \
+ [UNW_X86_##R] = offsetof(gregset_t, r_##r),
+ UNW_R_OFF(EAX, eax)
+ UNW_R_OFF(EDX, edx)
+ UNW_R_OFF(ECX, ecx)
+ UNW_R_OFF(EBX, ebx)
+ UNW_R_OFF(ESI, esi)
+ UNW_R_OFF(EDI, edi)
+ UNW_R_OFF(EBP, ebp)
+ UNW_R_OFF(ESP, esp)
+ UNW_R_OFF(EIP, eip)
+// UNW_R_OFF(CS, cs)
+// UNW_R_OFF(EFLAGS, eflags)
+// UNW_R_OFF(SS, ss)
+#elif defined __linux__
+ [UNW_X86_EAX] = 0x18,
+ [UNW_X86_EBX] = 0x00,
+ [UNW_X86_ECX] = 0x04,
+ [UNW_X86_EDX] = 0x08,
+ [UNW_X86_ESI] = 0x0c,
+ [UNW_X86_EDI] = 0x10,
+ [UNW_X86_EBP] = 0x14,
+ [UNW_X86_EIP] = 0x30,
+ [UNW_X86_ESP] = 0x3c
+/* CS = 0x34, */
+/* DS = 0x1c, */
+/* ES = 0x20, */
+/* FS = 0x24, */
+/* GS = 0x28, */
+/* ORIG_EAX = 0x2c, */
+/* EFLAGS = 0x38, */
+/* SS = 0x40 */
+#else
+#error Port me
+#endif
+#elif defined(UNW_TARGET_X86_64)
+#if defined __FreeBSD__
+#define UNW_R_OFF(R, r) \
+ [UNW_X86_64_##R] = offsetof(gregset_t, r_##r),
+ UNW_R_OFF(RAX, rax)
+ UNW_R_OFF(RDX, rdx)
+ UNW_R_OFF(RCX, rcx)
+ UNW_R_OFF(RBX, rbx)
+ UNW_R_OFF(RSI, rsi)
+ UNW_R_OFF(RDI, rdi)
+ UNW_R_OFF(RBP, rbp)
+ UNW_R_OFF(RSP, rsp)
+ UNW_R_OFF(R8, r8)
+ UNW_R_OFF(R9, r9)
+ UNW_R_OFF(R10, r10)
+ UNW_R_OFF(R11, r11)
+ UNW_R_OFF(R12, r12)
+ UNW_R_OFF(R13, r13)
+ UNW_R_OFF(R14, r14)
+ UNW_R_OFF(R15, r15)
+ UNW_R_OFF(RIP, rip)
+// UNW_R_OFF(CS, cs)
+// UNW_R_OFF(EFLAGS, rflags)
+// UNW_R_OFF(SS, ss)
+#undef UNW_R_OFF
+#elif defined __linux__
+ [UNW_X86_64_RAX] = 0x50,
+ [UNW_X86_64_RDX] = 0x60,
+ [UNW_X86_64_RCX] = 0x58,
+ [UNW_X86_64_RBX] = 0x28,
+ [UNW_X86_64_RSI] = 0x68,
+ [UNW_X86_64_RDI] = 0x70,
+ [UNW_X86_64_RBP] = 0x20,
+ [UNW_X86_64_RSP] = 0x98,
+ [UNW_X86_64_R8] = 0x48,
+ [UNW_X86_64_R9] = 0x40,
+ [UNW_X86_64_R10] = 0x38,
+ [UNW_X86_64_R11] = 0x30,
+ [UNW_X86_64_R12] = 0x18,
+ [UNW_X86_64_R13] = 0x10,
+ [UNW_X86_64_R14] = 0x08,
+ [UNW_X86_64_R15] = 0x00,
+ [UNW_X86_64_RIP] = 0x80
+// [UNW_X86_64_CS] = 0x88,
+// [UNW_X86_64_EFLAGS] = 0x90,
+// [UNW_X86_64_RSP] = 0x98,
+// [UNW_X86_64_SS] = 0xa0
+#else
+#error Port me
+#endif
+#elif defined(UNW_TARGET_PPC32) || defined(UNW_TARGET_PPC64)
+
+#define UNW_REG_SLOT_SIZE sizeof(unsigned long)
+#define UNW_PPC_R(v) ((v) * UNW_REG_SLOT_SIZE)
+#define UNW_PPC_PT(p) UNW_PPC_R(PT_##p)
+
+#define UNW_FP_OFF(b, i) \
+ [UNW_PPC##b##_F##i] = UNW_PPC_R(PT_FPR0 + i * 8/UNW_REG_SLOT_SIZE)
+
+#define UNW_R_OFF(b, i) \
+ [UNW_PPC##b##_R##i] = UNW_PPC_R(PT_R##i)
+
+#define UNW_PPC_REGS(b) \
+ UNW_R_OFF(b, 0), \
+ UNW_R_OFF(b, 1), \
+ UNW_R_OFF(b, 2), \
+ UNW_R_OFF(b, 3), \
+ UNW_R_OFF(b, 4), \
+ UNW_R_OFF(b, 5), \
+ UNW_R_OFF(b, 6), \
+ UNW_R_OFF(b, 7), \
+ UNW_R_OFF(b, 8), \
+ UNW_R_OFF(b, 9), \
+ UNW_R_OFF(b, 10), \
+ UNW_R_OFF(b, 11), \
+ UNW_R_OFF(b, 12), \
+ UNW_R_OFF(b, 13), \
+ UNW_R_OFF(b, 14), \
+ UNW_R_OFF(b, 15), \
+ UNW_R_OFF(b, 16), \
+ UNW_R_OFF(b, 17), \
+ UNW_R_OFF(b, 18), \
+ UNW_R_OFF(b, 19), \
+ UNW_R_OFF(b, 20), \
+ UNW_R_OFF(b, 21), \
+ UNW_R_OFF(b, 22), \
+ UNW_R_OFF(b, 23), \
+ UNW_R_OFF(b, 24), \
+ UNW_R_OFF(b, 25), \
+ UNW_R_OFF(b, 26), \
+ UNW_R_OFF(b, 27), \
+ UNW_R_OFF(b, 28), \
+ UNW_R_OFF(b, 29), \
+ UNW_R_OFF(b, 30), \
+ UNW_R_OFF(b, 31), \
+ \
+ [UNW_PPC##b##_CTR] = UNW_PPC_PT(CTR), \
+ [UNW_PPC##b##_XER] = UNW_PPC_PT(XER), \
+ [UNW_PPC##b##_LR] = UNW_PPC_PT(LNK), \
+ \
+ UNW_FP_OFF(b, 0), \
+ UNW_FP_OFF(b, 1), \
+ UNW_FP_OFF(b, 2), \
+ UNW_FP_OFF(b, 3), \
+ UNW_FP_OFF(b, 4), \
+ UNW_FP_OFF(b, 5), \
+ UNW_FP_OFF(b, 6), \
+ UNW_FP_OFF(b, 7), \
+ UNW_FP_OFF(b, 8), \
+ UNW_FP_OFF(b, 9), \
+ UNW_FP_OFF(b, 10), \
+ UNW_FP_OFF(b, 11), \
+ UNW_FP_OFF(b, 12), \
+ UNW_FP_OFF(b, 13), \
+ UNW_FP_OFF(b, 14), \
+ UNW_FP_OFF(b, 15), \
+ UNW_FP_OFF(b, 16), \
+ UNW_FP_OFF(b, 17), \
+ UNW_FP_OFF(b, 18), \
+ UNW_FP_OFF(b, 19), \
+ UNW_FP_OFF(b, 20), \
+ UNW_FP_OFF(b, 21), \
+ UNW_FP_OFF(b, 22), \
+ UNW_FP_OFF(b, 23), \
+ UNW_FP_OFF(b, 24), \
+ UNW_FP_OFF(b, 25), \
+ UNW_FP_OFF(b, 26), \
+ UNW_FP_OFF(b, 27), \
+ UNW_FP_OFF(b, 28), \
+ UNW_FP_OFF(b, 29), \
+ UNW_FP_OFF(b, 30), \
+ UNW_FP_OFF(b, 31)
+
+#define UNW_PPC32_REGS \
+ [UNW_PPC32_FPSCR] = UNW_PPC_PT(FPSCR), \
+ [UNW_PPC32_CCR] = UNW_PPC_PT(CCR)
+
+#define UNW_VR_OFF(i) \
+ [UNW_PPC64_V##i] = UNW_PPC_R(PT_VR0 + i * 2)
+
+#define UNW_PPC64_REGS \
+ [UNW_PPC64_NIP] = UNW_PPC_PT(NIP), \
+ [UNW_PPC64_FRAME_POINTER] = -1, \
+ [UNW_PPC64_ARG_POINTER] = -1, \
+ [UNW_PPC64_CR0] = -1, \
+ [UNW_PPC64_CR1] = -1, \
+ [UNW_PPC64_CR2] = -1, \
+ [UNW_PPC64_CR3] = -1, \
+ [UNW_PPC64_CR4] = -1, \
+ [UNW_PPC64_CR5] = -1, \
+ [UNW_PPC64_CR6] = -1, \
+ [UNW_PPC64_CR7] = -1, \
+ [UNW_PPC64_VRSAVE] = UNW_PPC_PT(VRSAVE), \
+ [UNW_PPC64_VSCR] = UNW_PPC_PT(VSCR), \
+ [UNW_PPC64_SPE_ACC] = -1, \
+ [UNW_PPC64_SPEFSCR] = -1, \
+ UNW_VR_OFF(0), \
+ UNW_VR_OFF(1), \
+ UNW_VR_OFF(2), \
+ UNW_VR_OFF(3), \
+ UNW_VR_OFF(4), \
+ UNW_VR_OFF(5), \
+ UNW_VR_OFF(6), \
+ UNW_VR_OFF(7), \
+ UNW_VR_OFF(8), \
+ UNW_VR_OFF(9), \
+ UNW_VR_OFF(10), \
+ UNW_VR_OFF(11), \
+ UNW_VR_OFF(12), \
+ UNW_VR_OFF(13), \
+ UNW_VR_OFF(14), \
+ UNW_VR_OFF(15), \
+ UNW_VR_OFF(16), \
+ UNW_VR_OFF(17), \
+ UNW_VR_OFF(18), \
+ UNW_VR_OFF(19), \
+ UNW_VR_OFF(20), \
+ UNW_VR_OFF(21), \
+ UNW_VR_OFF(22), \
+ UNW_VR_OFF(23), \
+ UNW_VR_OFF(24), \
+ UNW_VR_OFF(25), \
+ UNW_VR_OFF(26), \
+ UNW_VR_OFF(27), \
+ UNW_VR_OFF(28), \
+ UNW_VR_OFF(29), \
+ UNW_VR_OFF(30), \
+ UNW_VR_OFF(31)
+
+#if defined(UNW_TARGET_PPC32)
+ UNW_PPC_REGS(32),
+ UNW_PPC32_REGS,
+#else
+ UNW_PPC_REGS(64),
+ UNW_PPC64_REGS,
+#endif
+
+#elif defined(UNW_TARGET_ARM)
+#if defined(__linux__) || defined(__FreeBSD__)
+ [UNW_ARM_R0] = 0x00,
+ [UNW_ARM_R1] = 0x04,
+ [UNW_ARM_R2] = 0x08,
+ [UNW_ARM_R3] = 0x0c,
+ [UNW_ARM_R4] = 0x10,
+ [UNW_ARM_R5] = 0x14,
+ [UNW_ARM_R6] = 0x18,
+ [UNW_ARM_R7] = 0x1c,
+ [UNW_ARM_R8] = 0x20,
+ [UNW_ARM_R9] = 0x24,
+ [UNW_ARM_R10] = 0x28,
+ [UNW_ARM_R11] = 0x2c,
+ [UNW_ARM_R12] = 0x30,
+ [UNW_ARM_R13] = 0x34,
+ [UNW_ARM_R14] = 0x38,
+ [UNW_ARM_R15] = 0x3c,
+#else
+#error Fix me
+#endif
+#elif defined(UNW_TARGET_MIPS)
+ [UNW_MIPS_R0] = 0,
+ [UNW_MIPS_R1] = 1,
+ [UNW_MIPS_R2] = 2,
+ [UNW_MIPS_R3] = 3,
+ [UNW_MIPS_R4] = 4,
+ [UNW_MIPS_R5] = 5,
+ [UNW_MIPS_R6] = 6,
+ [UNW_MIPS_R7] = 7,
+ [UNW_MIPS_R8] = 8,
+ [UNW_MIPS_R9] = 9,
+ [UNW_MIPS_R10] = 10,
+ [UNW_MIPS_R11] = 11,
+ [UNW_MIPS_R12] = 12,
+ [UNW_MIPS_R13] = 13,
+ [UNW_MIPS_R14] = 14,
+ [UNW_MIPS_R15] = 15,
+ [UNW_MIPS_R16] = 16,
+ [UNW_MIPS_R17] = 17,
+ [UNW_MIPS_R18] = 18,
+ [UNW_MIPS_R19] = 19,
+ [UNW_MIPS_R20] = 20,
+ [UNW_MIPS_R21] = 21,
+ [UNW_MIPS_R22] = 22,
+ [UNW_MIPS_R23] = 23,
+ [UNW_MIPS_R24] = 24,
+ [UNW_MIPS_R25] = 25,
+ [UNW_MIPS_R26] = 26,
+ [UNW_MIPS_R27] = 27,
+ [UNW_MIPS_R28] = 28,
+ [UNW_MIPS_R29] = 29,
+ [UNW_MIPS_R30] = 30,
+ [UNW_MIPS_R31] = 31,
+ [UNW_MIPS_PC] = 64,
+#elif defined(UNW_TARGET_SH)
+#elif defined(UNW_TARGET_AARCH64)
+ [UNW_AARCH64_X0] = 0x00,
+ [UNW_AARCH64_X1] = 0x08,
+ [UNW_AARCH64_X2] = 0x10,
+ [UNW_AARCH64_X3] = 0x18,
+ [UNW_AARCH64_X4] = 0x20,
+ [UNW_AARCH64_X5] = 0x28,
+ [UNW_AARCH64_X6] = 0x30,
+ [UNW_AARCH64_X7] = 0x38,
+ [UNW_AARCH64_X8] = 0x40,
+ [UNW_AARCH64_X9] = 0x48,
+ [UNW_AARCH64_X10] = 0x50,
+ [UNW_AARCH64_X11] = 0x58,
+ [UNW_AARCH64_X12] = 0x60,
+ [UNW_AARCH64_X13] = 0x68,
+ [UNW_AARCH64_X14] = 0x70,
+ [UNW_AARCH64_X15] = 0x78,
+ [UNW_AARCH64_X16] = 0x80,
+ [UNW_AARCH64_X17] = 0x88,
+ [UNW_AARCH64_X18] = 0x90,
+ [UNW_AARCH64_X19] = 0x98,
+ [UNW_AARCH64_X20] = 0xa0,
+ [UNW_AARCH64_X21] = 0xa8,
+ [UNW_AARCH64_X22] = 0xb0,
+ [UNW_AARCH64_X23] = 0xb8,
+ [UNW_AARCH64_X24] = 0xc0,
+ [UNW_AARCH64_X25] = 0xc8,
+ [UNW_AARCH64_X26] = 0xd0,
+ [UNW_AARCH64_X27] = 0xd8,
+ [UNW_AARCH64_X28] = 0xe0,
+ [UNW_AARCH64_X29] = 0xe8,
+ [UNW_AARCH64_X30] = 0xf0,
+ [UNW_AARCH64_SP] = 0xf8,
+ [UNW_AARCH64_PC] = 0x100,
+ [UNW_AARCH64_PSTATE] = 0x108
+#elif defined(UNW_TARGET_TILEGX)
+ [UNW_TILEGX_R0] = 0x00,
+ [UNW_TILEGX_R1] = 0x08,
+ [UNW_TILEGX_R2] = 0x10,
+ [UNW_TILEGX_R3] = 0x08,
+ [UNW_TILEGX_R4] = 0x20,
+ [UNW_TILEGX_R5] = 0x28,
+ [UNW_TILEGX_R6] = 0x30,
+ [UNW_TILEGX_R7] = 0x38,
+ [UNW_TILEGX_R8] = 0x40,
+ [UNW_TILEGX_R9] = 0x48,
+ [UNW_TILEGX_R10] = 0x50,
+ [UNW_TILEGX_R11] = 0x58,
+ [UNW_TILEGX_R12] = 0x60,
+ [UNW_TILEGX_R13] = 0x68,
+ [UNW_TILEGX_R14] = 0x70,
+ [UNW_TILEGX_R15] = 0x78,
+ [UNW_TILEGX_R16] = 0x80,
+ [UNW_TILEGX_R17] = 0x88,
+ [UNW_TILEGX_R18] = 0x90,
+ [UNW_TILEGX_R19] = 0x98,
+ [UNW_TILEGX_R20] = 0xa0,
+ [UNW_TILEGX_R21] = 0xa8,
+ [UNW_TILEGX_R22] = 0xb0,
+ [UNW_TILEGX_R23] = 0xb8,
+ [UNW_TILEGX_R24] = 0xc0,
+ [UNW_TILEGX_R25] = 0xc8,
+ [UNW_TILEGX_R26] = 0xd0,
+ [UNW_TILEGX_R27] = 0xd8,
+ [UNW_TILEGX_R28] = 0xe0,
+ [UNW_TILEGX_R29] = 0xe8,
+ [UNW_TILEGX_R30] = 0xf0,
+ [UNW_TILEGX_R31] = 0xf8,
+ [UNW_TILEGX_R32] = 0x100,
+ [UNW_TILEGX_R33] = 0x108,
+ [UNW_TILEGX_R34] = 0x110,
+ [UNW_TILEGX_R35] = 0x118,
+ [UNW_TILEGX_R36] = 0x120,
+ [UNW_TILEGX_R37] = 0x128,
+ [UNW_TILEGX_R38] = 0x130,
+ [UNW_TILEGX_R39] = 0x138,
+ [UNW_TILEGX_R40] = 0x140,
+ [UNW_TILEGX_R41] = 0x148,
+ [UNW_TILEGX_R42] = 0x150,
+ [UNW_TILEGX_R43] = 0x158,
+ [UNW_TILEGX_R44] = 0x160,
+ [UNW_TILEGX_R45] = 0x168,
+ [UNW_TILEGX_R46] = 0x170,
+ [UNW_TILEGX_R47] = 0x178,
+ [UNW_TILEGX_R48] = 0x180,
+ [UNW_TILEGX_R49] = 0x188,
+ [UNW_TILEGX_R50] = 0x190,
+ [UNW_TILEGX_R51] = 0x198,
+ [UNW_TILEGX_R52] = 0x1a0,
+ [UNW_TILEGX_R53] = 0x1a8,
+ [UNW_TILEGX_R54] = 0x1b0,
+ [UNW_TILEGX_R55] = 0x1b8,
+ [UNW_TILEGX_PC] = 0x1a0
+#else
+# error Fix me.
+#endif
+ };
diff --git a/src/pal/src/libunwind/src/ptrace/_UPT_resume.c b/src/pal/src/libunwind/src/ptrace/_UPT_resume.c
new file mode 100644
index 0000000000..d70a0d4821
--- /dev/null
+++ b/src/pal/src/libunwind/src/ptrace/_UPT_resume.c
@@ -0,0 +1,40 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "_UPT_internal.h"
+
+int
+_UPT_resume (unw_addr_space_t as, unw_cursor_t *c, void *arg)
+{
+ struct UPT_info *ui = arg;
+
+#ifdef HAVE_TTRACE
+# warning No support for ttrace() yet.
+#elif HAVE_DECL_PTRACE_CONT
+ return ptrace (PTRACE_CONT, ui->pid, 0, 0);
+#elif HAVE_DECL_PT_CONTINUE
+ return ptrace(PT_CONTINUE, ui->pid, (caddr_t)1, 0);
+#endif
+}
diff --git a/src/pal/src/libunwind/src/ptrace/libunwind-ptrace.pc.in b/src/pal/src/libunwind/src/ptrace/libunwind-ptrace.pc.in
new file mode 100644
index 0000000000..673004b69e
--- /dev/null
+++ b/src/pal/src/libunwind/src/ptrace/libunwind-ptrace.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libunwind-ptrace
+Description: libunwind ptrace library
+Version: @VERSION@
+Requires: libunwind-generic libunwind
+Libs: -L${libdir} -lunwind-ptrace
+Cflags: -I${includedir}
diff --git a/src/pal/src/libunwind/src/setjmp/libunwind-setjmp.pc.in b/src/pal/src/libunwind/src/setjmp/libunwind-setjmp.pc.in
new file mode 100644
index 0000000000..7b71126535
--- /dev/null
+++ b/src/pal/src/libunwind/src/setjmp/libunwind-setjmp.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libunwind-setjmp
+Description: libunwind setjmp library
+Version: @VERSION@
+Requires: libunwind
+Libs: -L${libdir} -lunwind-setjmp
+Cflags: -I${includedir}
diff --git a/src/pal/src/libunwind/src/setjmp/longjmp.c b/src/pal/src/libunwind/src/setjmp/longjmp.c
new file mode 100644
index 0000000000..8295a9b8ed
--- /dev/null
+++ b/src/pal/src/libunwind/src/setjmp/longjmp.c
@@ -0,0 +1,115 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#define UNW_LOCAL_ONLY
+
+#undef _FORTIFY_SOURCE
+#include <assert.h>
+#include <libunwind.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdlib.h>
+
+#include "jmpbuf.h"
+#include "setjmp_i.h"
+
+#if defined(__GLIBC__)
+#if __GLIBC_PREREQ(2, 4)
+
+/* Starting with glibc-2.4, {sig,}setjmp in GLIBC obfuscates the
+ register values in jmp_buf by XORing them with a "random"
+ canary value.
+
+ This makes it impossible to implement longjmp, as we
+ can never match wp[JB_SP], unless we decode the canary first.
+
+ Doing so is possible, but doesn't appear to be worth the trouble,
+ so we simply defer to glibc longjmp here. */
+#define _longjmp __nonworking__longjmp
+#define longjmp __nonworking_longjmp
+static void _longjmp (jmp_buf env, int val);
+static void longjmp (jmp_buf env, int val);
+#endif
+#endif /* __GLIBC__ */
+
+void
+_longjmp (jmp_buf env, int val)
+{
+ extern int _UI_longjmp_cont;
+ unw_context_t uc;
+ unw_cursor_t c;
+ unw_word_t sp;
+ unw_word_t *wp = (unw_word_t *) env;
+
+ if (unw_getcontext (&uc) < 0 || unw_init_local (&c, &uc) < 0)
+ abort ();
+
+ do
+ {
+ if (unw_get_reg (&c, UNW_REG_SP, &sp) < 0)
+ abort ();
+#ifdef __FreeBSD__
+ if (sp != wp[JB_SP] + sizeof(unw_word_t))
+#else
+ if (sp != wp[JB_SP])
+#endif
+ continue;
+
+ if (!bsp_match (&c, wp))
+ continue;
+
+ /* found the right frame: */
+
+ assert (UNW_NUM_EH_REGS >= 2);
+
+ if (unw_set_reg (&c, UNW_REG_EH + 0, wp[JB_RP]) < 0
+ || unw_set_reg (&c, UNW_REG_EH + 1, val) < 0
+ || unw_set_reg (&c, UNW_REG_IP,
+ (unw_word_t) (uintptr_t) &_UI_longjmp_cont))
+ abort ();
+
+ unw_resume (&c);
+
+ abort ();
+ }
+ while (unw_step (&c) > 0);
+
+ abort ();
+}
+
+#ifdef __GNUC__
+#define STRINGIFY1(x) #x
+#define STRINGIFY(x) STRINGIFY1(x)
+void longjmp (jmp_buf env, int val)
+ __attribute__ ((alias (STRINGIFY(_longjmp))));
+#else
+
+void
+longjmp (jmp_buf env, int val)
+{
+ _longjmp (env, val);
+}
+
+#endif /* __GNUC__ */
diff --git a/src/pal/src/libunwind/src/setjmp/setjmp.c b/src/pal/src/libunwind/src/setjmp/setjmp.c
new file mode 100644
index 0000000000..bec9fc7d5b
--- /dev/null
+++ b/src/pal/src/libunwind/src/setjmp/setjmp.c
@@ -0,0 +1,49 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <libunwind.h>
+#include <setjmp.h>
+
+#include "jmpbuf.h"
+
+/* Why use K&R syntax here? setjmp() is often a macro and that
+ expands into a call to, say, __setjmp() and we need to define the
+ libunwind-version of setjmp() with the name of the actual function.
+ Using K&R syntax lets us keep the setjmp() macro while keeping the
+ syntax valid... This trick works provided setjmp() doesn't do
+ anything other than a function call. */
+
+int
+setjmp (env)
+ jmp_buf env;
+{
+ void **wp = (void **) env;
+
+ /* this should work on most platforms, but may not be
+ performance-optimal; check the code! */
+ wp[JB_SP] = __builtin_frame_address (0);
+ wp[JB_RP] = (void *) __builtin_return_address (0);
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/setjmp/setjmp_i.h b/src/pal/src/libunwind/src/setjmp/setjmp_i.h
new file mode 100644
index 0000000000..4d9139693e
--- /dev/null
+++ b/src/pal/src/libunwind/src/setjmp/setjmp_i.h
@@ -0,0 +1,118 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#if UNW_TARGET_IA64
+
+#include "libunwind_i.h"
+#include "tdep-ia64/rse.h"
+
+static inline int
+bsp_match (unw_cursor_t *c, unw_word_t *wp)
+{
+ unw_word_t bsp, pfs, sol;
+
+ if (unw_get_reg (c, UNW_IA64_BSP, &bsp) < 0
+ || unw_get_reg (c, UNW_IA64_AR_PFS, &pfs) < 0)
+ abort ();
+
+ /* simulate the effect of "br.call sigsetjmp" on ar.bsp: */
+ sol = (pfs >> 7) & 0x7f;
+ bsp = rse_skip_regs (bsp, sol);
+
+ if (bsp != wp[JB_BSP])
+ return 0;
+
+ if (unlikely (sol == 0))
+ {
+ unw_word_t sp, prev_sp;
+ unw_cursor_t tmp = *c;
+
+ /* The caller of {sig,}setjmp() cannot have a NULL-frame. If we
+ see a NULL-frame, we haven't reached the right target yet.
+ To have a NULL-frame, the number of locals must be zero and
+ the stack-frame must also be empty. */
+
+ if (unw_step (&tmp) < 0)
+ abort ();
+
+ if (unw_get_reg (&tmp, UNW_REG_SP, &sp) < 0
+ || unw_get_reg (&tmp, UNW_REG_SP, &prev_sp) < 0)
+ abort ();
+
+ if (sp == prev_sp)
+ /* got a NULL-frame; keep looking... */
+ return 0;
+ }
+ return 1;
+}
+
+/* On ia64 we cannot always call sigprocmask() at
+ _UI_siglongjmp_cont() because the signal may have switched stacks
+ and the old stack's register-backing store may have overflown,
+ leaving us no space to allocate the stacked registers needed to
+ call sigprocmask(). Fortunately, we can just let unw_resume() (via
+ sigreturn) take care of restoring the signal-mask. That's faster
+ anyhow. */
+static inline int
+resume_restores_sigmask (unw_cursor_t *c, unw_word_t *wp)
+{
+ unw_word_t sc_addr = ((struct cursor *) c)->sigcontext_addr;
+ struct sigcontext *sc = (struct sigcontext *) sc_addr;
+ sigset_t current_mask;
+ void *mp;
+
+ if (!sc_addr)
+ return 0;
+
+ /* let unw_resume() install the desired signal mask */
+
+ if (wp[JB_MASK_SAVED])
+ mp = &wp[JB_MASK];
+ else
+ {
+ if (sigprocmask (SIG_BLOCK, NULL, &current_mask) < 0)
+ abort ();
+ mp = &current_mask;
+ }
+ memcpy (&sc->sc_mask, mp, sizeof (sc->sc_mask));
+ return 1;
+}
+
+#else /* !UNW_TARGET_IA64 */
+
+static inline int
+bsp_match (unw_cursor_t *c, unw_word_t *wp)
+{
+ return 1;
+}
+
+static inline int
+resume_restores_sigmask (unw_cursor_t *c, unw_word_t *wp)
+{
+ /* We may want to do this analogously as for ia64... */
+ return 0;
+}
+
+#endif /* !UNW_TARGET_IA64 */
diff --git a/src/pal/src/libunwind/src/setjmp/siglongjmp.c b/src/pal/src/libunwind/src/setjmp/siglongjmp.c
new file mode 100644
index 0000000000..0e286f6f08
--- /dev/null
+++ b/src/pal/src/libunwind/src/setjmp/siglongjmp.c
@@ -0,0 +1,127 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#define UNW_LOCAL_ONLY
+
+#include <setjmp.h>
+
+#include "libunwind_i.h"
+#include "jmpbuf.h"
+#include "setjmp_i.h"
+
+#if !defined(_NSIG) && defined(_SIG_MAXSIG)
+# define _NSIG (_SIG_MAXSIG - 1)
+#endif
+
+#if defined(__GLIBC__)
+#if __GLIBC_PREREQ(2, 4)
+
+/* Starting with glibc-2.4, {sig,}setjmp in GLIBC obfuscates the
+ register values in jmp_buf by XORing them with a "random"
+ canary value.
+
+ This makes it impossible to implement longjmp, as we
+ can never match wp[JB_SP], unless we decode the canary first.
+
+ Doing so is possible, but doesn't appear to be worth the trouble,
+ so we simply defer to glibc siglongjmp here. */
+
+#define siglongjmp __nonworking_siglongjmp
+static void siglongjmp (sigjmp_buf env, int val) UNUSED;
+#endif
+#endif /* __GLIBC_PREREQ */
+
+void
+siglongjmp (sigjmp_buf env, int val)
+{
+ unw_word_t *wp = (unw_word_t *) env;
+ extern int _UI_siglongjmp_cont;
+ extern int _UI_longjmp_cont;
+ unw_context_t uc;
+ unw_cursor_t c;
+ unw_word_t sp;
+ int *cont;
+
+ if (unw_getcontext (&uc) < 0 || unw_init_local (&c, &uc) < 0)
+ abort ();
+
+ do
+ {
+ if (unw_get_reg (&c, UNW_REG_SP, &sp) < 0)
+ abort ();
+#ifdef __FreeBSD__
+ if (sp != wp[JB_SP] + sizeof(unw_word_t))
+#else
+ if (sp != wp[JB_SP])
+#endif
+ continue;
+
+ if (!bsp_match (&c, wp))
+ continue;
+
+ /* found the right frame: */
+
+ /* default to resuming without restoring signal-mask */
+ cont = &_UI_longjmp_cont;
+
+ /* Order of evaluation is important here: if unw_resume()
+ restores signal mask, we must set it up appropriately, even
+ if wp[JB_MASK_SAVED] is FALSE. */
+ if (!resume_restores_sigmask (&c, wp) && wp[JB_MASK_SAVED])
+ {
+ /* sigmask was saved */
+#if defined(__linux__)
+ if (UNW_NUM_EH_REGS < 4 || _NSIG > 16 * sizeof (unw_word_t))
+ /* signal mask doesn't fit into EH arguments and we can't
+ put it on the stack without overwriting something
+ else... */
+ abort ();
+ else
+ if (unw_set_reg (&c, UNW_REG_EH + 2, wp[JB_MASK]) < 0
+ || (_NSIG > 8 * sizeof (unw_word_t)
+ && unw_set_reg (&c, UNW_REG_EH + 3, wp[JB_MASK + 1]) < 0))
+ abort ();
+#elif defined(__FreeBSD__)
+ if (unw_set_reg (&c, UNW_REG_EH + 2, &wp[JB_MASK]) < 0)
+ abort();
+#else
+#error Port me
+#endif
+ cont = &_UI_siglongjmp_cont;
+ }
+
+ if (unw_set_reg (&c, UNW_REG_EH + 0, wp[JB_RP]) < 0
+ || unw_set_reg (&c, UNW_REG_EH + 1, val) < 0
+ || unw_set_reg (&c, UNW_REG_IP, (unw_word_t) (uintptr_t) cont))
+ abort ();
+
+ unw_resume (&c);
+
+ abort ();
+ }
+ while (unw_step (&c) > 0);
+
+ abort ();
+}
diff --git a/src/pal/src/libunwind/src/setjmp/sigsetjmp.c b/src/pal/src/libunwind/src/setjmp/sigsetjmp.c
new file mode 100644
index 0000000000..f84935d638
--- /dev/null
+++ b/src/pal/src/libunwind/src/setjmp/sigsetjmp.c
@@ -0,0 +1,50 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <libunwind.h>
+#include <setjmp.h>
+#include <stdlib.h>
+
+#include "jmpbuf.h"
+
+int
+sigsetjmp (sigjmp_buf env, int savemask)
+{
+ unw_word_t *wp = (unw_word_t *) env;
+
+ /* This should work on most platforms, but may not be
+ performance-optimal; check the code! */
+
+ wp[JB_SP] = (unw_word_t) __builtin_frame_address (0);
+ wp[JB_RP] = (unw_word_t) __builtin_return_address (0);
+ wp[JB_MASK_SAVED] = savemask;
+
+ /* Note: we assume here that "wp" has same or better alignment as
+ sigset_t. */
+ if (savemask
+ && sigprocmask (SIG_BLOCK, NULL, (sigset_t *) (wp + JB_MASK)) < 0)
+ abort ();
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/sh/Gapply_reg_state.c b/src/pal/src/libunwind/src/sh/Gapply_reg_state.c
new file mode 100644
index 0000000000..82f056da67
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Gapply_reg_state.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+ void *reg_states_data)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
diff --git a/src/pal/src/libunwind/src/sh/Gcreate_addr_space.c b/src/pal/src/libunwind/src/sh/Gcreate_addr_space.c
new file mode 100644
index 0000000000..6ca3a384da
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Gcreate_addr_space.c
@@ -0,0 +1,59 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "unwind_i.h"
+
+unw_addr_space_t
+unw_create_addr_space (unw_accessors_t *a, int byte_order)
+{
+#ifdef UNW_LOCAL_ONLY
+ return NULL;
+#else
+ unw_addr_space_t as;
+
+ /* SH supports little-endian and big-endian. */
+ if (byte_order != 0 && byte_order != __LITTLE_ENDIAN
+ && byte_order != __BIG_ENDIAN)
+ return NULL;
+
+ as = malloc (sizeof (*as));
+ if (!as)
+ return NULL;
+
+ memset (as, 0, sizeof (*as));
+
+ as->acc = *a;
+
+ /* Default to little-endian for SH. */
+ if (byte_order == 0 || byte_order == __LITTLE_ENDIAN)
+ as->big_endian = 0;
+ else
+ as->big_endian = 1;
+
+ return as;
+#endif
+}
diff --git a/src/pal/src/libunwind/src/sh/Gget_proc_info.c b/src/pal/src/libunwind/src/sh/Gget_proc_info.c
new file mode 100644
index 0000000000..c363d2405d
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Gget_proc_info.c
@@ -0,0 +1,39 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ ret = dwarf_make_proc_info (&c->dwarf);
+ if (ret < 0)
+ return ret;
+
+ *pi = c->dwarf.pi;
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/sh/Gget_save_loc.c b/src/pal/src/libunwind/src/sh/Gget_save_loc.c
new file mode 100644
index 0000000000..24d9f63bc3
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Gget_save_loc.c
@@ -0,0 +1,83 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ dwarf_loc_t loc;
+
+ switch (reg)
+ {
+ case UNW_SH_R0:
+ case UNW_SH_R1:
+ case UNW_SH_R2:
+ case UNW_SH_R3:
+ case UNW_SH_R4:
+ case UNW_SH_R5:
+ case UNW_SH_R6:
+ case UNW_SH_R7:
+ case UNW_SH_R8:
+ case UNW_SH_R9:
+ case UNW_SH_R10:
+ case UNW_SH_R11:
+ case UNW_SH_R12:
+ case UNW_SH_R13:
+ case UNW_SH_R14:
+ case UNW_SH_R15:
+ case UNW_SH_PC:
+ case UNW_SH_PR:
+ loc = c->dwarf.loc[reg];
+ break;
+
+ default:
+ loc = DWARF_NULL_LOC; /* default to "not saved" */
+ break;
+ }
+
+ memset (sloc, 0, sizeof (*sloc));
+
+ if (DWARF_IS_NULL_LOC (loc))
+ {
+ sloc->type = UNW_SLT_NONE;
+ return 0;
+ }
+
+#if !defined(UNW_LOCAL_ONLY)
+ if (DWARF_IS_REG_LOC (loc))
+ {
+ sloc->type = UNW_SLT_REG;
+ sloc->u.regnum = DWARF_GET_LOC (loc);
+ }
+ else
+#endif
+ {
+ sloc->type = UNW_SLT_MEMORY;
+ sloc->u.addr = DWARF_GET_LOC (loc);
+ }
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/sh/Gglobal.c b/src/pal/src/libunwind/src/sh/Gglobal.c
new file mode 100644
index 0000000000..ed27333976
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Gglobal.c
@@ -0,0 +1,56 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "dwarf_i.h"
+
+HIDDEN define_lock (sh_lock);
+HIDDEN int tdep_init_done;
+
+HIDDEN void
+tdep_init (void)
+{
+ intrmask_t saved_mask;
+
+ sigfillset (&unwi_full_mask);
+
+ lock_acquire (&sh_lock, saved_mask);
+ {
+ if (tdep_init_done)
+ /* another thread else beat us to it... */
+ goto out;
+
+ mi_init ();
+
+ dwarf_init ();
+
+#ifndef UNW_REMOTE_ONLY
+ sh_local_addr_space_init ();
+#endif
+ tdep_init_done = 1; /* signal that we're initialized... */
+ }
+ out:
+ lock_release (&sh_lock, saved_mask);
+}
diff --git a/src/pal/src/libunwind/src/sh/Ginit.c b/src/pal/src/libunwind/src/sh/Ginit.c
new file mode 100644
index 0000000000..52988a721e
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Ginit.c
@@ -0,0 +1,186 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "unwind_i.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+/* unw_local_addr_space is a NULL pointer in this case. */
+unw_addr_space_t unw_local_addr_space;
+
+#else /* !UNW_REMOTE_ONLY */
+
+static struct unw_addr_space local_addr_space;
+
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
+
+static inline void *
+uc_addr (ucontext_t *uc, int reg)
+{
+ if (reg >= UNW_SH_R0 && reg <= UNW_SH_PR)
+ return &uc->uc_mcontext.gregs[reg];
+ else
+ return NULL;
+}
+
+# ifdef UNW_LOCAL_ONLY
+
+HIDDEN void *
+tdep_uc_addr (ucontext_t *uc, int reg)
+{
+ return uc_addr (uc, reg);
+}
+
+# endif /* UNW_LOCAL_ONLY */
+
+HIDDEN unw_dyn_info_list_t _U_dyn_info_list;
+
+/* XXX fix me: there is currently no way to locate the dyn-info list
+ by a remote unwinder. On ia64, this is done via a special
+ unwind-table entry. Perhaps something similar can be done with
+ DWARF2 unwind info. */
+
+static void
+put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
+{
+ /* it's a no-op */
+}
+
+static int
+get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
+ void *arg)
+{
+ *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list;
+ return 0;
+}
+
+static int
+access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
+ void *arg)
+{
+ if (write)
+ {
+ Debug (16, "mem[%x] <- %x\n", addr, *val);
+ *(unw_word_t *) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_word_t *) addr;
+ Debug (16, "mem[%x] -> %x\n", addr, *val);
+ }
+ return 0;
+}
+
+static int
+access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
+ void *arg)
+{
+ unw_word_t *addr;
+ ucontext_t *uc = arg;
+
+ if (unw_is_fpreg (reg))
+ goto badreg;
+
+ if (!(addr = uc_addr (uc, reg)))
+ goto badreg;
+
+ if (write)
+ {
+ *(unw_word_t *) addr = *val;
+ Debug (12, "%s <- %x\n", unw_regname (reg), *val);
+ }
+ else
+ {
+ *val = *(unw_word_t *) addr;
+ Debug (12, "%s -> %x\n", unw_regname (reg), *val);
+ }
+ return 0;
+
+ badreg:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+}
+
+static int
+access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
+ int write, void *arg)
+{
+ ucontext_t *uc = arg;
+ unw_fpreg_t *addr;
+
+ if (!unw_is_fpreg (reg))
+ goto badreg;
+
+ if (!(addr = uc_addr (uc, reg)))
+ goto badreg;
+
+ if (write)
+ {
+ Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg),
+ ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
+ *(unw_fpreg_t *) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_fpreg_t *) addr;
+ Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg),
+ ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
+ }
+ return 0;
+
+ badreg:
+ Debug (1, "bad register number %u\n", reg);
+ /* attempt to access a non-preserved register */
+ return -UNW_EBADREG;
+}
+
+static int
+get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
+ char *buf, size_t buf_len, unw_word_t *offp,
+ void *arg)
+{
+ return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
+}
+
+HIDDEN void
+sh_local_addr_space_init (void)
+{
+ memset (&local_addr_space, 0, sizeof (local_addr_space));
+ local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
+ local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
+ local_addr_space.acc.put_unwind_info = put_unwind_info;
+ local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
+ local_addr_space.acc.access_mem = access_mem;
+ local_addr_space.acc.access_reg = access_reg;
+ local_addr_space.acc.access_fpreg = access_fpreg;
+ local_addr_space.acc.resume = sh_local_resume;
+ local_addr_space.acc.get_proc_name = get_static_proc_name;
+ unw_flush_cache (&local_addr_space, 0, 0);
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/sh/Ginit_local.c b/src/pal/src/libunwind/src/sh/Ginit_local.c
new file mode 100644
index 0000000000..99ddb36fb3
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Ginit_local.c
@@ -0,0 +1,78 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright 2011 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "init.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+int
+unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
+{
+ return -UNW_EINVAL;
+}
+
+#else /* !UNW_REMOTE_ONLY */
+
+static int
+unw_init_local (unw_cursor_t *cursor, unw_context_t *uc, unsigned use_prev_instr)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->dwarf.as = unw_local_addr_space;
+ c->dwarf.as_arg = uc;
+
+ return common_init (c, use_prev_instr);
+}
+
+int
+unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
+{
+ return unw_init_local_common(cursor, uc, 1);
+}
+
+int
+unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
+{
+ if (!flag)
+ {
+ return unw_init_local_common(cursor, uc, 1);
+ }
+ else if (flag == UNW_INIT_SIGNAL_FRAME)
+ {
+ return unw_init_local_common(cursor, uc, 0);
+ }
+ else
+ {
+ return -UNW_EINVAL;
+ }
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/sh/Ginit_remote.c b/src/pal/src/libunwind/src/sh/Ginit_remote.c
new file mode 100644
index 0000000000..9b8ba5b89d
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Ginit_remote.c
@@ -0,0 +1,45 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "init.h"
+#include "unwind_i.h"
+
+int
+unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
+{
+#ifdef UNW_LOCAL_ONLY
+ return -UNW_EINVAL;
+#else /* !UNW_LOCAL_ONLY */
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->dwarf.as = as;
+ c->dwarf.as_arg = as_arg;
+ return common_init (c, 0);
+#endif /* !UNW_LOCAL_ONLY */
+}
diff --git a/src/pal/src/libunwind/src/sh/Gis_signal_frame.c b/src/pal/src/libunwind/src/sh/Gis_signal_frame.c
new file mode 100644
index 0000000000..4481fe1a49
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Gis_signal_frame.c
@@ -0,0 +1,119 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+/* Disassembly of the Linux VDSO sigreturn functions:
+
+00000000 <__kernel_sigreturn>:
+ 0: 05 93 mov.w e <__kernel_sigreturn+0xe>,r3 ! 77
+ 2: 10 c3 trapa #16
+ 4: 0b 20 or r0,r0
+ 6: 0b 20 or r0,r0
+ 8: 0b 20 or r0,r0
+ a: 0b 20 or r0,r0
+ c: 0b 20 or r0,r0
+ e: 77 00 .word 0x0077
+ 10: 09 00 nop
+ 12: 09 00 nop
+ 14: 09 00 nop
+ 16: 09 00 nop
+ 18: 09 00 nop
+ 1a: 09 00 nop
+ 1c: 09 00 nop
+ 1e: 09 00 nop
+
+00000020 <__kernel_rt_sigreturn>:
+ 20: 05 93 mov.w 2e <__kernel_rt_sigreturn+0xe>,r3 ! ad
+ 22: 10 c3 trapa #16
+ 24: 0b 20 or r0,r0
+ 26: 0b 20 or r0,r0
+ 28: 0b 20 or r0,r0
+ 2a: 0b 20 or r0,r0
+ 2c: 0b 20 or r0,r0
+ 2e: ad 00 mov.w @(r0,r10),r0
+ 30: 09 00 nop
+ 32: 09 00 nop
+ 34: 09 00 nop
+ 36: 09 00 nop
+ 38: 09 00 nop
+ 3a: 09 00 nop
+ 3c: 09 00 nop
+ 3e: 09 00 nop
+*/
+
+int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+#ifdef __linux__
+ struct cursor *c = (struct cursor *) cursor;
+ unw_word_t w0, ip;
+ unw_addr_space_t as;
+ unw_accessors_t *a;
+ void *arg;
+ int ret;
+
+ as = c->dwarf.as;
+ a = unw_get_accessors_int (as);
+ arg = c->dwarf.as_arg;
+
+ ip = c->dwarf.ip;
+
+ ret = (*a->access_mem) (as, ip, &w0, 0, arg);
+ if (ret < 0)
+ return ret;
+
+ if (w0 != 0xc3109305)
+ return 0;
+
+ ret = (*a->access_mem) (as, ip+4, &w0, 0, arg);
+ if (ret < 0)
+ return ret;
+
+ if (w0 != 0x200b200b)
+ return 0;
+
+ ret = (*a->access_mem) (as, ip+8, &w0, 0, arg);
+ if (ret < 0)
+ return ret;
+
+ if (w0 != 0x200b200b)
+ return 0;
+
+ ret = (*a->access_mem) (as, ip+12, &w0, 0, arg);
+ if (ret < 0)
+ return ret;
+
+ if (w0 == 0x0077200b)
+ return 1; /* non-RT */
+ else if (w0 == 0x00ad200b)
+ return 2; /* RT */
+
+ /* does not look like a signal frame */
+ return 0;
+
+#else
+ return -UNW_ENOINFO;
+#endif
+}
diff --git a/src/pal/src/libunwind/src/sh/Greg_states_iterate.c b/src/pal/src/libunwind/src/sh/Greg_states_iterate.c
new file mode 100644
index 0000000000..a17dc1b561
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Greg_states_iterate.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+ unw_reg_states_callback cb, void *token)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
diff --git a/src/pal/src/libunwind/src/sh/Gregs.c b/src/pal/src/libunwind/src/sh/Gregs.c
new file mode 100644
index 0000000000..7d8e8e93da
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Gregs.c
@@ -0,0 +1,81 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+HIDDEN int
+tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
+ int write)
+{
+ dwarf_loc_t loc = DWARF_NULL_LOC;
+
+ switch (reg)
+ {
+ case UNW_SH_PC:
+ if (write)
+ c->dwarf.ip = *valp; /* update the IP cache */
+ case UNW_SH_R0:
+ case UNW_SH_R1:
+ case UNW_SH_R2:
+ case UNW_SH_R3:
+ case UNW_SH_R4:
+ case UNW_SH_R5:
+ case UNW_SH_R6:
+ case UNW_SH_R7:
+ case UNW_SH_R8:
+ case UNW_SH_R9:
+ case UNW_SH_R10:
+ case UNW_SH_R11:
+ case UNW_SH_R12:
+ case UNW_SH_R13:
+ case UNW_SH_R14:
+ case UNW_SH_PR:
+ loc = c->dwarf.loc[reg];
+ break;
+
+ case UNW_SH_R15:
+ if (write)
+ return -UNW_EREADONLYREG;
+ *valp = c->dwarf.cfa;
+ return 0;
+
+ default:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+ }
+
+ if (write)
+ return dwarf_put (&c->dwarf, loc, *valp);
+ else
+ return dwarf_get (&c->dwarf, loc, valp);
+}
+
+HIDDEN int
+tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
+ int write)
+{
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+}
diff --git a/src/pal/src/libunwind/src/sh/Gresume.c b/src/pal/src/libunwind/src/sh/Gresume.c
new file mode 100644
index 0000000000..a263c92718
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Gresume.c
@@ -0,0 +1,165 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright 2011 Linaro Limited
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "offsets.h"
+
+#ifndef UNW_REMOTE_ONLY
+
+HIDDEN inline int
+sh_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
+{
+#ifdef __linux__
+ struct cursor *c = (struct cursor *) cursor;
+ unw_tdep_context_t *uc = c->dwarf.as_arg;
+
+ if (c->sigcontext_format == SH_SCF_NONE)
+ {
+ /* Since there are no signals involved here we restore the non scratch
+ registers only. */
+ unsigned long regs[8];
+ regs[0] = uc->uc_mcontext.gregs[8];
+ regs[1] = uc->uc_mcontext.gregs[9];
+ regs[2] = uc->uc_mcontext.gregs[10];
+ regs[3] = uc->uc_mcontext.gregs[11];
+ regs[4] = uc->uc_mcontext.gregs[12];
+ regs[5] = uc->uc_mcontext.gregs[13];
+ regs[6] = uc->uc_mcontext.gregs[14];
+ regs[7] = uc->uc_mcontext.gregs[15];
+ unsigned long pc = uc->uc_mcontext.pr;
+
+ struct regs_overlay {
+ char x[sizeof(regs)];
+ };
+
+ asm volatile (
+ "mov.l @%0+, r8\n"
+ "mov.l @%0+, r9\n"
+ "mov.l @%0+, r10\n"
+ "mov.l @%0+, r11\n"
+ "mov.l @%0+, r12\n"
+ "mov.l @%0+, r13\n"
+ "mov.l @%0+, r14\n"
+ "mov.l @%0, r15\n"
+ "lds %1, pr\n"
+ "rts\n"
+ "nop\n"
+ :
+ : "r" (regs),
+ "r" (pc),
+ "m" (*(struct regs_overlay *)regs)
+ );
+ }
+ else
+ {
+ /* In case a signal frame is involved, we're using its trampoline which
+ calls sigreturn. */
+ struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
+ sc->sc_regs[0] = uc->uc_mcontext.gregs[0];
+ sc->sc_regs[1] = uc->uc_mcontext.gregs[1];
+ sc->sc_regs[2] = uc->uc_mcontext.gregs[2];
+ sc->sc_regs[3] = uc->uc_mcontext.gregs[3];
+ sc->sc_regs[4] = uc->uc_mcontext.gregs[4];
+ sc->sc_regs[5] = uc->uc_mcontext.gregs[5];
+ sc->sc_regs[6] = uc->uc_mcontext.gregs[6];
+ sc->sc_regs[7] = uc->uc_mcontext.gregs[7];
+ sc->sc_regs[8] = uc->uc_mcontext.gregs[8];
+ sc->sc_regs[9] = uc->uc_mcontext.gregs[9];
+ sc->sc_regs[10] = uc->uc_mcontext.gregs[10];
+ sc->sc_regs[11] = uc->uc_mcontext.gregs[11];
+ sc->sc_regs[12] = uc->uc_mcontext.gregs[12];
+ sc->sc_regs[13] = uc->uc_mcontext.gregs[13];
+ sc->sc_regs[14] = uc->uc_mcontext.gregs[14];
+ sc->sc_regs[15] = uc->uc_mcontext.gregs[15];
+ sc->sc_pc = uc->uc_mcontext.pc;
+ sc->sc_pr = uc->uc_mcontext.pr;
+
+ /* Set the SP and the PC in order to continue execution at the modified
+ trampoline which restores the signal mask and the registers. */
+ asm __volatile__ (
+ "mov %0, r15\n"
+ "lds %1, pr\n"
+ "rts\n"
+ "nop\n"
+ :
+ : "r" (c->sigcontext_sp),
+ "r" (c->sigcontext_pc)
+ );
+ }
+ unreachable();
+#endif
+ return -UNW_EINVAL;
+}
+
+#endif /* !UNW_REMOTE_ONLY */
+
+static inline void
+establish_machine_state (struct cursor *c)
+{
+ unw_addr_space_t as = c->dwarf.as;
+ void *arg = c->dwarf.as_arg;
+ unw_fpreg_t fpval;
+ unw_word_t val;
+ int reg;
+
+ Debug (8, "copying out cursor state\n");
+
+ for (reg = 0; reg <= UNW_REG_LAST; ++reg)
+ {
+ Debug (16, "copying %s %d\n", unw_regname (reg), reg);
+ if (unw_is_fpreg (reg))
+ {
+ if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0)
+ as->acc.access_fpreg (as, reg, &fpval, 1, arg);
+ }
+ else
+ {
+ if (tdep_access_reg (c, reg, &val, 0) >= 0)
+ as->acc.access_reg (as, reg, &val, 1, arg);
+ }
+ }
+}
+
+int
+unw_resume (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ if (!c->dwarf.ip)
+ {
+ /* This can happen easily when the frame-chain gets truncated
+ due to bad or missing unwind-info. */
+ Debug (1, "refusing to resume execution at address 0\n");
+ return -UNW_EINVAL;
+ }
+
+ establish_machine_state (c);
+
+ return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c,
+ c->dwarf.as_arg);
+}
diff --git a/src/pal/src/libunwind/src/sh/Gstep.c b/src/pal/src/libunwind/src/sh/Gstep.c
new file mode 100644
index 0000000000..60d7ec2ba9
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Gstep.c
@@ -0,0 +1,117 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright 2011 Linaro Limited
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "offsets.h"
+
+static int
+sh_handle_signal_frame (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+ unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa;
+ struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0);
+
+ if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0)
+ return -UNW_EUNSPEC;
+
+ ret = unw_is_signal_frame (cursor);
+ Debug(1, "unw_is_signal_frame()=%d\n", ret);
+
+ /* Save the SP and PC to be able to return execution at this point
+ later in time (unw_resume). */
+ c->sigcontext_sp = c->dwarf.cfa;
+ c->sigcontext_pc = c->dwarf.ip;
+
+ if (ret == 1)
+ {
+ /* Handle non-RT signal frame. */
+ c->sigcontext_format = SH_SCF_LINUX_SIGFRAME;
+ sc_addr = sp_addr;
+ }
+ else if (ret == 2)
+ {
+ /* Handle RT signal frame. */
+ c->sigcontext_format = SH_SCF_LINUX_RT_SIGFRAME;
+ sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF;
+ }
+ else
+ return -UNW_EUNSPEC;
+
+ c->sigcontext_addr = sc_addr;
+
+ /* Update the dwarf cursor.
+ Set the location of the registers to the corresponding addresses of the
+ uc_mcontext / sigcontext structure contents. */
+ c->dwarf.loc[UNW_SH_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0);
+ c->dwarf.loc[UNW_SH_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0);
+ c->dwarf.loc[UNW_SH_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0);
+ c->dwarf.loc[UNW_SH_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0);
+ c->dwarf.loc[UNW_SH_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0);
+ c->dwarf.loc[UNW_SH_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0);
+ c->dwarf.loc[UNW_SH_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0);
+ c->dwarf.loc[UNW_SH_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0);
+ c->dwarf.loc[UNW_SH_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0);
+ c->dwarf.loc[UNW_SH_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0);
+ c->dwarf.loc[UNW_SH_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0);
+ c->dwarf.loc[UNW_SH_R11] = DWARF_LOC (sc_addr + LINUX_SC_R11_OFF, 0);
+ c->dwarf.loc[UNW_SH_R12] = DWARF_LOC (sc_addr + LINUX_SC_R12_OFF, 0);
+ c->dwarf.loc[UNW_SH_R13] = DWARF_LOC (sc_addr + LINUX_SC_R13_OFF, 0);
+ c->dwarf.loc[UNW_SH_R14] = DWARF_LOC (sc_addr + LINUX_SC_R14_OFF, 0);
+ c->dwarf.loc[UNW_SH_R15] = DWARF_LOC (sc_addr + LINUX_SC_R15_OFF, 0);
+ c->dwarf.loc[UNW_SH_PR] = DWARF_LOC (sc_addr + LINUX_SC_PR_OFF, 0);
+ c->dwarf.loc[UNW_SH_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0);
+
+ /* Set SP/CFA and PC/IP. */
+ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_SH_R15], &c->dwarf.cfa);
+ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_SH_PC], &c->dwarf.ip);
+
+ c->dwarf.pi_valid = 0;
+
+ return 1;
+}
+
+int
+unw_step (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ if (unw_is_signal_frame (cursor) > 0)
+ return sh_handle_signal_frame (cursor);
+
+ ret = dwarf_step (&c->dwarf);
+
+ if (unlikely (ret == -UNW_ESTOPUNWIND))
+ return ret;
+
+ if (unlikely (ret < 0))
+ return 0;
+
+ return (c->dwarf.ip == 0) ? 0 : 1;
+}
diff --git a/src/pal/src/libunwind/src/sh/Lapply_reg_state.c b/src/pal/src/libunwind/src/sh/Lapply_reg_state.c
new file mode 100644
index 0000000000..7ebada480e
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Lapply_reg_state.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/pal/src/libunwind/src/sh/Lcreate_addr_space.c b/src/pal/src/libunwind/src/sh/Lcreate_addr_space.c
new file mode 100644
index 0000000000..0f2dc6be90
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Lcreate_addr_space.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gcreate_addr_space.c"
+#endif
diff --git a/src/pal/src/libunwind/src/sh/Lget_proc_info.c b/src/pal/src/libunwind/src/sh/Lget_proc_info.c
new file mode 100644
index 0000000000..69028b019f
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Lget_proc_info.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_proc_info.c"
+#endif
diff --git a/src/pal/src/libunwind/src/sh/Lget_save_loc.c b/src/pal/src/libunwind/src/sh/Lget_save_loc.c
new file mode 100644
index 0000000000..9ea048a907
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Lget_save_loc.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_save_loc.c"
+#endif
diff --git a/src/pal/src/libunwind/src/sh/Lglobal.c b/src/pal/src/libunwind/src/sh/Lglobal.c
new file mode 100644
index 0000000000..6d7b489e14
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Lglobal.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gglobal.c"
+#endif
diff --git a/src/pal/src/libunwind/src/sh/Linit.c b/src/pal/src/libunwind/src/sh/Linit.c
new file mode 100644
index 0000000000..e9abfdd46a
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Linit.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit.c"
+#endif
diff --git a/src/pal/src/libunwind/src/sh/Linit_local.c b/src/pal/src/libunwind/src/sh/Linit_local.c
new file mode 100644
index 0000000000..68a1687e85
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Linit_local.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_local.c"
+#endif
diff --git a/src/pal/src/libunwind/src/sh/Linit_remote.c b/src/pal/src/libunwind/src/sh/Linit_remote.c
new file mode 100644
index 0000000000..58cb04ab7c
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Linit_remote.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_remote.c"
+#endif
diff --git a/src/pal/src/libunwind/src/sh/Lis_signal_frame.c b/src/pal/src/libunwind/src/sh/Lis_signal_frame.c
new file mode 100644
index 0000000000..b9a7c4f51a
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Lis_signal_frame.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gis_signal_frame.c"
+#endif
diff --git a/src/pal/src/libunwind/src/sh/Lreg_states_iterate.c b/src/pal/src/libunwind/src/sh/Lreg_states_iterate.c
new file mode 100644
index 0000000000..f1eb1e79dc
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Lreg_states_iterate.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
diff --git a/src/pal/src/libunwind/src/sh/Lregs.c b/src/pal/src/libunwind/src/sh/Lregs.c
new file mode 100644
index 0000000000..2c9c75cd7d
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Lregs.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gregs.c"
+#endif
diff --git a/src/pal/src/libunwind/src/sh/Lresume.c b/src/pal/src/libunwind/src/sh/Lresume.c
new file mode 100644
index 0000000000..41a8cf003d
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Lresume.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gresume.c"
+#endif
diff --git a/src/pal/src/libunwind/src/sh/Lstep.c b/src/pal/src/libunwind/src/sh/Lstep.c
new file mode 100644
index 0000000000..c1ac3c7547
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/Lstep.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gstep.c"
+#endif
diff --git a/src/pal/src/libunwind/src/sh/gen-offsets.c b/src/pal/src/libunwind/src/sh/gen-offsets.c
new file mode 100644
index 0000000000..16695a6489
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/gen-offsets.c
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <stddef.h>
+#include <ucontext.h>
+#include <asm/sigcontext.h>
+
+#define UC(N,X) \
+ printf ("#define LINUX_UC_" N "_OFF\t0x%X\n", offsetof (ucontext_t, X))
+
+#define SC(N,X) \
+ printf ("#define LINUX_SC_" N "_OFF\t0x%X\n", offsetof (struct sigcontext, X))
+
+int
+main (void)
+{
+ printf (
+"/* Linux-specific definitions: */\n\n"
+
+"/* Define various structure offsets to simplify cross-compilation. */\n\n"
+
+"/* Offsets for SH Linux \"ucontext_t\": */\n\n");
+
+ UC ("FLAGS", uc_flags);
+ UC ("LINK", uc_link);
+ UC ("STACK", uc_stack);
+ UC ("MCONTEXT", uc_mcontext);
+ UC ("SIGMASK", uc_sigmask);
+
+ printf ("\n/* Offsets for SH Linux \"struct sigcontext\": */\n\n");
+
+ SC ("R0", sc_regs[0]);
+ SC ("R1", sc_regs[1]);
+ SC ("R2", sc_regs[2]);
+ SC ("R3", sc_regs[3]);
+ SC ("R4", sc_regs[4]);
+ SC ("R5", sc_regs[5]);
+ SC ("R6", sc_regs[6]);
+ SC ("R7", sc_regs[7]);
+ SC ("R8", sc_regs[8]);
+ SC ("R9", sc_regs[9]);
+ SC ("R10", sc_regs[10]);
+ SC ("R11", sc_regs[11]);
+ SC ("R12", sc_regs[12]);
+ SC ("R13", sc_regs[13]);
+ SC ("R14", sc_regs[14]);
+ SC ("R15", sc_regs[15]);
+
+ SC ("PC", sc_pc);
+ SC ("PR", sc_pr);
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/sh/init.h b/src/pal/src/libunwind/src/sh/init.h
new file mode 100644
index 0000000000..36713fe89b
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/init.h
@@ -0,0 +1,73 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+static inline int
+common_init (struct cursor *c, unsigned use_prev_instr)
+{
+ int ret;
+
+ c->dwarf.loc[UNW_SH_R0] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R0);
+ c->dwarf.loc[UNW_SH_R1] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R1);
+ c->dwarf.loc[UNW_SH_R2] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R2);
+ c->dwarf.loc[UNW_SH_R3] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R3);
+ c->dwarf.loc[UNW_SH_R4] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R4);
+ c->dwarf.loc[UNW_SH_R5] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R5);
+ c->dwarf.loc[UNW_SH_R6] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R6);
+ c->dwarf.loc[UNW_SH_R7] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R7);
+ c->dwarf.loc[UNW_SH_R8] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R8);
+ c->dwarf.loc[UNW_SH_R9] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R9);
+ c->dwarf.loc[UNW_SH_R10] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R10);
+ c->dwarf.loc[UNW_SH_R11] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R11);
+ c->dwarf.loc[UNW_SH_R12] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R12);
+ c->dwarf.loc[UNW_SH_R13] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R13);
+ c->dwarf.loc[UNW_SH_R14] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R14);
+ c->dwarf.loc[UNW_SH_R15] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R15);
+ c->dwarf.loc[UNW_SH_PC] = DWARF_REG_LOC (&c->dwarf, UNW_SH_PC);
+ c->dwarf.loc[UNW_SH_PR] = DWARF_REG_LOC (&c->dwarf, UNW_SH_PR);
+
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_SH_PC], &c->dwarf.ip);
+ if (ret < 0)
+ return ret;
+
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_TDEP_SP], &c->dwarf.cfa);
+ if (ret < 0)
+ return ret;
+
+ c->sigcontext_format = SH_SCF_NONE;
+ c->sigcontext_addr = 0;
+ c->sigcontext_sp = 0;
+ c->sigcontext_pc = 0;
+
+ c->dwarf.args_size = 0;
+ c->dwarf.stash_frames = 0;
+ c->dwarf.use_prev_instr = use_prev_instr;
+ c->dwarf.pi_valid = 0;
+ c->dwarf.pi_is_dynamic = 0;
+ c->dwarf.hint = 0;
+ c->dwarf.prev_rs = 0;
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/sh/is_fpreg.c b/src/pal/src/libunwind/src/sh/is_fpreg.c
new file mode 100644
index 0000000000..de09340194
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/is_fpreg.c
@@ -0,0 +1,32 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+int
+unw_is_fpreg (int regnum)
+{
+ /* FIXME: Support FP. */
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/sh/offsets.h b/src/pal/src/libunwind/src/sh/offsets.h
new file mode 100644
index 0000000000..b02d8aee1e
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/offsets.h
@@ -0,0 +1,32 @@
+/* Linux-specific definitions: */
+
+/* Define various structure offsets to simplify cross-compilation. */
+
+/* Offsets for SH Linux "ucontext_t": */
+
+#define LINUX_UC_FLAGS_OFF 0x0
+#define LINUX_UC_LINK_OFF 0x4
+#define LINUX_UC_STACK_OFF 0x8
+#define LINUX_UC_MCONTEXT_OFF 0x14
+#define LINUX_UC_SIGMASK_OFF 0xFC
+
+/* Offsets for SH Linux "struct sigcontext": */
+
+#define LINUX_SC_R0_OFF 0x4
+#define LINUX_SC_R1_OFF 0x8
+#define LINUX_SC_R2_OFF 0xC
+#define LINUX_SC_R3_OFF 0x10
+#define LINUX_SC_R4_OFF 0x14
+#define LINUX_SC_R5_OFF 0x18
+#define LINUX_SC_R6_OFF 0x1C
+#define LINUX_SC_R7_OFF 0x20
+#define LINUX_SC_R8_OFF 0x24
+#define LINUX_SC_R9_OFF 0x28
+#define LINUX_SC_R10_OFF 0x2C
+#define LINUX_SC_R11_OFF 0x30
+#define LINUX_SC_R12_OFF 0x34
+#define LINUX_SC_R13_OFF 0x38
+#define LINUX_SC_R14_OFF 0x3C
+#define LINUX_SC_R15_OFF 0x40
+#define LINUX_SC_PC_OFF 0x44
+#define LINUX_SC_PR_OFF 0x48
diff --git a/src/pal/src/libunwind/src/sh/regname.c b/src/pal/src/libunwind/src/sh/regname.c
new file mode 100644
index 0000000000..b52925b4da
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/regname.c
@@ -0,0 +1,56 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+static const char *const regname[] =
+ {
+ [UNW_SH_R0] = "r0",
+ [UNW_SH_R1] = "r1",
+ [UNW_SH_R2] = "r2",
+ [UNW_SH_R3] = "r3",
+ [UNW_SH_R4] = "r4",
+ [UNW_SH_R5] = "r5",
+ [UNW_SH_R6] = "r6",
+ [UNW_SH_R7] = "r7",
+ [UNW_SH_R8] = "r8",
+ [UNW_SH_R9] = "r9",
+ [UNW_SH_R10] = "r10",
+ [UNW_SH_R11] = "r11",
+ [UNW_SH_R12] = "r12",
+ [UNW_SH_R13] = "r13",
+ [UNW_SH_R14] = "r14",
+ [UNW_SH_R15] = "r15",
+ [UNW_SH_PC] = "pc",
+ [UNW_SH_PR] = "pr",
+ };
+
+const char *
+unw_regname (unw_regnum_t reg)
+{
+ if (reg < (unw_regnum_t) ARRAY_SIZE (regname) && regname[reg] != NULL)
+ return regname[reg];
+ else
+ return "???";
+}
diff --git a/src/pal/src/libunwind/src/sh/siglongjmp.S b/src/pal/src/libunwind/src/sh/siglongjmp.S
new file mode 100644
index 0000000000..9ca53d124b
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/siglongjmp.S
@@ -0,0 +1,8 @@
+ /* Dummy implementation for now. */
+
+ .globl _UI_siglongjmp_cont
+ .globl _UI_longjmp_cont
+
+_UI_siglongjmp_cont:
+_UI_longjmp_cont:
+ rts
diff --git a/src/pal/src/libunwind/src/sh/unwind_i.h b/src/pal/src/libunwind/src/sh/unwind_i.h
new file mode 100644
index 0000000000..3066d84631
--- /dev/null
+++ b/src/pal/src/libunwind/src/sh/unwind_i.h
@@ -0,0 +1,40 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef unwind_i_h
+#define unwind_i_h
+
+#include <libunwind-sh.h>
+
+#include "libunwind_i.h"
+
+#define sh_lock UNW_OBJ(lock)
+#define sh_local_resume UNW_OBJ(local_resume)
+#define sh_local_addr_space_init UNW_OBJ(local_addr_space_init)
+
+extern void sh_local_addr_space_init (void);
+extern int sh_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
+ void *arg);
+
+#endif /* unwind_i_h */
diff --git a/src/pal/src/libunwind/src/tilegx/Gapply_reg_state.c b/src/pal/src/libunwind/src/tilegx/Gapply_reg_state.c
new file mode 100644
index 0000000000..82f056da67
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Gapply_reg_state.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+ void *reg_states_data)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
diff --git a/src/pal/src/libunwind/src/tilegx/Gcreate_addr_space.c b/src/pal/src/libunwind/src/tilegx/Gcreate_addr_space.c
new file mode 100644
index 0000000000..39acdc2c3d
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Gcreate_addr_space.c
@@ -0,0 +1,65 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2014 Tilera Corp.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+
+#include "unwind_i.h"
+
+unw_addr_space_t
+unw_create_addr_space (unw_accessors_t *a, int byte_order)
+{
+#ifdef UNW_LOCAL_ONLY
+ return NULL;
+#else
+ unw_addr_space_t as = malloc (sizeof (*as));
+
+ if (!as)
+ return NULL;
+
+ memset (as, 0, sizeof (*as));
+
+ as->acc = *a;
+
+ /*
+ * Tilegx supports only big or little-endian, not weird stuff like
+ * PDP_ENDIAN.
+ */
+ if (byte_order != 0
+ && byte_order != __LITTLE_ENDIAN
+ && byte_order != __BIG_ENDIAN)
+ return NULL;
+
+ if (byte_order == 0)
+ /* use host default: */
+ as->big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
+ else
+ as->big_endian = (byte_order == __BIG_ENDIAN);
+
+ as->abi = UNW_TILEGX_ABI_N64;
+ as->addr_size = 8;
+
+ return as;
+#endif
+}
diff --git a/src/pal/src/libunwind/src/tilegx/Gget_proc_info.c b/src/pal/src/libunwind/src/tilegx/Gget_proc_info.c
new file mode 100644
index 0000000000..3a158da2df
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Gget_proc_info.c
@@ -0,0 +1,48 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2014 Tilera Corp.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ ret = dwarf_make_proc_info (&c->dwarf);
+
+ if (ret < 0)
+ {
+ /* On Tilegx, some routines i.e. _start() etc has no dwarf info.
+ Just simply mark the end of the frames. */
+ memset (pi, 0, sizeof (*pi));
+ pi->start_ip = c->dwarf.ip;
+ pi->end_ip = c->dwarf.ip + 1;
+ return 0;
+ }
+
+ *pi = c->dwarf.pi;
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/tilegx/Gget_save_loc.c b/src/pal/src/libunwind/src/tilegx/Gget_save_loc.c
new file mode 100644
index 0000000000..fcf0697892
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Gget_save_loc.c
@@ -0,0 +1,62 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2014 Tilera Corp.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ dwarf_loc_t loc;
+
+ loc = DWARF_NULL_LOC; /* default to "not saved" */
+
+ if (reg <= UNW_TILEGX_R55)
+ loc = c->dwarf.loc[reg - UNW_TILEGX_R0];
+ else
+ printf("\nInvalid register!");
+
+ memset (sloc, 0, sizeof (*sloc));
+
+ if (DWARF_IS_NULL_LOC (loc))
+ {
+ sloc->type = UNW_SLT_NONE;
+ return 0;
+ }
+
+#if !defined(UNW_LOCAL_ONLY)
+ if (DWARF_IS_REG_LOC (loc))
+ {
+ sloc->type = UNW_SLT_REG;
+ sloc->u.regnum = DWARF_GET_LOC (loc);
+ }
+ else
+#endif
+ {
+ sloc->type = UNW_SLT_MEMORY;
+ sloc->u.addr = DWARF_GET_LOC (loc);
+ }
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/tilegx/Gglobal.c b/src/pal/src/libunwind/src/tilegx/Gglobal.c
new file mode 100644
index 0000000000..e18f50a50f
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Gglobal.c
@@ -0,0 +1,64 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2014 Tilera Corp.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "dwarf_i.h"
+
+__attribute__((weak))
+pthread_mutex_t tilegx_lock = PTHREAD_MUTEX_INITIALIZER;
+HIDDEN int tdep_init_done;
+
+HIDDEN const uint8_t dwarf_to_unw_regnum_map[] =
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55
+ };
+
+HIDDEN void
+tdep_init (void)
+{
+ intrmask_t saved_mask;
+
+ sigfillset (&unwi_full_mask);
+
+ lock_acquire (&tilegx_lock, saved_mask);
+
+ if (tdep_init_done)
+ /* another thread else beat us to it... */
+ goto out;
+
+ mi_init ();
+ dwarf_init ();
+
+#ifndef UNW_REMOTE_ONLY
+ tilegx_local_addr_space_init ();
+#endif
+ tdep_init_done = 1; /* signal that we're initialized... */
+
+ out:
+ lock_release (&tilegx_lock, saved_mask);
+}
diff --git a/src/pal/src/libunwind/src/tilegx/Ginit.c b/src/pal/src/libunwind/src/tilegx/Ginit.c
new file mode 100644
index 0000000000..7564a558be
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Ginit.c
@@ -0,0 +1,167 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2014 Tilera Corp.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "unwind_i.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+/* unw_local_addr_space is a NULL pointer in this case. */
+unw_addr_space_t unw_local_addr_space;
+
+#else /* !UNW_REMOTE_ONLY */
+
+static struct unw_addr_space local_addr_space;
+
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
+
+/* Return the address of the 64-bit slot in UC for REG (even for o32,
+ where registers are 32-bit, the slots are still 64-bit). */
+
+static inline void *
+uc_addr (ucontext_t *uc, int reg)
+{
+ if (reg >= UNW_TILEGX_R0 && reg < UNW_TILEGX_R0 + 56)
+ return &uc->uc_mcontext.gregs[reg - UNW_TILEGX_R0];
+ else if (reg == UNW_TILEGX_PC)
+ return &uc->uc_mcontext.pc;
+ else
+ return NULL;
+}
+
+# ifdef UNW_LOCAL_ONLY
+
+HIDDEN void *
+tdep_uc_addr (ucontext_t *uc, int reg)
+{
+ char *addr = uc_addr (uc, reg);
+ return addr;
+}
+
+# endif /* UNW_LOCAL_ONLY */
+
+HIDDEN unw_dyn_info_list_t _U_dyn_info_list;
+
+/* XXX fix me: there is currently no way to locate the dyn-info list
+ by a remote unwinder. On ia64, this is done via a special
+ unwind-table entry. Perhaps something similar can be done with
+ DWARF2 unwind info. */
+
+static void
+put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
+{
+ /* it's a no-op */
+}
+
+static int
+get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
+ void *arg)
+{
+ *dyn_info_list_addr = (unw_word_t) (intptr_t) &_U_dyn_info_list;
+ return 0;
+}
+
+static int
+access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
+ void *arg)
+{
+ if ((long long)addr & (sizeof(unw_word_t) - 1))
+ return 0;
+
+ if (write)
+ {
+ Debug (16, "mem[%llx] <- %llx\n", (long long) addr, (long long) *val);
+ *(unw_word_t *) (intptr_t) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_word_t *) (intptr_t) addr;
+ Debug (16, "mem[%llx] -> %llx\n", (long long) addr, (long long) *val);
+ }
+ return 0;
+}
+
+static int
+access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
+ void *arg)
+{
+ unw_word_t *addr;
+ ucontext_t *uc = arg;
+
+ if (unw_is_fpreg (reg))
+ goto badreg;
+
+ Debug (16, "reg = %s\n", unw_regname (reg));
+ if (!(addr = uc_addr (uc, reg)))
+ goto badreg;
+
+ if (write)
+ {
+ *(unw_word_t *) (intptr_t) addr = (tilegx_reg_t) *val;
+ Debug (12, "%s <- %llx\n", unw_regname (reg), (long long) *val);
+ }
+ else
+ {
+ *val = (tilegx_reg_t) *(unw_word_t *) (intptr_t) addr;
+ Debug (12, "%s -> %llx\n", unw_regname (reg), (long long) *val);
+ }
+ return 0;
+
+ badreg:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+}
+
+static int
+get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
+ char *buf, size_t buf_len, unw_word_t *offp,
+ void *arg)
+{
+ return elf_w (get_proc_name) (as, getpid (), ip, buf, buf_len, offp);
+}
+
+__attribute__((weak)) void
+tilegx_local_addr_space_init (void)
+{
+ memset (&local_addr_space, 0, sizeof (local_addr_space));
+ local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
+
+ local_addr_space.abi = UNW_TILEGX_ABI_N64;
+ local_addr_space.addr_size = sizeof (void *);
+ local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
+ local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
+ local_addr_space.acc.put_unwind_info = put_unwind_info;
+ local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
+ local_addr_space.acc.access_mem = access_mem;
+ local_addr_space.acc.access_reg = access_reg;
+ local_addr_space.acc.access_fpreg = NULL;
+ local_addr_space.acc.resume = tilegx_local_resume;
+ local_addr_space.acc.get_proc_name = get_static_proc_name;
+ unw_flush_cache (&local_addr_space, 0, 0);
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/tilegx/Ginit_local.c b/src/pal/src/libunwind/src/tilegx/Ginit_local.c
new file mode 100644
index 0000000000..31a716df34
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Ginit_local.c
@@ -0,0 +1,80 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2014 Tilera Corp.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "init.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+int
+unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+{
+ return -UNW_EINVAL;
+}
+
+#else /* !UNW_REMOTE_ONLY */
+
+static int
+unw_init_local_common(unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ memset(c, 0, sizeof(unw_cursor_t));
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->dwarf.as = unw_local_addr_space;
+
+ c->dwarf.as_arg = uc;
+ return common_init (c, use_prev_instr);
+}
+
+int
+unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+{
+ return unw_init_local_common(cursor, uc, 1);
+}
+
+int
+unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
+{
+ if (!flag)
+ {
+ return unw_init_local_common(cursor, uc, 1);
+ }
+ else if (flag == UNW_INIT_SIGNAL_FRAME)
+ {
+ return unw_init_local_common(cursor, uc, 0);
+ }
+ else
+ {
+ return -UNW_EINVAL;
+ }
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/tilegx/Ginit_remote.c b/src/pal/src/libunwind/src/tilegx/Ginit_remote.c
new file mode 100644
index 0000000000..2a31b18aae
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Ginit_remote.c
@@ -0,0 +1,47 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2014 Tilera Corp.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "init.h"
+#include "unwind_i.h"
+
+int
+unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
+{
+#ifdef UNW_LOCAL_ONLY
+ return -UNW_EINVAL;
+#else /* !UNW_LOCAL_ONLY */
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->dwarf.as = as;
+ c->dwarf.as_arg = as_arg;
+
+ return common_init (c, 0);
+#endif /* !UNW_LOCAL_ONLY */
+}
diff --git a/src/pal/src/libunwind/src/tilegx/Gis_signal_frame.c b/src/pal/src/libunwind/src/tilegx/Gis_signal_frame.c
new file mode 100644
index 0000000000..5452c2cb2a
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Gis_signal_frame.c
@@ -0,0 +1,115 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2014 Tilera Corp.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include <stdio.h>
+#include "offsets.h"
+
+#ifdef __linux__
+#include <sys/syscall.h>
+#include <arch/abi.h>
+#else
+# error "Only support Linux!"
+#endif
+
+#define MOVELI_R10_RT_SIGRETURN \
+ ( 0x000007e051483000ULL | \
+ ((unsigned long)__NR_rt_sigreturn << 43) | \
+ ((unsigned long)TREG_SYSCALL_NR << 31) )
+#define SWINT1 0x286b180051485000ULL
+
+int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor*) cursor;
+ unw_word_t w0, w1, ip;
+ unw_addr_space_t as;
+ unw_accessors_t *a;
+ void *arg;
+ int ret;
+
+ as = c->dwarf.as;
+ a = unw_get_accessors_int (as);
+ arg = c->dwarf.as_arg;
+
+ ip = c->dwarf.ip;
+
+ if (!ip || !a->access_mem || (ip & (sizeof(unw_word_t) - 1)))
+ return 0;
+
+ if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0)
+ return ret;
+
+ if ((ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0)
+ return ret;
+
+ /* Return 1 if the IP points to a RT sigreturn sequence. */
+ if (w0 == MOVELI_R10_RT_SIGRETURN &&
+ w1 == SWINT1)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+
+HIDDEN int
+tilegx_handle_signal_frame (unw_cursor_t *cursor)
+{
+ int i;
+ struct cursor *c = (struct cursor *) cursor;
+ unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa;
+ struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0);
+ int ret;
+
+ if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0)
+ return -UNW_EUNSPEC;
+
+ /* Save the SP and PC to be able to return execution at this point
+ later in time (unw_resume). */
+ c->sigcontext_sp = c->dwarf.cfa;
+ c->sigcontext_pc = c->dwarf.ip;
+
+ c->sigcontext_addr = sp_addr + sizeof (siginfo_t) +
+ C_ABI_SAVE_AREA_SIZE;
+ sc_addr = c->sigcontext_addr + LINUX_UC_MCONTEXT_OFF;
+
+ /* Update the dwarf cursor.
+ Set the location of the registers to the corresponding addresses of the
+ uc_mcontext / sigcontext structure contents. */
+
+#define SC_REG_OFFSET(X) (8 * X)
+
+ for (i = UNW_TILEGX_R0; i <= UNW_TILEGX_R55; i++)
+ {
+ c->dwarf.loc[i] = DWARF_LOC (sc_addr + SC_REG_OFFSET(i), 0);
+ }
+
+ /* Set SP/CFA and PC/IP. */
+ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_TILEGX_R54], &c->dwarf.cfa);
+ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_TILEGX_R55], &c->dwarf.ip);
+
+ return 1;
+}
diff --git a/src/pal/src/libunwind/src/tilegx/Greg_states_iterate.c b/src/pal/src/libunwind/src/tilegx/Greg_states_iterate.c
new file mode 100644
index 0000000000..a17dc1b561
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Greg_states_iterate.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+ unw_reg_states_callback cb, void *token)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
diff --git a/src/pal/src/libunwind/src/tilegx/Gregs.c b/src/pal/src/libunwind/src/tilegx/Gregs.c
new file mode 100644
index 0000000000..565c6f4432
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Gregs.c
@@ -0,0 +1,76 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2014 Tilera Corp.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+HIDDEN int
+tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
+ int write)
+{
+ dwarf_loc_t loc = DWARF_NULL_LOC;
+
+ if (reg == UNW_TILEGX_R54 && !write)
+ {
+ reg = UNW_TILEGX_CFA;
+ }
+
+ if (reg <= UNW_TILEGX_R55)
+ loc = c->dwarf.loc[reg - UNW_TILEGX_R0];
+ else if (reg == UNW_TILEGX_CFA)
+ {
+ if (write)
+ return -UNW_EREADONLYREG;
+ *valp = c->dwarf.cfa;
+ return 0;
+ }
+ else
+ {
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+ }
+
+ if (write)
+ {
+ if (ci->dwarf.use_prev_instr == 0) {
+ if (reg == UNW_TILEGX_PC)
+ c->dwarf.ip = *valp; /* update the IP cache */
+ }
+ else {
+ if (reg == UNW_TILEGX_R55)
+ c->dwarf.ip = *valp; /* update the IP cache */
+ }
+ return dwarf_put (&c->dwarf, loc, *valp);
+ }
+ else
+ return dwarf_get (&c->dwarf, loc, valp);
+}
+
+HIDDEN int
+tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
+ int write)
+{
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+}
diff --git a/src/pal/src/libunwind/src/tilegx/Gresume.c b/src/pal/src/libunwind/src/tilegx/Gresume.c
new file mode 100644
index 0000000000..ece443a5b5
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Gresume.c
@@ -0,0 +1,94 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2014 Tilera Corp.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+
+#include "unwind_i.h"
+#include "offsets.h"
+#include <ucontext.h>
+
+#ifndef UNW_REMOTE_ONLY
+
+HIDDEN inline int
+tilegx_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
+{
+ int i;
+ struct cursor *c = (struct cursor *) cursor;
+ ucontext_t *uc = c->dwarf.as_arg;
+
+ Debug (1, "(cursor=%p\n", c);
+
+ return setcontext(uc);
+}
+
+#endif /* !UNW_REMOTE_ONLY */
+
+static inline void
+establish_machine_state (struct cursor *c)
+{
+ unw_addr_space_t as = c->dwarf.as;
+ void *arg = c->dwarf.as_arg;
+ unw_fpreg_t fpval;
+ unw_word_t val;
+ int reg;
+
+ Debug (8, "copying out cursor state\n");
+
+ for (reg = 0; reg <= UNW_REG_LAST; ++reg)
+ {
+ Debug (16, "copying %s %d\n", unw_regname (reg), reg);
+
+ if (unw_is_fpreg (reg))
+ {
+ Debug (1, "no fp!");
+ abort ();
+ }
+ else
+ {
+ if (tdep_access_reg (c, reg, &val, 0) >= 0)
+ as->acc.access_reg (as, reg, &val, 1, arg);
+ }
+ }
+}
+
+int
+unw_resume (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ Debug (1, "(cursor=%p) ip=0x%lx\n", c, c->dwarf.ip);
+
+ if (!c->dwarf.ip)
+ {
+ /* This can happen easily when the frame-chain gets truncated
+ due to bad or missing unwind-info. */
+ Debug (1, "refusing to resume execution at address 0\n");
+ return -UNW_EINVAL;
+ }
+
+ establish_machine_state (c);
+
+ return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c,
+ c->dwarf.as_arg);
+}
diff --git a/src/pal/src/libunwind/src/tilegx/Gstep.c b/src/pal/src/libunwind/src/tilegx/Gstep.c
new file mode 100644
index 0000000000..c748dbc588
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Gstep.c
@@ -0,0 +1,53 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2014 Tilera Corp.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "offsets.h"
+
+int
+unw_step (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ Debug (1, "(cursor=%p, ip=0x%016lx, sp=0x%016lx)\n",
+ c, c->dwarf.ip, c->dwarf.cfa);
+
+ /* Special handling the singal frame. */
+ if (unw_is_signal_frame (cursor) > 0)
+ return tilegx_handle_signal_frame (cursor);
+
+ /* Try DWARF-based unwinding... */
+ ret = dwarf_step (&c->dwarf);
+
+ if (unlikely (ret == -UNW_ESTOPUNWIND))
+ return ret;
+
+ /* Dwarf unwinding didn't work, stop. */
+ if (unlikely (ret < 0))
+ return 0;
+
+ return (c->dwarf.ip == 0) ? 0 : 1;
+}
diff --git a/src/pal/src/libunwind/src/tilegx/Lapply_reg_state.c b/src/pal/src/libunwind/src/tilegx/Lapply_reg_state.c
new file mode 100644
index 0000000000..7ebada480e
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Lapply_reg_state.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/pal/src/libunwind/src/tilegx/Lcreate_addr_space.c b/src/pal/src/libunwind/src/tilegx/Lcreate_addr_space.c
new file mode 100644
index 0000000000..0f2dc6be90
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Lcreate_addr_space.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gcreate_addr_space.c"
+#endif
diff --git a/src/pal/src/libunwind/src/tilegx/Lget_proc_info.c b/src/pal/src/libunwind/src/tilegx/Lget_proc_info.c
new file mode 100644
index 0000000000..69028b019f
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Lget_proc_info.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_proc_info.c"
+#endif
diff --git a/src/pal/src/libunwind/src/tilegx/Lget_save_loc.c b/src/pal/src/libunwind/src/tilegx/Lget_save_loc.c
new file mode 100644
index 0000000000..9ea048a907
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Lget_save_loc.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_save_loc.c"
+#endif
diff --git a/src/pal/src/libunwind/src/tilegx/Lglobal.c b/src/pal/src/libunwind/src/tilegx/Lglobal.c
new file mode 100644
index 0000000000..6d7b489e14
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Lglobal.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gglobal.c"
+#endif
diff --git a/src/pal/src/libunwind/src/tilegx/Linit.c b/src/pal/src/libunwind/src/tilegx/Linit.c
new file mode 100644
index 0000000000..e9abfdd46a
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Linit.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit.c"
+#endif
diff --git a/src/pal/src/libunwind/src/tilegx/Linit_local.c b/src/pal/src/libunwind/src/tilegx/Linit_local.c
new file mode 100644
index 0000000000..68a1687e85
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Linit_local.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_local.c"
+#endif
diff --git a/src/pal/src/libunwind/src/tilegx/Linit_remote.c b/src/pal/src/libunwind/src/tilegx/Linit_remote.c
new file mode 100644
index 0000000000..58cb04ab7c
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Linit_remote.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_remote.c"
+#endif
diff --git a/src/pal/src/libunwind/src/tilegx/Lis_signal_frame.c b/src/pal/src/libunwind/src/tilegx/Lis_signal_frame.c
new file mode 100644
index 0000000000..b9a7c4f51a
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Lis_signal_frame.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gis_signal_frame.c"
+#endif
diff --git a/src/pal/src/libunwind/src/tilegx/Lreg_states_iterate.c b/src/pal/src/libunwind/src/tilegx/Lreg_states_iterate.c
new file mode 100644
index 0000000000..f1eb1e79dc
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Lreg_states_iterate.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
diff --git a/src/pal/src/libunwind/src/tilegx/Lregs.c b/src/pal/src/libunwind/src/tilegx/Lregs.c
new file mode 100644
index 0000000000..2c9c75cd7d
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Lregs.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gregs.c"
+#endif
diff --git a/src/pal/src/libunwind/src/tilegx/Lresume.c b/src/pal/src/libunwind/src/tilegx/Lresume.c
new file mode 100644
index 0000000000..41a8cf003d
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Lresume.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gresume.c"
+#endif
diff --git a/src/pal/src/libunwind/src/tilegx/Lstep.c b/src/pal/src/libunwind/src/tilegx/Lstep.c
new file mode 100644
index 0000000000..c1ac3c7547
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/Lstep.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gstep.c"
+#endif
diff --git a/src/pal/src/libunwind/src/tilegx/elfxx.c b/src/pal/src/libunwind/src/tilegx/elfxx.c
new file mode 100644
index 0000000000..07d3d12b94
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/elfxx.c
@@ -0,0 +1,27 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+#include "../src/elfxx.c"
diff --git a/src/pal/src/libunwind/src/tilegx/gen-offsets.c b/src/pal/src/libunwind/src/tilegx/gen-offsets.c
new file mode 100644
index 0000000000..8704bb215e
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/gen-offsets.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include <stddef.h>
+#include <ucontext.h>
+
+#define UC(N,X) \
+ printf ("#define LINUX_UC_" N "_OFF\t0x%X\n", offsetof (ucontext_t, X))
+
+#define SC(N,X) \
+ printf ("#define LINUX_SC_" N "_OFF\t0x%X\n", offsetof (struct sigcontext, X))
+
+int
+main (void)
+{
+ printf (
+"/* Linux-specific definitions: */\n\n"
+
+"/* Define various structure offsets to simplify cross-compilation. */\n\n"
+
+"/* Offsets for TILEGX Linux \"ucontext_t\": */\n\n");
+
+ UC ("FLAGS", uc_flags);
+ UC ("LINK", uc_link);
+ UC ("STACK", uc_stack);
+ UC ("MCONTEXT", uc_mcontext);
+ UC ("SIGMASK", uc_sigmask);
+
+ UC ("MCONTEXT_GREGS", uc_mcontext.gregs);
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/tilegx/getcontext.S b/src/pal/src/libunwind/src/tilegx/getcontext.S
new file mode 100644
index 0000000000..fbc8654bc7
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/getcontext.S
@@ -0,0 +1,36 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2014 Tilera Corp.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "offsets.h"
+#include <endian.h>
+
+ .text
+ # define REG(X) LINUX_UC_MCONTEXT_GREGS + 8 * (X)
+ .global _Utilegx_getcontext
+ .type _Utilegx_getcontext, %function
+ # This is a stub version of getcontext() for TILEGX.
+_Utilegx_getcontext:
+
+
diff --git a/src/pal/src/libunwind/src/tilegx/init.h b/src/pal/src/libunwind/src/tilegx/init.h
new file mode 100644
index 0000000000..0e0f7fd1da
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/init.h
@@ -0,0 +1,63 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2014 Tilera Corp.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+static inline int
+common_init (struct cursor *c, unsigned use_prev_instr)
+{
+ int ret, i;
+
+ for (i = 0; i < 56; i++)
+ c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, UNW_TILEGX_R0 + i);
+ for (i = 56; i < DWARF_NUM_PRESERVED_REGS; ++i)
+ c->dwarf.loc[i] = DWARF_NULL_LOC;
+
+ if (use_prev_instr == 0)
+ ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_TILEGX_PC),
+ &c->dwarf.ip);
+ else
+ ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_TILEGX_R55),
+ &c->dwarf.ip);
+
+ if (ret < 0)
+ return ret;
+
+ ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_TILEGX_R54),
+ &c->dwarf.cfa);
+
+ if (ret < 0)
+ return ret;
+
+ c->dwarf.args_size = 0;
+ c->dwarf.stash_frames = 0;
+ c->dwarf.use_prev_instr = use_prev_instr;
+ c->dwarf.pi_valid = 0;
+ c->dwarf.pi_is_dynamic = 0;
+ c->dwarf.hint = 0;
+ c->dwarf.prev_rs = 0;
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/tilegx/is_fpreg.c b/src/pal/src/libunwind/src/tilegx/is_fpreg.c
new file mode 100644
index 0000000000..d6d5896901
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/is_fpreg.c
@@ -0,0 +1,33 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+/* TILEGX has no FP. */
+
+int
+unw_is_fpreg (int regnum)
+{
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/tilegx/offsets.h b/src/pal/src/libunwind/src/tilegx/offsets.h
new file mode 100644
index 0000000000..6d30f1edcf
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/offsets.h
@@ -0,0 +1,12 @@
+/* Linux-specific definitions: */
+
+/* Define various structure offsets to simplify cross-compilation. */
+
+/* Offsets for TILEGX Linux "ucontext_t": */
+
+#define LINUX_UC_FLAGS_OFF 0x0
+#define LINUX_UC_LINK_OFF 0x8
+#define LINUX_UC_STACK_OFF 0x10
+#define LINUX_UC_MCONTEXT_OFF 0x28
+#define LINUX_UC_SIGMASK_OFF 0x228
+#define LINUX_UC_MCONTEXT_GREGS 0x28
diff --git a/src/pal/src/libunwind/src/tilegx/regname.c b/src/pal/src/libunwind/src/tilegx/regname.c
new file mode 100644
index 0000000000..0ce47b9d66
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/regname.c
@@ -0,0 +1,55 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2014 Tilera Corp.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+static const char *regname[] =
+ {
+ /* 0. */
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ /* 8. */
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ /* 16. */
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ /* 24. */
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+ /* 32. */
+ "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
+ /* 40. */
+ "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
+ /* 48. */
+ "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",
+ /* pc, cfa */
+ "pc", "cfa"
+ };
+
+const char *
+unw_regname (unw_regnum_t reg)
+{
+ if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
+ return regname[reg];
+ else
+ return "???";
+}
diff --git a/src/pal/src/libunwind/src/tilegx/siglongjmp.S b/src/pal/src/libunwind/src/tilegx/siglongjmp.S
new file mode 100644
index 0000000000..bccb1c7785
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/siglongjmp.S
@@ -0,0 +1,7 @@
+ /* Dummy implementation for now. */
+ .globl _UI_siglongjmp_cont
+ .globl _UI_longjmp_cont
+
+_UI_siglongjmp_cont:
+_UI_longjmp_cont:
+ jrp lr
diff --git a/src/pal/src/libunwind/src/tilegx/unwind_i.h b/src/pal/src/libunwind/src/tilegx/unwind_i.h
new file mode 100644
index 0000000000..9d41c90b4d
--- /dev/null
+++ b/src/pal/src/libunwind/src/tilegx/unwind_i.h
@@ -0,0 +1,46 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 CodeSourcery
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef unwind_i_h
+#define unwind_i_h
+
+#include <memory.h>
+#include <stdint.h>
+
+#include <libunwind-tilegx.h>
+
+#include "libunwind_i.h"
+
+#define tilegx_local_resume UNW_OBJ(local_resume)
+#define tilegx_local_addr_space_init UNW_OBJ(local_addr_space_init)
+
+extern int tilegx_local_resume (unw_addr_space_t as,
+ unw_cursor_t *cursor,
+ void *arg);
+#define tilegx_handle_signal_frame UNW_OBJ(handle_signal_frame)
+extern int tilegx_handle_signal_frame(unw_cursor_t *cursor);
+
+extern void tilegx_local_addr_space_init (void);
+
+#endif /* unwind_i_h */
diff --git a/src/pal/src/libunwind/src/unwind/Backtrace.c b/src/pal/src/libunwind/src/unwind/Backtrace.c
new file mode 100644
index 0000000000..0b14df4cb9
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/Backtrace.c
@@ -0,0 +1,56 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind-internal.h"
+
+_Unwind_Reason_Code
+_Unwind_Backtrace (_Unwind_Trace_Fn trace, void *trace_parameter)
+{
+ struct _Unwind_Context context;
+ unw_context_t uc;
+ int ret;
+
+ if (_Unwind_InitContext (&context, &uc) < 0)
+ return _URC_FATAL_PHASE1_ERROR;
+
+ /* Phase 1 (search phase) */
+
+ while (1)
+ {
+ if ((ret = unw_step (&context.cursor)) <= 0)
+ {
+ if (ret == 0)
+ return _URC_END_OF_STACK;
+ else
+ return _URC_FATAL_PHASE1_ERROR;
+ }
+
+ if ((*trace) (&context, trace_parameter) != _URC_NO_REASON)
+ return _URC_FATAL_PHASE1_ERROR;
+ }
+}
+
+_Unwind_Reason_Code __libunwind_Unwind_Backtrace (_Unwind_Trace_Fn, void *)
+ ALIAS (_Unwind_Backtrace);
diff --git a/src/pal/src/libunwind/src/unwind/DeleteException.c b/src/pal/src/libunwind/src/unwind/DeleteException.c
new file mode 100644
index 0000000000..ad38eaf651
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/DeleteException.c
@@ -0,0 +1,38 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind-internal.h"
+
+void
+_Unwind_DeleteException (struct _Unwind_Exception *exception_object)
+{
+ _Unwind_Exception_Cleanup_Fn cleanup = exception_object->exception_cleanup;
+
+ if (cleanup)
+ (*cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exception_object);
+}
+
+void __libunwind_Unwind_DeleteException (struct _Unwind_Exception *)
+ ALIAS (_Unwind_DeleteException);
diff --git a/src/pal/src/libunwind/src/unwind/FindEnclosingFunction.c b/src/pal/src/libunwind/src/unwind/FindEnclosingFunction.c
new file mode 100644
index 0000000000..4f10666172
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/FindEnclosingFunction.c
@@ -0,0 +1,42 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind-internal.h"
+
+void *
+_Unwind_FindEnclosingFunction (void *ip)
+{
+ unw_proc_info_t pi;
+
+ if (unw_get_proc_info_by_ip (unw_local_addr_space,
+ (unw_word_t) (uintptr_t) ip, &pi, 0)
+ < 0)
+ return NULL;
+
+ return (void *) (uintptr_t) pi.start_ip;
+}
+
+void *__libunwind_Unwind_FindEnclosingFunction (void *)
+ ALIAS (_Unwind_FindEnclosingFunction);
diff --git a/src/pal/src/libunwind/src/unwind/ForcedUnwind.c b/src/pal/src/libunwind/src/unwind/ForcedUnwind.c
new file mode 100644
index 0000000000..905b31cd87
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/ForcedUnwind.c
@@ -0,0 +1,52 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind-internal.h"
+
+_Unwind_Reason_Code
+_Unwind_ForcedUnwind (struct _Unwind_Exception *exception_object,
+ _Unwind_Stop_Fn stop, void *stop_parameter)
+{
+ struct _Unwind_Context context;
+ unw_context_t uc;
+
+ /* We check "stop" here to tell the compiler's inliner that
+ exception_object->private_1 isn't NULL when calling
+ _Unwind_Phase2(). */
+ if (!stop)
+ return _URC_FATAL_PHASE2_ERROR;
+
+ if (_Unwind_InitContext (&context, &uc) < 0)
+ return _URC_FATAL_PHASE2_ERROR;
+
+ exception_object->private_1 = (unsigned long) stop;
+ exception_object->private_2 = (unsigned long) stop_parameter;
+
+ return _Unwind_Phase2 (exception_object, &context);
+}
+
+_Unwind_Reason_Code __libunwind_Unwind_ForcedUnwind (struct _Unwind_Exception*,
+ _Unwind_Stop_Fn, void *)
+ ALIAS (_Unwind_ForcedUnwind);
diff --git a/src/pal/src/libunwind/src/unwind/GetBSP.c b/src/pal/src/libunwind/src/unwind/GetBSP.c
new file mode 100644
index 0000000000..d1bc84e0d2
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/GetBSP.c
@@ -0,0 +1,42 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind-internal.h"
+
+unsigned long
+_Unwind_GetBSP (struct _Unwind_Context *context)
+{
+#ifdef UNW_TARGET_IA64
+ unw_word_t val;
+
+ unw_get_reg (&context->cursor, UNW_IA64_BSP, &val);
+ return val;
+#else
+ return 0;
+#endif
+}
+
+unsigned long __libunwind_Unwind_GetBSP (struct _Unwind_Context *)
+ ALIAS (_Unwind_GetBSP);
diff --git a/src/pal/src/libunwind/src/unwind/GetCFA.c b/src/pal/src/libunwind/src/unwind/GetCFA.c
new file mode 100644
index 0000000000..5ca63903dd
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/GetCFA.c
@@ -0,0 +1,38 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind-internal.h"
+
+unsigned long
+_Unwind_GetCFA (struct _Unwind_Context *context)
+{
+ unw_word_t val;
+
+ unw_get_reg (&context->cursor, UNW_REG_SP, &val);
+ return val;
+}
+
+unsigned long __libunwind_Unwind_GetCFA (struct _Unwind_Context *)
+ ALIAS (_Unwind_GetCFA);
diff --git a/src/pal/src/libunwind/src/unwind/GetDataRelBase.c b/src/pal/src/libunwind/src/unwind/GetDataRelBase.c
new file mode 100644
index 0000000000..8e6914f4f3
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/GetDataRelBase.c
@@ -0,0 +1,39 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind-internal.h"
+
+unsigned long
+_Unwind_GetDataRelBase (struct _Unwind_Context *context)
+{
+ unw_proc_info_t pi;
+
+ pi.gp = 0;
+ unw_get_proc_info (&context->cursor, &pi);
+ return pi.gp;
+}
+
+unsigned long __libunwind_Unwind_GetDataRelBase (struct _Unwind_Context *)
+ ALIAS (_Unwind_GetDataRelBase);
diff --git a/src/pal/src/libunwind/src/unwind/GetGR.c b/src/pal/src/libunwind/src/unwind/GetGR.c
new file mode 100644
index 0000000000..fa70943435
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/GetGR.c
@@ -0,0 +1,43 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind-internal.h"
+
+unsigned long
+_Unwind_GetGR (struct _Unwind_Context *context, int index)
+{
+ unw_word_t val;
+
+ if (index == UNW_REG_SP && context->end_of_stack)
+ /* _Unwind_ForcedUnwind() requires us to return a NULL
+ stack-pointer after reaching the end of the stack. */
+ return 0;
+
+ unw_get_reg (&context->cursor, index, &val);
+ return val;
+}
+
+unsigned long __libunwind_Unwind_GetGR (struct _Unwind_Context *, int)
+ ALIAS (_Unwind_GetGR);
diff --git a/src/pal/src/libunwind/src/unwind/GetIP.c b/src/pal/src/libunwind/src/unwind/GetIP.c
new file mode 100644
index 0000000000..e9fc494402
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/GetIP.c
@@ -0,0 +1,38 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind-internal.h"
+
+unsigned long
+_Unwind_GetIP (struct _Unwind_Context *context)
+{
+ unw_word_t val;
+
+ unw_get_reg (&context->cursor, UNW_REG_IP, &val);
+ return val;
+}
+
+unsigned long __libunwind_Unwind_GetIP (struct _Unwind_Context *)
+ ALIAS (_Unwind_GetIP);
diff --git a/src/pal/src/libunwind/src/unwind/GetIPInfo.c b/src/pal/src/libunwind/src/unwind/GetIPInfo.c
new file mode 100644
index 0000000000..e8ee7fd7f1
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/GetIPInfo.c
@@ -0,0 +1,42 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2009 Red Hat
+ Contributed by Jan Kratochvil <jan.kratochvil@redhat.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind-internal.h"
+
+/* gcc/unwind-dw2.c: Retrieve the return address and flag whether that IP is
+ before or after first not yet fully executed instruction. */
+
+unsigned long
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
+{
+ unw_word_t val;
+
+ unw_get_reg (&context->cursor, UNW_REG_IP, &val);
+ *ip_before_insn = unw_is_signal_frame (&context->cursor);
+ return val;
+}
+
+unsigned long __libunwind_Unwind_GetIPInfo (struct _Unwind_Context *, int *)
+ ALIAS (_Unwind_GetIPInfo);
diff --git a/src/pal/src/libunwind/src/unwind/GetLanguageSpecificData.c b/src/pal/src/libunwind/src/unwind/GetLanguageSpecificData.c
new file mode 100644
index 0000000000..e7ca9b453c
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/GetLanguageSpecificData.c
@@ -0,0 +1,40 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind-internal.h"
+
+unsigned long
+_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
+{
+ unw_proc_info_t pi;
+
+ pi.lsda = 0;
+ unw_get_proc_info (&context->cursor, &pi);
+ return pi.lsda;
+}
+
+unsigned long
+__libunwind_Unwind_GetLanguageSpecificData (struct _Unwind_Context *)
+ ALIAS (_Unwind_GetLanguageSpecificData);
diff --git a/src/pal/src/libunwind/src/unwind/GetRegionStart.c b/src/pal/src/libunwind/src/unwind/GetRegionStart.c
new file mode 100644
index 0000000000..f4995813fa
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/GetRegionStart.c
@@ -0,0 +1,39 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind-internal.h"
+
+unsigned long
+_Unwind_GetRegionStart (struct _Unwind_Context *context)
+{
+ unw_proc_info_t pi;
+
+ pi.start_ip = 0;
+ unw_get_proc_info (&context->cursor, &pi);
+ return pi.start_ip;
+}
+
+unsigned long __libunwind_Unwind_GetRegionStart (struct _Unwind_Context *)
+ ALIAS (_Unwind_GetRegionStart);
diff --git a/src/pal/src/libunwind/src/unwind/GetTextRelBase.c b/src/pal/src/libunwind/src/unwind/GetTextRelBase.c
new file mode 100644
index 0000000000..ce65ae93e7
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/GetTextRelBase.c
@@ -0,0 +1,35 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind-internal.h"
+
+unsigned long
+_Unwind_GetTextRelBase (struct _Unwind_Context *context)
+{
+ return 0;
+}
+
+unsigned long __libunwind_Unwind_GetTextRelBase (struct _Unwind_Context *)
+ ALIAS (_Unwind_GetTextRelBase);
diff --git a/src/pal/src/libunwind/src/unwind/RaiseException.c b/src/pal/src/libunwind/src/unwind/RaiseException.c
new file mode 100644
index 0000000000..3c3ca19e98
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/RaiseException.c
@@ -0,0 +1,103 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind-internal.h"
+
+_Unwind_Reason_Code
+_Unwind_RaiseException (struct _Unwind_Exception *exception_object)
+{
+ uint64_t exception_class = exception_object->exception_class;
+ _Unwind_Personality_Fn personality;
+ struct _Unwind_Context context;
+ _Unwind_Reason_Code reason;
+ unw_proc_info_t pi;
+ unw_context_t uc;
+ unw_word_t ip;
+ int ret;
+
+ Debug (1, "(exception_object=%p)\n", exception_object);
+
+ if (_Unwind_InitContext (&context, &uc) < 0)
+ return _URC_FATAL_PHASE1_ERROR;
+
+ /* Phase 1 (search phase) */
+
+ while (1)
+ {
+ if ((ret = unw_step (&context.cursor)) <= 0)
+ {
+ if (ret == 0)
+ {
+ Debug (1, "no handler found\n");
+ return _URC_END_OF_STACK;
+ }
+ else
+ return _URC_FATAL_PHASE1_ERROR;
+ }
+
+ if (unw_get_proc_info (&context.cursor, &pi) < 0)
+ return _URC_FATAL_PHASE1_ERROR;
+
+ personality = (_Unwind_Personality_Fn) (uintptr_t) pi.handler;
+ if (personality)
+ {
+ reason = (*personality) (_U_VERSION, _UA_SEARCH_PHASE,
+ exception_class, exception_object,
+ &context);
+ if (reason != _URC_CONTINUE_UNWIND)
+ {
+ if (reason == _URC_HANDLER_FOUND)
+ break;
+ else
+ {
+ Debug (1, "personality returned %d\n", reason);
+ return _URC_FATAL_PHASE1_ERROR;
+ }
+ }
+ }
+ }
+
+ /* Exceptions are associated with IP-ranges. If a given exception
+ is handled at a particular IP, it will _always_ be handled at
+ that IP. If this weren't true, we'd have to track the tuple
+ (IP,SP,BSP) to uniquely identify the stack frame that's handling
+ the exception. */
+ if (unw_get_reg (&context.cursor, UNW_REG_IP, &ip) < 0)
+ return _URC_FATAL_PHASE1_ERROR;
+ exception_object->private_1 = 0; /* clear "stop" pointer */
+ exception_object->private_2 = ip; /* save frame marker */
+
+ Debug (1, "found handler for IP=%lx; entering cleanup phase\n", (long) ip);
+
+ /* Reset the cursor to the first frame: */
+ if (unw_init_local (&context.cursor, &uc) < 0)
+ return _URC_FATAL_PHASE1_ERROR;
+
+ return _Unwind_Phase2 (exception_object, &context);
+}
+
+_Unwind_Reason_Code
+__libunwind_Unwind_RaiseException (struct _Unwind_Exception *)
+ ALIAS (_Unwind_RaiseException);
diff --git a/src/pal/src/libunwind/src/unwind/Resume.c b/src/pal/src/libunwind/src/unwind/Resume.c
new file mode 100644
index 0000000000..e23d6be27c
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/Resume.c
@@ -0,0 +1,42 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind-internal.h"
+
+void
+_Unwind_Resume (struct _Unwind_Exception *exception_object)
+{
+ struct _Unwind_Context context;
+ unw_context_t uc;
+
+ if (_Unwind_InitContext (&context, &uc) < 0)
+ abort ();
+
+ _Unwind_Phase2 (exception_object, &context);
+ abort ();
+}
+
+void __libunwind_Unwind_Resume (struct _Unwind_Exception *)
+ ALIAS (_Unwind_Resume);
diff --git a/src/pal/src/libunwind/src/unwind/Resume_or_Rethrow.c b/src/pal/src/libunwind/src/unwind/Resume_or_Rethrow.c
new file mode 100644
index 0000000000..9c76443b36
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/Resume_or_Rethrow.c
@@ -0,0 +1,47 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind-internal.h"
+
+_Unwind_Reason_Code
+_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exception_object)
+{
+ struct _Unwind_Context context;
+ unw_context_t uc;
+
+ if (exception_object->private_1)
+ {
+ if (_Unwind_InitContext (&context, &uc) < 0)
+ return _URC_FATAL_PHASE2_ERROR;
+
+ return _Unwind_Phase2 (exception_object, &context);
+ }
+ else
+ return _Unwind_RaiseException (exception_object);
+}
+
+_Unwind_Reason_Code
+__libunwind_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *)
+ ALIAS (_Unwind_Resume_or_Rethrow);
diff --git a/src/pal/src/libunwind/src/unwind/SetGR.c b/src/pal/src/libunwind/src/unwind/SetGR.c
new file mode 100644
index 0000000000..ae77a8e825
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/SetGR.c
@@ -0,0 +1,47 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind-internal.h"
+#ifdef UNW_TARGET_X86
+#include "dwarf_i.h"
+#endif
+
+void
+_Unwind_SetGR (struct _Unwind_Context *context, int index,
+ unsigned long new_value)
+{
+#ifdef UNW_TARGET_X86
+ index = dwarf_to_unw_regnum(index);
+#endif
+ unw_set_reg (&context->cursor, index, new_value);
+#ifdef UNW_TARGET_IA64
+ if (index >= UNW_IA64_GR && index <= UNW_IA64_GR + 127)
+ /* Clear the NaT bit. */
+ unw_set_reg (&context->cursor, UNW_IA64_NAT + (index - UNW_IA64_GR), 0);
+#endif
+}
+
+void __libunwind_Unwind_SetGR (struct _Unwind_Context *, int, unsigned long)
+ ALIAS (_Unwind_SetGR);
diff --git a/src/pal/src/libunwind/src/unwind/SetIP.c b/src/pal/src/libunwind/src/unwind/SetIP.c
new file mode 100644
index 0000000000..fccc2f0dd5
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/SetIP.c
@@ -0,0 +1,35 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind-internal.h"
+
+void
+_Unwind_SetIP (struct _Unwind_Context *context, unsigned long new_value)
+{
+ unw_set_reg (&context->cursor, UNW_REG_IP, new_value);
+}
+
+void __libunwind_Unwind_SetIP (struct _Unwind_Context *, unsigned long)
+ ALIAS (_Unwind_SetIP);
diff --git a/src/pal/src/libunwind/src/unwind/libunwind.pc.in b/src/pal/src/libunwind/src/unwind/libunwind.pc.in
new file mode 100644
index 0000000000..1505c5d6f6
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/libunwind.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libunwind
+Description: libunwind base library
+Version: @VERSION@
+Libs: -L${libdir} -lunwind
+Libs.private: @LIBLZMA@
+Cflags: -I${includedir}
diff --git a/src/pal/src/libunwind/src/unwind/unwind-internal.h b/src/pal/src/libunwind/src/unwind/unwind-internal.h
new file mode 100644
index 0000000000..c68fc3c5ed
--- /dev/null
+++ b/src/pal/src/libunwind/src/unwind/unwind-internal.h
@@ -0,0 +1,140 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003, 2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef unwind_internal_h
+#define unwind_internal_h
+
+#define UNW_LOCAL_ONLY
+
+#include <unwind.h>
+#include <stdlib.h>
+#include <libunwind.h>
+
+#include "libunwind_i.h"
+
+/* The version of the _Unwind_*() interface implemented by this code. */
+#define _U_VERSION 1
+
+typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)
+ (int, _Unwind_Action, uint64_t, struct _Unwind_Exception *,
+ struct _Unwind_Context *);
+
+struct _Unwind_Context {
+ unw_cursor_t cursor;
+ int end_of_stack; /* set to 1 if the end of stack was reached */
+};
+
+/* This must be a macro because unw_getcontext() must be invoked from
+ the callee, even if optimization (and hence inlining) is turned
+ off. The macro arguments MUST NOT have any side-effects. */
+#define _Unwind_InitContext(context, uc) \
+ ((context)->end_of_stack = 0, \
+ ((unw_getcontext (uc) < 0 || unw_init_local (&(context)->cursor, uc) < 0) \
+ ? -1 : 0))
+
+static _Unwind_Reason_Code ALWAYS_INLINE
+_Unwind_Phase2 (struct _Unwind_Exception *exception_object,
+ struct _Unwind_Context *context)
+{
+ _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) exception_object->private_1;
+ uint64_t exception_class = exception_object->exception_class;
+ void *stop_parameter = (void *) exception_object->private_2;
+ _Unwind_Personality_Fn personality;
+ _Unwind_Reason_Code reason;
+ _Unwind_Action actions;
+ unw_proc_info_t pi;
+ unw_word_t ip;
+ int ret;
+
+ actions = _UA_CLEANUP_PHASE;
+ if (stop)
+ actions |= _UA_FORCE_UNWIND;
+
+ while (1)
+ {
+ ret = unw_step (&context->cursor);
+ if (ret <= 0)
+ {
+ if (ret == 0)
+ {
+ actions |= _UA_END_OF_STACK;
+ context->end_of_stack = 1;
+ }
+ else
+ return _URC_FATAL_PHASE2_ERROR;
+ }
+
+ if (stop)
+ {
+ reason = (*stop) (_U_VERSION, actions, exception_class,
+ exception_object, context, stop_parameter);
+ if (reason != _URC_NO_REASON)
+ /* Stop function may return _URC_FATAL_PHASE2_ERROR if
+ it's unable to handle end-of-stack condition or
+ _URC_FATAL_PHASE2_ERROR if something is wrong. Not
+ that it matters: the resulting state is indeterminate
+ anyhow so we must return _URC_FATAL_PHASE2_ERROR... */
+ return _URC_FATAL_PHASE2_ERROR;
+ }
+
+ if (context->end_of_stack
+ || unw_get_proc_info (&context->cursor, &pi) < 0)
+ return _URC_FATAL_PHASE2_ERROR;
+
+ personality = (_Unwind_Personality_Fn) (uintptr_t) pi.handler;
+ if (personality)
+ {
+ if (!stop)
+ {
+ if (unw_get_reg (&context->cursor, UNW_REG_IP, &ip) < 0)
+ return _URC_FATAL_PHASE2_ERROR;
+
+ if ((unsigned long) stop_parameter == ip)
+ actions |= _UA_HANDLER_FRAME;
+ }
+
+ reason = (*personality) (_U_VERSION, actions, exception_class,
+ exception_object, context);
+ if (reason != _URC_CONTINUE_UNWIND)
+ {
+ if (reason == _URC_INSTALL_CONTEXT)
+ {
+ /* we may regain control via _Unwind_Resume() */
+ unw_resume (&context->cursor);
+ abort ();
+ }
+ else
+ return _URC_FATAL_PHASE2_ERROR;
+ }
+ if (actions & _UA_HANDLER_FRAME)
+ /* The personality routine for the handler-frame changed
+ it's mind; that's a no-no... */
+ abort ();
+ }
+ }
+ return _URC_FATAL_PHASE2_ERROR; /* shouldn't be reached */
+}
+
+#endif /* unwind_internal_h */
diff --git a/src/pal/src/libunwind/src/x86/Gapply_reg_state.c b/src/pal/src/libunwind/src/x86/Gapply_reg_state.c
new file mode 100644
index 0000000000..82f056da67
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Gapply_reg_state.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+ void *reg_states_data)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
diff --git a/src/pal/src/libunwind/src/x86/Gcreate_addr_space.c b/src/pal/src/libunwind/src/x86/Gcreate_addr_space.c
new file mode 100644
index 0000000000..a7e41a58f4
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Gcreate_addr_space.c
@@ -0,0 +1,58 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+
+#include "unwind_i.h"
+
+#if defined(_LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN)
+#define __LITTLE_ENDIAN _LITTLE_ENDIAN
+#endif
+
+unw_addr_space_t
+unw_create_addr_space (unw_accessors_t *a, int byte_order)
+{
+#ifdef UNW_LOCAL_ONLY
+ return NULL;
+#else
+ unw_addr_space_t as;
+
+ /*
+ * x86 supports only little-endian.
+ */
+ if (byte_order != 0 && byte_order != __LITTLE_ENDIAN)
+ return NULL;
+
+ as = malloc (sizeof (*as));
+ if (!as)
+ return NULL;
+
+ memset (as, 0, sizeof (*as));
+
+ as->acc = *a;
+
+ return as;
+#endif
+}
diff --git a/src/pal/src/libunwind/src/x86/Gget_proc_info.c b/src/pal/src/libunwind/src/x86/Gget_proc_info.c
new file mode 100644
index 0000000000..4dc2cff366
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Gget_proc_info.c
@@ -0,0 +1,45 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (dwarf_make_proc_info (&c->dwarf) < 0)
+ {
+ /* On x86, it's relatively common to be missing DWARF unwind
+ info. We don't want to fail in that case, because the
+ frame-chain still would let us do a backtrace at least. */
+ memset (pi, 0, sizeof (*pi));
+ pi->start_ip = c->dwarf.ip;
+ pi->end_ip = c->dwarf.ip + 1;
+ return 0;
+ }
+ *pi = c->dwarf.pi;
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/x86/Gget_save_loc.c b/src/pal/src/libunwind/src/x86/Gget_save_loc.c
new file mode 100644
index 0000000000..e459382f6d
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Gget_save_loc.c
@@ -0,0 +1,133 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ dwarf_loc_t loc;
+
+ loc = DWARF_NULL_LOC; /* default to "not saved" */
+
+ switch (reg)
+ {
+ case UNW_X86_EIP: loc = c->dwarf.loc[EIP]; break;
+ case UNW_X86_CFA: break;
+ case UNW_X86_EAX: loc = c->dwarf.loc[EAX]; break;
+ case UNW_X86_ECX: loc = c->dwarf.loc[ECX]; break;
+ case UNW_X86_EDX: loc = c->dwarf.loc[EDX]; break;
+ case UNW_X86_EBX: loc = c->dwarf.loc[EBX]; break;
+ case UNW_X86_ESP: loc = c->dwarf.loc[ESP]; break;
+ case UNW_X86_EBP: loc = c->dwarf.loc[EBP]; break;
+ case UNW_X86_ESI: loc = c->dwarf.loc[ESI]; break;
+ case UNW_X86_EDI: loc = c->dwarf.loc[EDI]; break;
+ case UNW_X86_EFLAGS: loc = c->dwarf.loc[EFLAGS]; break;
+ case UNW_X86_TRAPNO: loc = c->dwarf.loc[TRAPNO]; break;
+ case UNW_X86_ST0: loc = c->dwarf.loc[ST0]; break;
+
+ case UNW_X86_FCW:
+ case UNW_X86_FSW:
+ case UNW_X86_FTW:
+ case UNW_X86_FOP:
+ case UNW_X86_FCS:
+ case UNW_X86_FIP:
+ case UNW_X86_FEA:
+ case UNW_X86_FDS:
+ case UNW_X86_MXCSR:
+ case UNW_X86_GS:
+ case UNW_X86_FS:
+ case UNW_X86_ES:
+ case UNW_X86_DS:
+ case UNW_X86_SS:
+ case UNW_X86_CS:
+ case UNW_X86_TSS:
+ case UNW_X86_LDT:
+ loc = x86_scratch_loc (c, reg);
+ break;
+
+ /* stacked fp registers */
+ case UNW_X86_ST1:
+ case UNW_X86_ST2:
+ case UNW_X86_ST3:
+ case UNW_X86_ST4:
+ case UNW_X86_ST5:
+ case UNW_X86_ST6:
+ case UNW_X86_ST7:
+ /* SSE fp registers */
+ case UNW_X86_XMM0_lo:
+ case UNW_X86_XMM0_hi:
+ case UNW_X86_XMM1_lo:
+ case UNW_X86_XMM1_hi:
+ case UNW_X86_XMM2_lo:
+ case UNW_X86_XMM2_hi:
+ case UNW_X86_XMM3_lo:
+ case UNW_X86_XMM3_hi:
+ case UNW_X86_XMM4_lo:
+ case UNW_X86_XMM4_hi:
+ case UNW_X86_XMM5_lo:
+ case UNW_X86_XMM5_hi:
+ case UNW_X86_XMM6_lo:
+ case UNW_X86_XMM6_hi:
+ case UNW_X86_XMM7_lo:
+ case UNW_X86_XMM7_hi:
+ case UNW_X86_XMM0:
+ case UNW_X86_XMM1:
+ case UNW_X86_XMM2:
+ case UNW_X86_XMM3:
+ case UNW_X86_XMM4:
+ case UNW_X86_XMM5:
+ case UNW_X86_XMM6:
+ case UNW_X86_XMM7:
+ loc = x86_scratch_loc (c, reg);
+ break;
+
+ default:
+ break;
+ }
+
+ memset (sloc, 0, sizeof (*sloc));
+
+ if (DWARF_IS_NULL_LOC (loc))
+ {
+ sloc->type = UNW_SLT_NONE;
+ return 0;
+ }
+
+#if !defined(UNW_LOCAL_ONLY)
+ if (DWARF_IS_REG_LOC (loc))
+ {
+ sloc->type = UNW_SLT_REG;
+ sloc->u.regnum = DWARF_GET_LOC (loc);
+ }
+ else
+#endif
+ {
+ sloc->type = UNW_SLT_MEMORY;
+ sloc->u.addr = DWARF_GET_LOC (loc);
+ }
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/x86/Gglobal.c b/src/pal/src/libunwind/src/x86/Gglobal.c
new file mode 100644
index 0000000000..132b824994
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Gglobal.c
@@ -0,0 +1,67 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "dwarf_i.h"
+
+HIDDEN define_lock (x86_lock);
+HIDDEN int tdep_init_done;
+
+/* See comments for svr4_dbx_register_map[] in gcc/config/i386/i386.c. */
+
+HIDDEN const uint8_t dwarf_to_unw_regnum_map[19] =
+ {
+ UNW_X86_EAX, UNW_X86_ECX, UNW_X86_EDX, UNW_X86_EBX,
+ UNW_X86_ESP, UNW_X86_EBP, UNW_X86_ESI, UNW_X86_EDI,
+ UNW_X86_EIP, UNW_X86_EFLAGS, UNW_X86_TRAPNO,
+ UNW_X86_ST0, UNW_X86_ST1, UNW_X86_ST2, UNW_X86_ST3,
+ UNW_X86_ST4, UNW_X86_ST5, UNW_X86_ST6, UNW_X86_ST7
+ };
+
+HIDDEN void
+tdep_init (void)
+{
+ intrmask_t saved_mask;
+
+ sigfillset (&unwi_full_mask);
+
+ lock_acquire (&x86_lock, saved_mask);
+ {
+ if (tdep_init_done)
+ /* another thread else beat us to it... */
+ goto out;
+
+ mi_init ();
+
+ dwarf_init ();
+
+#ifndef UNW_REMOTE_ONLY
+ x86_local_addr_space_init ();
+#endif
+ tdep_init_done = 1; /* signal that we're initialized... */
+ }
+ out:
+ lock_release (&x86_lock, saved_mask);
+}
diff --git a/src/pal/src/libunwind/src/x86/Ginit.c b/src/pal/src/libunwind/src/x86/Ginit.c
new file mode 100644
index 0000000000..f6b8dc27d4
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Ginit.c
@@ -0,0 +1,243 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002 Hewlett-Packard Co
+ Copyright (C) 2007 David Mosberger-Tang
+ Contributed by David Mosberger-Tang <dmosberger@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "unwind_i.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+/* unw_local_addr_space is a NULL pointer in this case. */
+unw_addr_space_t unw_local_addr_space;
+
+#else /* !UNW_REMOTE_ONLY */
+
+static struct unw_addr_space local_addr_space;
+
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
+
+# ifdef UNW_LOCAL_ONLY
+
+HIDDEN void *
+tdep_uc_addr (ucontext_t *uc, int reg)
+{
+ return x86_r_uc_addr (uc, reg);
+}
+
+# endif /* UNW_LOCAL_ONLY */
+
+HIDDEN unw_dyn_info_list_t _U_dyn_info_list;
+
+/* XXX fix me: there is currently no way to locate the dyn-info list
+ by a remote unwinder. On ia64, this is done via a special
+ unwind-table entry. Perhaps something similar can be done with
+ DWARF2 unwind info. */
+
+static void
+put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
+{
+ /* it's a no-op */
+}
+
+static int
+get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
+ void *arg)
+{
+ *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list;
+ return 0;
+}
+
+#define PAGE_SIZE 4096
+#define PAGE_START(a) ((a) & ~(PAGE_SIZE-1))
+
+/* Cache of already validated addresses */
+#define NLGA 4
+static unw_word_t last_good_addr[NLGA];
+static int lga_victim;
+
+static int
+validate_mem (unw_word_t addr)
+{
+ int i, victim;
+#ifdef HAVE_MINCORE
+ unsigned char mvec[2]; /* Unaligned access may cross page boundary */
+#endif
+ size_t len;
+
+ if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr))
+ len = PAGE_SIZE;
+ else
+ len = PAGE_SIZE * 2;
+
+ addr = PAGE_START(addr);
+
+ if (addr == 0)
+ return -1;
+
+ for (i = 0; i < NLGA; i++)
+ {
+ if (last_good_addr[i] && (addr == last_good_addr[i]))
+ return 0;
+ }
+
+#ifdef HAVE_MINCORE
+ if (mincore ((void *) addr, len, mvec) == -1)
+#else
+ if (msync ((void *) addr, len, MS_ASYNC) == -1)
+#endif
+ return -1;
+
+ victim = lga_victim;
+ for (i = 0; i < NLGA; i++) {
+ if (!last_good_addr[victim]) {
+ last_good_addr[victim++] = addr;
+ return 0;
+ }
+ victim = (victim + 1) % NLGA;
+ }
+
+ /* All slots full. Evict the victim. */
+ last_good_addr[victim] = addr;
+ victim = (victim + 1) % NLGA;
+ lga_victim = victim;
+
+ return 0;
+}
+
+static int
+access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
+ void *arg)
+{
+ if (write)
+ {
+ Debug (16, "mem[%x] <- %x\n", addr, *val);
+ *(unw_word_t *) addr = *val;
+ }
+ else
+ {
+ /* validate address */
+ const struct cursor *c = (const struct cursor *)arg;
+ if (c && c->validate && validate_mem(addr))
+ return -1;
+ *val = *(unw_word_t *) addr;
+ Debug (16, "mem[%x] -> %x\n", addr, *val);
+ }
+ return 0;
+}
+
+static int
+access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
+ void *arg)
+{
+ unw_word_t *addr;
+ ucontext_t *uc = ((struct cursor *)arg)->uc;
+
+ if (unw_is_fpreg (reg))
+ goto badreg;
+
+ if (!(addr = x86_r_uc_addr (uc, reg)))
+ goto badreg;
+
+ if (write)
+ {
+ *(unw_word_t *) addr = *val;
+ Debug (12, "%s <- %x\n", unw_regname (reg), *val);
+ }
+ else
+ {
+ *val = *(unw_word_t *) addr;
+ Debug (12, "%s -> %x\n", unw_regname (reg), *val);
+ }
+ return 0;
+
+ badreg:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+}
+
+static int
+access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
+ int write, void *arg)
+{
+ ucontext_t *uc = ((struct cursor *)arg)->uc;
+ unw_fpreg_t *addr;
+
+ if (!unw_is_fpreg (reg))
+ goto badreg;
+
+ if (!(addr = x86_r_uc_addr (uc, reg)))
+ goto badreg;
+
+ if (write)
+ {
+ Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg),
+ ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
+ *(unw_fpreg_t *) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_fpreg_t *) addr;
+ Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg),
+ ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
+ }
+ return 0;
+
+ badreg:
+ Debug (1, "bad register number %u\n", reg);
+ /* attempt to access a non-preserved register */
+ return -UNW_EBADREG;
+}
+
+static int
+get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
+ char *buf, size_t buf_len, unw_word_t *offp,
+ void *arg)
+{
+ return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
+}
+
+HIDDEN void
+x86_local_addr_space_init (void)
+{
+ memset (&local_addr_space, 0, sizeof (local_addr_space));
+ local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
+ local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
+ local_addr_space.acc.put_unwind_info = put_unwind_info;
+ local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
+ local_addr_space.acc.access_mem = access_mem;
+ local_addr_space.acc.access_reg = access_reg;
+ local_addr_space.acc.access_fpreg = access_fpreg;
+ local_addr_space.acc.resume = x86_local_resume;
+ local_addr_space.acc.get_proc_name = get_static_proc_name;
+ unw_flush_cache (&local_addr_space, 0, 0);
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/x86/Ginit_local.c b/src/pal/src/libunwind/src/x86/Ginit_local.c
new file mode 100644
index 0000000000..bff068704d
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Ginit_local.c
@@ -0,0 +1,79 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "init.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+int
+unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+{
+ return -UNW_EINVAL;
+}
+
+#else /* !UNW_REMOTE_ONLY */
+
+static int
+unw_init_local_common(unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->dwarf.as = unw_local_addr_space;
+ c->dwarf.as_arg = c;
+ c->uc = uc;
+ c->validate = 0;
+ return common_init (c, use_prev_instr);
+}
+
+int
+unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+{
+ return unw_init_local_common(cursor, uc, 1);
+}
+
+int
+unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
+{
+ if (!flag)
+ {
+ return unw_init_local_common(cursor, uc, 1);
+ }
+ else if (flag == UNW_INIT_SIGNAL_FRAME)
+ {
+ return unw_init_local_common(cursor, uc, 0);
+ }
+ else
+ {
+ return -UNW_EINVAL;
+ }
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/x86/Ginit_remote.c b/src/pal/src/libunwind/src/x86/Ginit_remote.c
new file mode 100644
index 0000000000..7c15096e4f
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Ginit_remote.c
@@ -0,0 +1,56 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "init.h"
+#include "unwind_i.h"
+
+int
+unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
+{
+#ifdef UNW_LOCAL_ONLY
+ return -UNW_EINVAL;
+#else /* !UNW_LOCAL_ONLY */
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->dwarf.as = as;
+ c->dwarf.as_arg = as_arg;
+ if (as == unw_local_addr_space)
+ {
+ c->dwarf.as_arg = c;
+ c->uc = as_arg;
+ }
+ else
+ {
+ c->dwarf.as_arg = as_arg;
+ c->uc = 0;
+ }
+ return common_init (c, 0);
+#endif /* !UNW_LOCAL_ONLY */
+}
diff --git a/src/pal/src/libunwind/src/x86/Gos-freebsd.c b/src/pal/src/libunwind/src/x86/Gos-freebsd.c
new file mode 100644
index 0000000000..7dd0140463
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Gos-freebsd.c
@@ -0,0 +1,374 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <signal.h>
+#include <stddef.h>
+#include <ucontext.h>
+#include <machine/sigframe.h>
+
+#include "unwind_i.h"
+#include "offsets.h"
+
+int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ unw_word_t w0, w1, w2, w3, w4, w5, ip;
+ unw_addr_space_t as;
+ unw_accessors_t *a;
+ void *arg;
+ int ret;
+
+ as = c->dwarf.as;
+ a = unw_get_accessors_int (as);
+ arg = c->dwarf.as_arg;
+
+ /* Check if EIP points at sigreturn() sequence. It can be:
+sigcode+4: from amd64 freebsd32 environment
+8d 44 24 20 lea 0x20(%esp),%eax
+50 push %eax
+b8 a1 01 00 00 mov $0x1a1,%eax
+50 push %eax
+cd 80 int $0x80
+
+sigcode+4: from real i386
+8d 44 24 20 lea 0x20(%esp),%eax
+50 push %eax
+f7 40 54 00 02 00 testl $0x20000,0x54(%eax)
+75 03 jne sigcode+21
+8e 68 14 mov 0x14(%eax),%gs
+b8 a1 01 00 00 mov $0x1a1,%eax
+50 push %eax
+cd 80 int $0x80
+
+freebsd4_sigcode+4:
+XXX
+osigcode:
+XXX
+ */
+ ip = c->dwarf.ip;
+ ret = X86_SCF_NONE;
+ c->sigcontext_format = ret;
+ if ((*a->access_mem) (as, ip, &w0, 0, arg) < 0 ||
+ (*a->access_mem) (as, ip + 4, &w1, 0, arg) < 0 ||
+ (*a->access_mem) (as, ip + 8, &w2, 0, arg) < 0 ||
+ (*a->access_mem) (as, ip + 12, &w3, 0, arg) < 0)
+ return ret;
+ if (w0 == 0x2024448d && w1 == 0x01a1b850 && w2 == 0xcd500000 &&
+ (w3 & 0xff) == 0x80)
+ ret = X86_SCF_FREEBSD_SIGFRAME;
+ else {
+ if ((*a->access_mem) (as, ip + 16, &w4, 0, arg) < 0 ||
+ (*a->access_mem) (as, ip + 20, &w5, 0, arg) < 0)
+ return ret;
+ if (w0 == 0x2024448d && w1 == 0x5440f750 && w2 == 0x75000200 &&
+ w3 == 0x14688e03 && w4 == 0x0001a1b8 && w5 == 0x80cd5000)
+ ret = X86_SCF_FREEBSD_SIGFRAME;
+ }
+
+ /* Check for syscall */
+ if (ret == X86_SCF_NONE && (*a->access_mem) (as, ip - 2, &w0, 0, arg) >= 0 &&
+ (w0 & 0xffff) == 0x80cd)
+ ret = X86_SCF_FREEBSD_SYSCALL;
+ Debug (16, "returning %d\n", ret);
+ c->sigcontext_format = ret;
+ return (ret);
+}
+
+HIDDEN int
+x86_handle_signal_frame (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ if (c->sigcontext_format == X86_SCF_FREEBSD_SIGFRAME) {
+ struct sigframe *sf;
+ uintptr_t uc_addr;
+ struct dwarf_loc esp_loc;
+
+ sf = (struct sigframe *)c->dwarf.cfa;
+ uc_addr = (uintptr_t)&(sf->sf_uc);
+ c->sigcontext_addr = c->dwarf.cfa;
+
+ esp_loc = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESP_OFF, 0);
+ ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa);
+ if (ret < 0)
+ {
+ Debug (2, "returning 0\n");
+ return 0;
+ }
+
+ c->dwarf.loc[EIP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EIP_OFF, 0);
+ c->dwarf.loc[ESP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESP_OFF, 0);
+ c->dwarf.loc[EAX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EAX_OFF, 0);
+ c->dwarf.loc[ECX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ECX_OFF, 0);
+ c->dwarf.loc[EDX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EDX_OFF, 0);
+ c->dwarf.loc[EBX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EBX_OFF, 0);
+ c->dwarf.loc[EBP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EBP_OFF, 0);
+ c->dwarf.loc[ESI] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESI_OFF, 0);
+ c->dwarf.loc[EDI] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EDI_OFF, 0);
+ c->dwarf.loc[EFLAGS] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EFLAGS_OFF, 0);
+ c->dwarf.loc[TRAPNO] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_TRAPNO_OFF, 0);
+ c->dwarf.loc[ST0] = DWARF_NULL_LOC;
+ } else if (c->sigcontext_format == X86_SCF_FREEBSD_SYSCALL) {
+ c->dwarf.loc[EIP] = DWARF_LOC (c->dwarf.cfa, 0);
+ c->dwarf.loc[EAX] = DWARF_NULL_LOC;
+ c->dwarf.cfa += 4;
+ c->dwarf.use_prev_instr = 1;
+ } else {
+ Debug (8, "Gstep: not handling frame format %d\n", c->sigcontext_format);
+ abort();
+ }
+ return 0;
+}
+
+HIDDEN dwarf_loc_t
+x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg)
+{
+ unw_word_t addr = c->sigcontext_addr, off, xmm_off;
+ unw_word_t fpstate, fpformat;
+ int ret, is_fpstate = 0, is_xmmstate = 0;
+
+ switch (c->sigcontext_format)
+ {
+ case X86_SCF_NONE:
+ return DWARF_REG_LOC (&c->dwarf, reg);
+
+ case X86_SCF_FREEBSD_SIGFRAME:
+ addr += offsetof(struct sigframe, sf_uc) + FREEBSD_UC_MCONTEXT_OFF;
+ break;
+
+ case X86_SCF_FREEBSD_SIGFRAME4:
+ abort();
+ break;
+
+ case X86_SCF_FREEBSD_OSIGFRAME:
+ /* XXXKIB */
+ abort();
+ break;
+
+ case X86_SCF_FREEBSD_SYSCALL:
+ /* XXXKIB */
+ abort();
+ break;
+
+ default:
+ /* XXXKIB */
+ abort();
+ break;
+ }
+
+ off = 0; /* shut gcc warning */
+ switch (reg)
+ {
+ case UNW_X86_GS: off = FREEBSD_UC_MCONTEXT_GS_OFF; break;
+ case UNW_X86_FS: off = FREEBSD_UC_MCONTEXT_FS_OFF; break;
+ case UNW_X86_ES: off = FREEBSD_UC_MCONTEXT_ES_OFF; break;
+ case UNW_X86_DS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break;
+ case UNW_X86_EDI: off = FREEBSD_UC_MCONTEXT_EDI_OFF; break;
+ case UNW_X86_ESI: off = FREEBSD_UC_MCONTEXT_ESI_OFF; break;
+ case UNW_X86_EBP: off = FREEBSD_UC_MCONTEXT_EBP_OFF; break;
+ case UNW_X86_ESP: off = FREEBSD_UC_MCONTEXT_ESP_OFF; break;
+ case UNW_X86_EBX: off = FREEBSD_UC_MCONTEXT_EBX_OFF; break;
+ case UNW_X86_EDX: off = FREEBSD_UC_MCONTEXT_EDX_OFF; break;
+ case UNW_X86_ECX: off = FREEBSD_UC_MCONTEXT_ECX_OFF; break;
+ case UNW_X86_EAX: off = FREEBSD_UC_MCONTEXT_EAX_OFF; break;
+ case UNW_X86_TRAPNO: off = FREEBSD_UC_MCONTEXT_TRAPNO_OFF; break;
+ case UNW_X86_EIP: off = FREEBSD_UC_MCONTEXT_EIP_OFF; break;
+ case UNW_X86_CS: off = FREEBSD_UC_MCONTEXT_CS_OFF; break;
+ case UNW_X86_EFLAGS: off = FREEBSD_UC_MCONTEXT_EFLAGS_OFF; break;
+ case UNW_X86_SS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break;
+
+ case UNW_X86_FCW:
+ is_fpstate = 1;
+ off = FREEBSD_UC_MCONTEXT_CW_OFF;
+ xmm_off = FREEBSD_UC_MCONTEXT_CW_XMM_OFF;
+ break;
+ case UNW_X86_FSW:
+ is_fpstate = 1;
+ off = FREEBSD_UC_MCONTEXT_SW_OFF;
+ xmm_off = FREEBSD_UC_MCONTEXT_SW_XMM_OFF;
+ break;
+ case UNW_X86_FTW:
+ is_fpstate = 1;
+ xmm_off = FREEBSD_UC_MCONTEXT_TAG_XMM_OFF;
+ off = FREEBSD_UC_MCONTEXT_TAG_OFF;
+ break;
+ case UNW_X86_FCS:
+ is_fpstate = 1;
+ off = FREEBSD_UC_MCONTEXT_CSSEL_OFF;
+ xmm_off = FREEBSD_UC_MCONTEXT_CSSEL_XMM_OFF;
+ break;
+ case UNW_X86_FIP:
+ is_fpstate = 1;
+ off = FREEBSD_UC_MCONTEXT_IPOFF_OFF;
+ xmm_off = FREEBSD_UC_MCONTEXT_IPOFF_XMM_OFF;
+ break;
+ case UNW_X86_FEA:
+ is_fpstate = 1;
+ off = FREEBSD_UC_MCONTEXT_DATAOFF_OFF;
+ xmm_off = FREEBSD_UC_MCONTEXT_DATAOFF_XMM_OFF;
+ break;
+ case UNW_X86_FDS:
+ is_fpstate = 1;
+ off = FREEBSD_US_MCONTEXT_DATASEL_OFF;
+ xmm_off = FREEBSD_US_MCONTEXT_DATASEL_XMM_OFF;
+ break;
+ case UNW_X86_MXCSR:
+ is_fpstate = 1;
+ is_xmmstate = 1;
+ xmm_off = FREEBSD_UC_MCONTEXT_MXCSR_XMM_OFF;
+ break;
+
+ /* stacked fp registers */
+ case UNW_X86_ST0: case UNW_X86_ST1: case UNW_X86_ST2: case UNW_X86_ST3:
+ case UNW_X86_ST4: case UNW_X86_ST5: case UNW_X86_ST6: case UNW_X86_ST7:
+ is_fpstate = 1;
+ off = FREEBSD_UC_MCONTEXT_ST0_OFF + 10*(reg - UNW_X86_ST0);
+ xmm_off = FREEBSD_UC_MCONTEXT_ST0_XMM_OFF + 10*(reg - UNW_X86_ST0);
+ break;
+
+ /* SSE fp registers */
+ case UNW_X86_XMM0_lo: case UNW_X86_XMM0_hi:
+ case UNW_X86_XMM1_lo: case UNW_X86_XMM1_hi:
+ case UNW_X86_XMM2_lo: case UNW_X86_XMM2_hi:
+ case UNW_X86_XMM3_lo: case UNW_X86_XMM3_hi:
+ case UNW_X86_XMM4_lo: case UNW_X86_XMM4_hi:
+ case UNW_X86_XMM5_lo: case UNW_X86_XMM5_hi:
+ case UNW_X86_XMM6_lo: case UNW_X86_XMM6_hi:
+ case UNW_X86_XMM7_lo: case UNW_X86_XMM7_hi:
+ is_fpstate = 1;
+ is_xmmstate = 1;
+ xmm_off = FREEBSD_UC_MCONTEXT_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo);
+ break;
+ case UNW_X86_XMM0:
+ case UNW_X86_XMM1:
+ case UNW_X86_XMM2:
+ case UNW_X86_XMM3:
+ case UNW_X86_XMM4:
+ case UNW_X86_XMM5:
+ case UNW_X86_XMM6:
+ case UNW_X86_XMM7:
+ is_fpstate = 1;
+ is_xmmstate = 1;
+ xmm_off = FREEBSD_UC_MCONTEXT_XMM0_OFF + 16*(reg - UNW_X86_XMM0);
+ break;
+
+ case UNW_X86_FOP:
+ case UNW_X86_TSS:
+ case UNW_X86_LDT:
+ default:
+ return DWARF_REG_LOC (&c->dwarf, reg);
+ }
+
+ if (is_fpstate)
+ {
+ if ((ret = dwarf_get (&c->dwarf,
+ DWARF_MEM_LOC (&c->dwarf, addr + FREEBSD_UC_MCONTEXT_FPSTATE_OFF),
+ &fpstate)) < 0)
+ return DWARF_NULL_LOC;
+ if (fpstate == FREEBSD_UC_MCONTEXT_FPOWNED_NONE)
+ return DWARF_NULL_LOC;
+ if ((ret = dwarf_get (&c->dwarf,
+ DWARF_MEM_LOC (&c->dwarf, addr + FREEBSD_UC_MCONTEXT_FPFORMAT_OFF),
+ &fpformat)) < 0)
+ return DWARF_NULL_LOC;
+ if (fpformat == FREEBSD_UC_MCONTEXT_FPFMT_NODEV ||
+ (is_xmmstate && fpformat != FREEBSD_UC_MCONTEXT_FPFMT_XMM))
+ return DWARF_NULL_LOC;
+ if (is_xmmstate)
+ off = xmm_off;
+ }
+
+ return DWARF_MEM_LOC (c, addr + off);
+}
+
+#ifndef UNW_REMOTE_ONLY
+HIDDEN void *
+x86_r_uc_addr (ucontext_t *uc, int reg)
+{
+ void *addr;
+
+ switch (reg)
+ {
+ case UNW_X86_GS: addr = &uc->uc_mcontext.mc_gs; break;
+ case UNW_X86_FS: addr = &uc->uc_mcontext.mc_fs; break;
+ case UNW_X86_ES: addr = &uc->uc_mcontext.mc_es; break;
+ case UNW_X86_DS: addr = &uc->uc_mcontext.mc_ds; break;
+ case UNW_X86_EAX: addr = &uc->uc_mcontext.mc_eax; break;
+ case UNW_X86_EBX: addr = &uc->uc_mcontext.mc_ebx; break;
+ case UNW_X86_ECX: addr = &uc->uc_mcontext.mc_ecx; break;
+ case UNW_X86_EDX: addr = &uc->uc_mcontext.mc_edx; break;
+ case UNW_X86_ESI: addr = &uc->uc_mcontext.mc_esi; break;
+ case UNW_X86_EDI: addr = &uc->uc_mcontext.mc_edi; break;
+ case UNW_X86_EBP: addr = &uc->uc_mcontext.mc_ebp; break;
+ case UNW_X86_EIP: addr = &uc->uc_mcontext.mc_eip; break;
+ case UNW_X86_ESP: addr = &uc->uc_mcontext.mc_esp; break;
+ case UNW_X86_TRAPNO: addr = &uc->uc_mcontext.mc_trapno; break;
+ case UNW_X86_CS: addr = &uc->uc_mcontext.mc_cs; break;
+ case UNW_X86_EFLAGS: addr = &uc->uc_mcontext.mc_eflags; break;
+ case UNW_X86_SS: addr = &uc->uc_mcontext.mc_ss; break;
+
+ default:
+ addr = NULL;
+ }
+ return addr;
+}
+
+HIDDEN int
+x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ ucontext_t *uc = c->uc;
+
+ /* Ensure c->pi is up-to-date. On x86, it's relatively common to be
+ missing DWARF unwind info. We don't want to fail in that case,
+ because the frame-chain still would let us do a backtrace at
+ least. */
+ dwarf_make_proc_info (&c->dwarf);
+
+ if (c->sigcontext_format == X86_SCF_NONE) {
+ Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip);
+ setcontext (uc);
+ abort();
+ } else if (c->sigcontext_format == X86_SCF_FREEBSD_SIGFRAME) {
+ struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
+
+ Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc);
+ sigreturn((ucontext_t *)((const char *)sc + FREEBSD_SC_UCONTEXT_OFF));
+ abort();
+ } else {
+ Debug (8, "resuming at ip=%x for sigcontext format %d not implemented\n",
+ c->dwarf.ip, c->sigcontext_format);
+ abort();
+ }
+ return -UNW_EINVAL;
+}
+
+#endif
diff --git a/src/pal/src/libunwind/src/x86/Gos-linux.c b/src/pal/src/libunwind/src/x86/Gos-linux.c
new file mode 100644
index 0000000000..fb9a5e3461
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Gos-linux.c
@@ -0,0 +1,331 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "offsets.h"
+
+#include <sys/syscall.h>
+
+int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ unw_word_t w0, w1, ip;
+ unw_addr_space_t as;
+ unw_accessors_t *a;
+ void *arg;
+ int ret;
+
+ as = c->dwarf.as;
+ a = unw_get_accessors_int (as);
+ arg = c->dwarf.as_arg;
+
+ /* Check if EIP points at sigreturn() sequence. On Linux, this is:
+
+ __restore:
+ 0x58 pop %eax
+ 0xb8 0x77 0x00 0x00 0x00 movl 0x77,%eax
+ 0xcd 0x80 int 0x80
+
+ without SA_SIGINFO, and
+
+ __restore_rt:
+ 0xb8 0xad 0x00 0x00 0x00 movl 0xad,%eax
+ 0xcd 0x80 int 0x80
+ 0x00
+
+ if SA_SIGINFO is specified.
+ */
+ ip = c->dwarf.ip;
+ if ((*a->access_mem) (as, ip, &w0, 0, arg) < 0
+ || (*a->access_mem) (as, ip + 4, &w1, 0, arg) < 0)
+ ret = 0;
+ else
+ ret = ((w0 == 0x0077b858 && w1 == 0x80cd0000)
+ || (w0 == 0x0000adb8 && (w1 & 0xffffff) == 0x80cd00));
+ Debug (16, "returning %d\n", ret);
+ return ret;
+}
+
+HIDDEN int
+x86_handle_signal_frame (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ /* c->esp points at the arguments to the handler. Without
+ SA_SIGINFO, the arguments consist of a signal number
+ followed by a struct sigcontext. With SA_SIGINFO, the
+ arguments consist a signal number, a siginfo *, and a
+ ucontext *. */
+ unw_word_t sc_addr;
+ unw_word_t siginfo_ptr_addr = c->dwarf.cfa + 4;
+ unw_word_t sigcontext_ptr_addr = c->dwarf.cfa + 8;
+ unw_word_t siginfo_ptr, sigcontext_ptr;
+ struct dwarf_loc esp_loc, siginfo_ptr_loc, sigcontext_ptr_loc;
+
+ siginfo_ptr_loc = DWARF_LOC (siginfo_ptr_addr, 0);
+ sigcontext_ptr_loc = DWARF_LOC (sigcontext_ptr_addr, 0);
+ ret = (dwarf_get (&c->dwarf, siginfo_ptr_loc, &siginfo_ptr)
+ | dwarf_get (&c->dwarf, sigcontext_ptr_loc, &sigcontext_ptr));
+ if (ret < 0)
+ {
+ Debug (2, "returning 0\n");
+ return 0;
+ }
+ if (siginfo_ptr < c->dwarf.cfa
+ || siginfo_ptr > c->dwarf.cfa + 256
+ || sigcontext_ptr < c->dwarf.cfa
+ || sigcontext_ptr > c->dwarf.cfa + 256)
+ {
+ /* Not plausible for SA_SIGINFO signal */
+ c->sigcontext_format = X86_SCF_LINUX_SIGFRAME;
+ c->sigcontext_addr = sc_addr = c->dwarf.cfa + 4;
+ }
+ else
+ {
+ /* If SA_SIGINFO were not specified, we actually read
+ various segment pointers instead. We believe that at
+ least fs and _fsh are always zero for linux, so it is
+ not just unlikely, but impossible that we would end
+ up here. */
+ c->sigcontext_format = X86_SCF_LINUX_RT_SIGFRAME;
+ c->sigcontext_addr = sigcontext_ptr;
+ sc_addr = sigcontext_ptr + LINUX_UC_MCONTEXT_OFF;
+ }
+ esp_loc = DWARF_LOC (sc_addr + LINUX_SC_ESP_OFF, 0);
+ ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa);
+ if (ret < 0)
+ {
+ Debug (2, "returning 0\n");
+ return 0;
+ }
+
+ c->dwarf.loc[EAX] = DWARF_LOC (sc_addr + LINUX_SC_EAX_OFF, 0);
+ c->dwarf.loc[ECX] = DWARF_LOC (sc_addr + LINUX_SC_ECX_OFF, 0);
+ c->dwarf.loc[EDX] = DWARF_LOC (sc_addr + LINUX_SC_EDX_OFF, 0);
+ c->dwarf.loc[EBX] = DWARF_LOC (sc_addr + LINUX_SC_EBX_OFF, 0);
+ c->dwarf.loc[EBP] = DWARF_LOC (sc_addr + LINUX_SC_EBP_OFF, 0);
+ c->dwarf.loc[ESI] = DWARF_LOC (sc_addr + LINUX_SC_ESI_OFF, 0);
+ c->dwarf.loc[EDI] = DWARF_LOC (sc_addr + LINUX_SC_EDI_OFF, 0);
+ c->dwarf.loc[EFLAGS] = DWARF_NULL_LOC;
+ c->dwarf.loc[TRAPNO] = DWARF_NULL_LOC;
+ c->dwarf.loc[ST0] = DWARF_NULL_LOC;
+ c->dwarf.loc[EIP] = DWARF_LOC (sc_addr + LINUX_SC_EIP_OFF, 0);
+ c->dwarf.loc[ESP] = DWARF_LOC (sc_addr + LINUX_SC_ESP_OFF, 0);
+
+ return 0;
+}
+
+HIDDEN dwarf_loc_t
+x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg)
+{
+ unw_word_t addr = c->sigcontext_addr, fpstate_addr, off;
+ int ret, is_fpstate = 0;
+
+ switch (c->sigcontext_format)
+ {
+ case X86_SCF_NONE:
+ return DWARF_REG_LOC (&c->dwarf, reg);
+
+ case X86_SCF_LINUX_SIGFRAME:
+ break;
+
+ case X86_SCF_LINUX_RT_SIGFRAME:
+ addr += LINUX_UC_MCONTEXT_OFF;
+ break;
+
+ default:
+ return DWARF_NULL_LOC;
+ }
+
+ switch (reg)
+ {
+ case UNW_X86_GS: off = LINUX_SC_GS_OFF; break;
+ case UNW_X86_FS: off = LINUX_SC_FS_OFF; break;
+ case UNW_X86_ES: off = LINUX_SC_ES_OFF; break;
+ case UNW_X86_DS: off = LINUX_SC_DS_OFF; break;
+ case UNW_X86_EDI: off = LINUX_SC_EDI_OFF; break;
+ case UNW_X86_ESI: off = LINUX_SC_ESI_OFF; break;
+ case UNW_X86_EBP: off = LINUX_SC_EBP_OFF; break;
+ case UNW_X86_ESP: off = LINUX_SC_ESP_OFF; break;
+ case UNW_X86_EBX: off = LINUX_SC_EBX_OFF; break;
+ case UNW_X86_EDX: off = LINUX_SC_EDX_OFF; break;
+ case UNW_X86_ECX: off = LINUX_SC_ECX_OFF; break;
+ case UNW_X86_EAX: off = LINUX_SC_EAX_OFF; break;
+ case UNW_X86_TRAPNO: off = LINUX_SC_TRAPNO_OFF; break;
+ case UNW_X86_EIP: off = LINUX_SC_EIP_OFF; break;
+ case UNW_X86_CS: off = LINUX_SC_CS_OFF; break;
+ case UNW_X86_EFLAGS: off = LINUX_SC_EFLAGS_OFF; break;
+ case UNW_X86_SS: off = LINUX_SC_SS_OFF; break;
+
+ /* The following is probably not correct for all possible cases.
+ Somebody who understands this better should review this for
+ correctness. */
+
+ case UNW_X86_FCW: is_fpstate = 1; off = LINUX_FPSTATE_CW_OFF; break;
+ case UNW_X86_FSW: is_fpstate = 1; off = LINUX_FPSTATE_SW_OFF; break;
+ case UNW_X86_FTW: is_fpstate = 1; off = LINUX_FPSTATE_TAG_OFF; break;
+ case UNW_X86_FCS: is_fpstate = 1; off = LINUX_FPSTATE_CSSEL_OFF; break;
+ case UNW_X86_FIP: is_fpstate = 1; off = LINUX_FPSTATE_IPOFF_OFF; break;
+ case UNW_X86_FEA: is_fpstate = 1; off = LINUX_FPSTATE_DATAOFF_OFF; break;
+ case UNW_X86_FDS: is_fpstate = 1; off = LINUX_FPSTATE_DATASEL_OFF; break;
+ case UNW_X86_MXCSR: is_fpstate = 1; off = LINUX_FPSTATE_MXCSR_OFF; break;
+
+ /* stacked fp registers */
+ case UNW_X86_ST0: case UNW_X86_ST1: case UNW_X86_ST2: case UNW_X86_ST3:
+ case UNW_X86_ST4: case UNW_X86_ST5: case UNW_X86_ST6: case UNW_X86_ST7:
+ is_fpstate = 1;
+ off = LINUX_FPSTATE_ST0_OFF + 10*(reg - UNW_X86_ST0);
+ break;
+
+ /* SSE fp registers */
+ case UNW_X86_XMM0_lo: case UNW_X86_XMM0_hi:
+ case UNW_X86_XMM1_lo: case UNW_X86_XMM1_hi:
+ case UNW_X86_XMM2_lo: case UNW_X86_XMM2_hi:
+ case UNW_X86_XMM3_lo: case UNW_X86_XMM3_hi:
+ case UNW_X86_XMM4_lo: case UNW_X86_XMM4_hi:
+ case UNW_X86_XMM5_lo: case UNW_X86_XMM5_hi:
+ case UNW_X86_XMM6_lo: case UNW_X86_XMM6_hi:
+ case UNW_X86_XMM7_lo: case UNW_X86_XMM7_hi:
+ is_fpstate = 1;
+ off = LINUX_FPSTATE_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo);
+ break;
+ case UNW_X86_XMM0:
+ case UNW_X86_XMM1:
+ case UNW_X86_XMM2:
+ case UNW_X86_XMM3:
+ case UNW_X86_XMM4:
+ case UNW_X86_XMM5:
+ case UNW_X86_XMM6:
+ case UNW_X86_XMM7:
+ is_fpstate = 1;
+ off = LINUX_FPSTATE_XMM0_OFF + 16*(reg - UNW_X86_XMM0);
+ break;
+
+ case UNW_X86_FOP:
+ case UNW_X86_TSS:
+ case UNW_X86_LDT:
+ default:
+ return DWARF_REG_LOC (&c->dwarf, reg);
+ }
+
+ if (is_fpstate)
+ {
+ if ((ret = dwarf_get (&c->dwarf,
+ DWARF_MEM_LOC (&c->dwarf,
+ addr + LINUX_SC_FPSTATE_OFF),
+ &fpstate_addr)) < 0)
+ return DWARF_NULL_LOC;
+
+ if (!fpstate_addr)
+ return DWARF_NULL_LOC;
+
+ return DWARF_MEM_LOC (c, fpstate_addr + off);
+ }
+ else
+ return DWARF_MEM_LOC (c, addr + off);
+}
+
+#ifndef UNW_REMOTE_ONLY
+HIDDEN void *
+x86_r_uc_addr (ucontext_t *uc, int reg)
+{
+ void *addr;
+
+ switch (reg)
+ {
+ case UNW_X86_GS: addr = &uc->uc_mcontext.gregs[REG_GS]; break;
+ case UNW_X86_FS: addr = &uc->uc_mcontext.gregs[REG_FS]; break;
+ case UNW_X86_ES: addr = &uc->uc_mcontext.gregs[REG_ES]; break;
+ case UNW_X86_DS: addr = &uc->uc_mcontext.gregs[REG_DS]; break;
+ case UNW_X86_EAX: addr = &uc->uc_mcontext.gregs[REG_EAX]; break;
+ case UNW_X86_EBX: addr = &uc->uc_mcontext.gregs[REG_EBX]; break;
+ case UNW_X86_ECX: addr = &uc->uc_mcontext.gregs[REG_ECX]; break;
+ case UNW_X86_EDX: addr = &uc->uc_mcontext.gregs[REG_EDX]; break;
+ case UNW_X86_ESI: addr = &uc->uc_mcontext.gregs[REG_ESI]; break;
+ case UNW_X86_EDI: addr = &uc->uc_mcontext.gregs[REG_EDI]; break;
+ case UNW_X86_EBP: addr = &uc->uc_mcontext.gregs[REG_EBP]; break;
+ case UNW_X86_EIP: addr = &uc->uc_mcontext.gregs[REG_EIP]; break;
+ case UNW_X86_ESP: addr = &uc->uc_mcontext.gregs[REG_ESP]; break;
+ case UNW_X86_TRAPNO: addr = &uc->uc_mcontext.gregs[REG_TRAPNO]; break;
+ case UNW_X86_CS: addr = &uc->uc_mcontext.gregs[REG_CS]; break;
+ case UNW_X86_EFLAGS: addr = &uc->uc_mcontext.gregs[REG_EFL]; break;
+ case UNW_X86_SS: addr = &uc->uc_mcontext.gregs[REG_SS]; break;
+
+ default:
+ addr = NULL;
+ }
+ return addr;
+}
+
+HIDDEN int
+x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ ucontext_t *uc = c->uc;
+
+ /* Ensure c->pi is up-to-date. On x86, it's relatively common to be
+ missing DWARF unwind info. We don't want to fail in that case,
+ because the frame-chain still would let us do a backtrace at
+ least. */
+ dwarf_make_proc_info (&c->dwarf);
+
+ if (unlikely (c->sigcontext_format != X86_SCF_NONE))
+ {
+ struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
+
+ Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc);
+ x86_sigreturn (sc);
+ }
+ else
+ {
+ Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip);
+ setcontext (uc);
+ }
+ return -UNW_EINVAL;
+}
+
+/* sigreturn() is a no-op on x86 glibc. */
+HIDDEN void
+x86_sigreturn (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
+ mcontext_t *sc_mcontext = &((ucontext_t*)sc)->uc_mcontext;
+ /* Copy in saved uc - all preserved regs are at the start of sigcontext */
+ memcpy(sc_mcontext, &c->uc->uc_mcontext,
+ DWARF_NUM_PRESERVED_REGS * sizeof(unw_word_t));
+
+ Debug (8, "resuming at ip=%llx via sigreturn(%p)\n",
+ (unsigned long long) c->dwarf.ip, sc);
+ __asm__ __volatile__ ("mov %0, %%esp;"
+ "mov %1, %%eax;"
+ "syscall"
+ :: "r"(sc), "i"(SYS_rt_sigreturn)
+ : "memory");
+ abort();
+}
+#endif
diff --git a/src/pal/src/libunwind/src/x86/Greg_states_iterate.c b/src/pal/src/libunwind/src/x86/Greg_states_iterate.c
new file mode 100644
index 0000000000..a17dc1b561
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Greg_states_iterate.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+ unw_reg_states_callback cb, void *token)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
diff --git a/src/pal/src/libunwind/src/x86/Gregs.c b/src/pal/src/libunwind/src/x86/Gregs.c
new file mode 100644
index 0000000000..4a9592617d
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Gregs.c
@@ -0,0 +1,178 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2004 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "offsets.h"
+#include "unwind_i.h"
+
+HIDDEN dwarf_loc_t
+x86_scratch_loc (struct cursor *c, unw_regnum_t reg)
+{
+ if (c->sigcontext_addr)
+ return x86_get_scratch_loc (c, reg);
+ else
+ return DWARF_REG_LOC (&c->dwarf, reg);
+}
+
+HIDDEN int
+tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
+ int write)
+{
+ dwarf_loc_t loc = DWARF_NULL_LOC;
+ unsigned int mask;
+ int arg_num;
+
+ switch (reg)
+ {
+
+ case UNW_X86_EIP:
+ if (write)
+ c->dwarf.ip = *valp; /* also update the EIP cache */
+ loc = c->dwarf.loc[EIP];
+ break;
+
+ case UNW_X86_CFA:
+ case UNW_X86_ESP:
+ if (write)
+ return -UNW_EREADONLYREG;
+ *valp = c->dwarf.cfa;
+ return 0;
+
+ case UNW_X86_EAX:
+ case UNW_X86_EDX:
+ arg_num = reg - UNW_X86_EAX;
+ mask = (1 << arg_num);
+ if (write)
+ {
+ c->dwarf.eh_args[arg_num] = *valp;
+ c->dwarf.eh_valid_mask |= mask;
+ return 0;
+ }
+ else if ((c->dwarf.eh_valid_mask & mask) != 0)
+ {
+ *valp = c->dwarf.eh_args[arg_num];
+ return 0;
+ }
+ else
+ loc = c->dwarf.loc[(reg == UNW_X86_EAX) ? EAX : EDX];
+ break;
+
+ case UNW_X86_ECX: loc = c->dwarf.loc[ECX]; break;
+ case UNW_X86_EBX: loc = c->dwarf.loc[EBX]; break;
+
+ case UNW_X86_EBP: loc = c->dwarf.loc[EBP]; break;
+ case UNW_X86_ESI: loc = c->dwarf.loc[ESI]; break;
+ case UNW_X86_EDI: loc = c->dwarf.loc[EDI]; break;
+ case UNW_X86_EFLAGS: loc = c->dwarf.loc[EFLAGS]; break;
+ case UNW_X86_TRAPNO: loc = c->dwarf.loc[TRAPNO]; break;
+
+ case UNW_X86_FCW:
+ case UNW_X86_FSW:
+ case UNW_X86_FTW:
+ case UNW_X86_FOP:
+ case UNW_X86_FCS:
+ case UNW_X86_FIP:
+ case UNW_X86_FEA:
+ case UNW_X86_FDS:
+ case UNW_X86_MXCSR:
+ case UNW_X86_GS:
+ case UNW_X86_FS:
+ case UNW_X86_ES:
+ case UNW_X86_DS:
+ case UNW_X86_SS:
+ case UNW_X86_CS:
+ case UNW_X86_TSS:
+ case UNW_X86_LDT:
+ loc = x86_scratch_loc (c, reg);
+ break;
+
+ default:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+ }
+
+ if (write)
+ return dwarf_put (&c->dwarf, loc, *valp);
+ else
+ return dwarf_get (&c->dwarf, loc, valp);
+}
+
+HIDDEN int
+tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
+ int write)
+{
+ struct dwarf_loc loc = DWARF_NULL_LOC;
+
+ switch (reg)
+ {
+ case UNW_X86_ST0:
+ loc = c->dwarf.loc[ST0];
+ break;
+
+ /* stacked fp registers */
+ case UNW_X86_ST1:
+ case UNW_X86_ST2:
+ case UNW_X86_ST3:
+ case UNW_X86_ST4:
+ case UNW_X86_ST5:
+ case UNW_X86_ST6:
+ case UNW_X86_ST7:
+ /* SSE fp registers */
+ case UNW_X86_XMM0:
+ case UNW_X86_XMM1:
+ case UNW_X86_XMM2:
+ case UNW_X86_XMM3:
+ case UNW_X86_XMM4:
+ case UNW_X86_XMM5:
+ case UNW_X86_XMM6:
+ case UNW_X86_XMM7:
+ case UNW_X86_XMM0_lo:
+ case UNW_X86_XMM0_hi:
+ case UNW_X86_XMM1_lo:
+ case UNW_X86_XMM1_hi:
+ case UNW_X86_XMM2_lo:
+ case UNW_X86_XMM2_hi:
+ case UNW_X86_XMM3_lo:
+ case UNW_X86_XMM3_hi:
+ case UNW_X86_XMM4_lo:
+ case UNW_X86_XMM4_hi:
+ case UNW_X86_XMM5_lo:
+ case UNW_X86_XMM5_hi:
+ case UNW_X86_XMM6_lo:
+ case UNW_X86_XMM6_hi:
+ case UNW_X86_XMM7_lo:
+ case UNW_X86_XMM7_hi:
+ loc = x86_scratch_loc (c, reg);
+ break;
+
+ default:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+ }
+
+ if (write)
+ return dwarf_putfp (&c->dwarf, loc, *valp);
+ else
+ return dwarf_getfp (&c->dwarf, loc, valp);
+}
diff --git a/src/pal/src/libunwind/src/x86/Gresume.c b/src/pal/src/libunwind/src/x86/Gresume.c
new file mode 100644
index 0000000000..5072c4ba08
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Gresume.c
@@ -0,0 +1,91 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2004 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+
+#include "unwind_i.h"
+#include "offsets.h"
+
+/* This routine is responsible for copying the register values in
+ cursor C and establishing them as the current machine state. */
+
+static inline int
+establish_machine_state (struct cursor *c)
+{
+ int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *,
+ int write, void *);
+ int (*access_fpreg) (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *,
+ int write, void *);
+ unw_addr_space_t as = c->dwarf.as;
+ void *arg = c->dwarf.as_arg;
+ unw_fpreg_t fpval;
+ unw_word_t val;
+ int reg;
+
+ access_reg = as->acc.access_reg;
+ access_fpreg = as->acc.access_fpreg;
+
+ Debug (8, "copying out cursor state\n");
+
+ for (reg = 0; reg <= UNW_REG_LAST; ++reg)
+ {
+ Debug (16, "copying %s %d\n", unw_regname (reg), reg);
+ if (unw_is_fpreg (reg))
+ {
+ if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0)
+ (*access_fpreg) (as, reg, &fpval, 1, arg);
+ }
+ else
+ {
+ if (tdep_access_reg (c, reg, &val, 0) >= 0)
+ (*access_reg) (as, reg, &val, 1, arg);
+ }
+ }
+
+ if (c->dwarf.args_size)
+ {
+ if (tdep_access_reg (c, UNW_X86_ESP, &val, 0) >= 0)
+ {
+ val += c->dwarf.args_size;
+ (*access_reg) (as, UNW_X86_ESP, &val, 1, arg);
+ }
+ }
+ return 0;
+}
+
+int
+unw_resume (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ if ((ret = establish_machine_state (c)) < 0)
+ return ret;
+
+ return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c,
+ c->dwarf.as_arg);
+}
diff --git a/src/pal/src/libunwind/src/x86/Gstep.c b/src/pal/src/libunwind/src/x86/Gstep.c
new file mode 100644
index 0000000000..129b739a3e
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Gstep.c
@@ -0,0 +1,115 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "offsets.h"
+
+int
+unw_step (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret, i;
+
+ Debug (1, "(cursor=%p, ip=0x%08x)\n", c, (unsigned) c->dwarf.ip);
+
+ /* Try DWARF-based unwinding... */
+ ret = dwarf_step (&c->dwarf);
+
+ if (ret < 0 && ret != -UNW_ENOINFO)
+ {
+ Debug (2, "returning %d\n", ret);
+ return ret;
+ }
+
+ if (unlikely (ret < 0))
+ {
+ /* DWARF failed, let's see if we can follow the frame-chain
+ or skip over the signal trampoline. */
+ struct dwarf_loc ebp_loc, eip_loc;
+
+ /* We could get here because of missing/bad unwind information.
+ Validate all addresses before dereferencing. */
+ c->validate = 1;
+
+ Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);
+
+ if (unw_is_signal_frame (cursor) > 0)
+ {
+ ret = x86_handle_signal_frame(cursor);
+ if (ret < 0)
+ {
+ Debug (2, "returning 0\n");
+ return 0;
+ }
+ }
+ else
+ {
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[EBP], &c->dwarf.cfa);
+ if (ret < 0)
+ {
+ Debug (2, "returning %d\n", ret);
+ return ret;
+ }
+
+ Debug (13, "[EBP=0x%x] = 0x%x\n", DWARF_GET_LOC (c->dwarf.loc[EBP]),
+ c->dwarf.cfa);
+
+ ebp_loc = DWARF_LOC (c->dwarf.cfa, 0);
+ eip_loc = DWARF_LOC (c->dwarf.cfa + 4, 0);
+ c->dwarf.cfa += 8;
+
+ /* Mark all registers unsaved, since we don't know where
+ they are saved (if at all), except for the EBP and
+ EIP. */
+ for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
+ c->dwarf.loc[i] = DWARF_NULL_LOC;
+
+ c->dwarf.loc[EBP] = ebp_loc;
+ c->dwarf.loc[EIP] = eip_loc;
+ c->dwarf.use_prev_instr = 1;
+ }
+
+ if (!DWARF_IS_NULL_LOC (c->dwarf.loc[EBP]))
+ {
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[EIP], &c->dwarf.ip);
+ if (ret < 0)
+ {
+ Debug (13, "dwarf_get([EIP=0x%x]) failed\n", DWARF_GET_LOC (c->dwarf.loc[EIP]));
+ Debug (2, "returning %d\n", ret);
+ return ret;
+ }
+ else
+ {
+ Debug (13, "[EIP=0x%x] = 0x%x\n", DWARF_GET_LOC (c->dwarf.loc[EIP]),
+ c->dwarf.ip);
+ }
+ }
+ else
+ c->dwarf.ip = 0;
+ }
+ ret = (c->dwarf.ip == 0) ? 0 : 1;
+ Debug (2, "returning %d\n", ret);
+ return ret;
+}
diff --git a/src/pal/src/libunwind/src/x86/Lapply_reg_state.c b/src/pal/src/libunwind/src/x86/Lapply_reg_state.c
new file mode 100644
index 0000000000..7ebada480e
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Lapply_reg_state.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86/Lcreate_addr_space.c b/src/pal/src/libunwind/src/x86/Lcreate_addr_space.c
new file mode 100644
index 0000000000..0f2dc6be90
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Lcreate_addr_space.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gcreate_addr_space.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86/Lget_proc_info.c b/src/pal/src/libunwind/src/x86/Lget_proc_info.c
new file mode 100644
index 0000000000..69028b019f
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Lget_proc_info.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_proc_info.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86/Lget_save_loc.c b/src/pal/src/libunwind/src/x86/Lget_save_loc.c
new file mode 100644
index 0000000000..9ea048a907
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Lget_save_loc.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_save_loc.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86/Lglobal.c b/src/pal/src/libunwind/src/x86/Lglobal.c
new file mode 100644
index 0000000000..6d7b489e14
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Lglobal.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gglobal.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86/Linit.c b/src/pal/src/libunwind/src/x86/Linit.c
new file mode 100644
index 0000000000..e9abfdd46a
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Linit.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86/Linit_local.c b/src/pal/src/libunwind/src/x86/Linit_local.c
new file mode 100644
index 0000000000..68a1687e85
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Linit_local.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_local.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86/Linit_remote.c b/src/pal/src/libunwind/src/x86/Linit_remote.c
new file mode 100644
index 0000000000..58cb04ab7c
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Linit_remote.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_remote.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86/Los-freebsd.c b/src/pal/src/libunwind/src/x86/Los-freebsd.c
new file mode 100644
index 0000000000..a75a205df1
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Los-freebsd.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gos-freebsd.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86/Los-linux.c b/src/pal/src/libunwind/src/x86/Los-linux.c
new file mode 100644
index 0000000000..3cc18aabcc
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Los-linux.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gos-linux.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86/Lreg_states_iterate.c b/src/pal/src/libunwind/src/x86/Lreg_states_iterate.c
new file mode 100644
index 0000000000..f1eb1e79dc
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Lreg_states_iterate.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86/Lregs.c b/src/pal/src/libunwind/src/x86/Lregs.c
new file mode 100644
index 0000000000..2c9c75cd7d
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Lregs.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gregs.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86/Lresume.c b/src/pal/src/libunwind/src/x86/Lresume.c
new file mode 100644
index 0000000000..41a8cf003d
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Lresume.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gresume.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86/Lstep.c b/src/pal/src/libunwind/src/x86/Lstep.c
new file mode 100644
index 0000000000..c1ac3c7547
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/Lstep.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gstep.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86/getcontext-freebsd.S b/src/pal/src/libunwind/src/x86/getcontext-freebsd.S
new file mode 100644
index 0000000000..670eff1ae1
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/getcontext-freebsd.S
@@ -0,0 +1,112 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "offsets.h"
+
+ .global _Ux86_getcontext
+ .type _Ux86_getcontext, @function
+_Ux86_getcontext:
+ .cfi_startproc
+ pushl %eax
+ .cfi_adjust_cfa_offset 4
+ mov 8(%esp),%eax /* ucontext_t* */
+ popl FREEBSD_UC_MCONTEXT_EAX_OFF(%eax)
+ .cfi_adjust_cfa_offset 4
+ movl %ebx, FREEBSD_UC_MCONTEXT_EBX_OFF(%eax)
+ movl %ecx, FREEBSD_UC_MCONTEXT_ECX_OFF(%eax)
+ movl %edx, FREEBSD_UC_MCONTEXT_EDX_OFF(%eax)
+ movl %edi, FREEBSD_UC_MCONTEXT_EDI_OFF(%eax)
+ movl %esi, FREEBSD_UC_MCONTEXT_ESI_OFF(%eax)
+ movl %ebp, FREEBSD_UC_MCONTEXT_EBP_OFF(%eax)
+
+ movl (%esp), %ecx
+ movl %ecx, FREEBSD_UC_MCONTEXT_EIP_OFF(%eax)
+
+ leal 4(%esp), %ecx /* Exclude the return address. */
+ movl %ecx, FREEBSD_UC_MCONTEXT_ESP_OFF(%eax)
+
+ xorl %ecx, %ecx
+ movw %fs, %cx
+ movl %ecx, FREEBSD_UC_MCONTEXT_FS_OFF(%eax)
+ movw %gs, %cx
+ movl %ecx, FREEBSD_UC_MCONTEXT_GS_OFF(%eax)
+ movw %ds, %cx
+ movl %ecx, FREEBSD_UC_MCONTEXT_DS_OFF(%eax)
+ movw %es, %cx
+ movl %ecx, FREEBSD_UC_MCONTEXT_ES_OFF(%eax)
+ movw %ss, %cx
+ movl %ecx, FREEBSD_UC_MCONTEXT_SS_OFF(%eax)
+ movw %cs, %cx
+ movl %ecx, FREEBSD_UC_MCONTEXT_CS_OFF(%eax)
+
+ pushfl
+ .cfi_adjust_cfa_offset 4
+ popl FREEBSD_UC_MCONTEXT_EFLAGS_OFF(%eax)
+ .cfi_adjust_cfa_offset -4
+
+ movl $0, FREEBSD_UC_MCONTEXT_TRAPNO_OFF(%eax)
+
+ movl $FREEBSD_UC_MCONTEXT_FPOWNED_FPU,\
+ FREEBSD_UC_MCONTEXT_OWNEDFP_OFF(%eax)
+ movl $FREEBSD_UC_MCONTEXT_FPFMT_XMM,\
+ FREEBSD_UC_MCONTEXT_FPFORMAT_OFF(%eax)
+
+ /*
+ * Require CPU with fxsave implemented, and enabled by OS.
+ *
+ * If passed ucontext is not aligned to 16-byte boundary,
+ * save fpu context into temporary aligned location on stack
+ * and then copy.
+ */
+ leal FREEBSD_UC_MCONTEXT_FPSTATE_OFF(%eax), %edx
+ testl $0xf, %edx
+ jne 2f
+ fxsave (%edx) /* fast path, passed ucontext save area was aligned */
+1: movl $FREEBSD_UC_MCONTEXT_MC_LEN_VAL,\
+ FREEBSD_UC_MCONTEXT_MC_LEN_OFF(%eax)
+
+ xorl %eax, %eax
+ ret
+
+2: movl %edx, %edi /* not aligned, do the dance */
+ subl $512 + 16, %esp /* save area and 16 bytes for alignment */
+ .cfi_adjust_cfa_offset 512 + 16
+ movl %esp, %edx
+ orl $0xf, %edx /* align *%edx to 16-byte up */
+ incl %edx
+ fxsave (%edx)
+ movl %edx, %esi /* copy to the final destination */
+ movl $512/4,%ecx
+ rep; movsl
+ addl $512 + 16, %esp /* restore the stack */
+ .cfi_adjust_cfa_offset -512 - 16
+ movl FREEBSD_UC_MCONTEXT_ESI_OFF(%eax), %esi
+ movl FREEBSD_UC_MCONTEXT_EDI_OFF(%eax), %edi
+ jmp 1b
+
+ .cfi_endproc
+ .size _Ux86_getcontext, . - _Ux86_getcontext
+
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
diff --git a/src/pal/src/libunwind/src/x86/getcontext-linux.S b/src/pal/src/libunwind/src/x86/getcontext-linux.S
new file mode 100644
index 0000000000..c469dadbac
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/getcontext-linux.S
@@ -0,0 +1,74 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2009 Google, Inc
+ Contributed by Paul Pluzhnikov <ppluzhnikov@google.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "offsets.h"
+
+/* int _Ux86_getcontext (ucontext_t *ucp)
+
+ Saves the machine context in UCP necessary for libunwind.
+ Unlike the libc implementation, we don't save the signal mask
+ and hence avoid the cost of a system call per unwind.
+
+*/
+
+ .global _Ux86_getcontext
+ .type _Ux86_getcontext, @function
+_Ux86_getcontext:
+ .cfi_startproc
+ mov 4(%esp),%eax /* ucontext_t* */
+
+ /* EAX is not preserved. */
+ movl $0, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EAX_OFF)(%eax)
+
+ movl %ebx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EBX_OFF)(%eax)
+ movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ECX_OFF)(%eax)
+ movl %edx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EDX_OFF)(%eax)
+ movl %edi, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EDI_OFF)(%eax)
+ movl %esi, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ESI_OFF)(%eax)
+ movl %ebp, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EBP_OFF)(%eax)
+
+ movl (%esp), %ecx
+ movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EIP_OFF)(%eax)
+
+ leal 4(%esp), %ecx /* Exclude the return address. */
+ movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ESP_OFF)(%eax)
+
+ /* glibc getcontext saves FS, but not GS */
+ xorl %ecx, %ecx
+ movw %fs, %cx
+ movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FS_OFF)(%eax)
+
+ leal LINUX_UC_FPREGS_MEM_OFF(%eax), %ecx
+ movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FPSTATE_OFF)(%eax)
+ fnstenv (%ecx)
+ fldenv (%ecx)
+
+ xor %eax, %eax
+ ret
+ .cfi_endproc
+ .size _Ux86_getcontext, . - _Ux86_getcontext
+
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
diff --git a/src/pal/src/libunwind/src/x86/init.h b/src/pal/src/libunwind/src/x86/init.h
new file mode 100644
index 0000000000..b0db8d337d
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/init.h
@@ -0,0 +1,69 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+static inline int
+common_init (struct cursor *c, unsigned use_prev_instr)
+{
+ int ret, i;
+
+ c->dwarf.loc[EAX] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EAX);
+ c->dwarf.loc[ECX] = DWARF_REG_LOC (&c->dwarf, UNW_X86_ECX);
+ c->dwarf.loc[EDX] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EDX);
+ c->dwarf.loc[EBX] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EBX);
+ c->dwarf.loc[ESP] = DWARF_REG_LOC (&c->dwarf, UNW_X86_ESP);
+ c->dwarf.loc[EBP] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EBP);
+ c->dwarf.loc[ESI] = DWARF_REG_LOC (&c->dwarf, UNW_X86_ESI);
+ c->dwarf.loc[EDI] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EDI);
+ c->dwarf.loc[EIP] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EIP);
+ c->dwarf.loc[EFLAGS] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EFLAGS);
+ c->dwarf.loc[TRAPNO] = DWARF_REG_LOC (&c->dwarf, UNW_X86_TRAPNO);
+ c->dwarf.loc[ST0] = DWARF_REG_LOC (&c->dwarf, UNW_X86_ST0);
+ for (i = ST0 + 1; i < DWARF_NUM_PRESERVED_REGS; ++i)
+ c->dwarf.loc[i] = DWARF_NULL_LOC;
+
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[EIP], &c->dwarf.ip);
+ if (ret < 0)
+ return ret;
+
+ ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_X86_ESP),
+ &c->dwarf.cfa);
+ if (ret < 0)
+ return ret;
+
+ c->sigcontext_format = X86_SCF_NONE;
+ c->sigcontext_addr = 0;
+
+ c->dwarf.args_size = 0;
+ c->dwarf.stash_frames = 0;
+ c->dwarf.use_prev_instr = use_prev_instr;
+ c->dwarf.pi_valid = 0;
+ c->dwarf.pi_is_dynamic = 0;
+ c->dwarf.hint = 0;
+ c->dwarf.prev_rs = 0;
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/x86/is_fpreg.c b/src/pal/src/libunwind/src/x86/is_fpreg.c
new file mode 100644
index 0000000000..a3a98ac8d3
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/is_fpreg.c
@@ -0,0 +1,34 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2004-2005 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+int
+unw_is_fpreg (int regnum)
+{
+ return ((regnum >= UNW_X86_ST0 && regnum <= UNW_X86_ST7)
+ || (regnum >= UNW_X86_XMM0_lo && regnum <= UNW_X86_XMM7_hi)
+ || (regnum >= UNW_X86_XMM0 && regnum <= UNW_X86_XMM7));
+}
diff --git a/src/pal/src/libunwind/src/x86/longjmp.S b/src/pal/src/libunwind/src/x86/longjmp.S
new file mode 100644
index 0000000000..05173d0c10
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/longjmp.S
@@ -0,0 +1,39 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+ .globl _UI_longjmp_cont
+
+ .type _UI_longjmp_cont, @function
+_UI_longjmp_cont:
+ .cfi_startproc
+ .cfi_register 8, 0 /* IP saved in EAX */
+ push %eax /* push target IP as return address */
+ .cfi_restore 8
+ mov %edx, %eax /* set up return-value */
+ ret
+ .cfi_endproc
+ .size _UI_siglongjmp_cont, .-_UI_longjmp_cont
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
diff --git a/src/pal/src/libunwind/src/x86/offsets.h b/src/pal/src/libunwind/src/x86/offsets.h
new file mode 100644
index 0000000000..e5aec7f588
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/offsets.h
@@ -0,0 +1,140 @@
+/* Linux-specific definitions: */
+
+/* Define various structure offsets to simplify cross-compilation. */
+
+/* Offsets for x86 Linux "ucontext_t": */
+
+#define LINUX_UC_FLAGS_OFF 0x00
+#define LINUX_UC_LINK_OFF 0x04
+#define LINUX_UC_STACK_OFF 0x08
+#define LINUX_UC_MCONTEXT_OFF 0x14
+#define LINUX_UC_SIGMASK_OFF 0x6c
+#define LINUX_UC_FPREGS_MEM_OFF 0xec
+
+/* The struct sigcontext is located at an offset of 4
+ from the stack pointer in the signal frame. */
+
+/* Offsets for x86 Linux "struct sigcontext": */
+
+#define LINUX_SC_GS_OFF 0x00
+#define LINUX_SC_GSH_OFF 0x02
+#define LINUX_SC_FS_OFF 0x04
+#define LINUX_SC_FSH_OFF 0x06
+#define LINUX_SC_ES_OFF 0x08
+#define LINUX_SC_ESH_OFF 0x0a
+#define LINUX_SC_DS_OFF 0x0c
+#define LINUX_SC_DSH_OFF 0x0e
+#define LINUX_SC_EDI_OFF 0x10
+#define LINUX_SC_ESI_OFF 0x14
+#define LINUX_SC_EBP_OFF 0x18
+#define LINUX_SC_ESP_OFF 0x1c
+#define LINUX_SC_EBX_OFF 0x20
+#define LINUX_SC_EDX_OFF 0x24
+#define LINUX_SC_ECX_OFF 0x28
+#define LINUX_SC_EAX_OFF 0x2c
+#define LINUX_SC_TRAPNO_OFF 0x30
+#define LINUX_SC_ERR_OFF 0x34
+#define LINUX_SC_EIP_OFF 0x38
+#define LINUX_SC_CS_OFF 0x3c
+#define LINUX_SC_CSH_OFF 0x3e
+#define LINUX_SC_EFLAGS_OFF 0x40
+#define LINUX_SC_ESP_AT_SIGNAL_OFF 0x44
+#define LINUX_SC_SS_OFF 0x48
+#define LINUX_SC_SSH_OFF 0x4a
+#define LINUX_SC_FPSTATE_OFF 0x4c
+#define LINUX_SC_OLDMASK_OFF 0x50
+#define LINUX_SC_CR2_OFF 0x54
+
+/* Offsets for x86 Linux "struct _fpstate": */
+
+#define LINUX_FPSTATE_CW_OFF 0x000
+#define LINUX_FPSTATE_SW_OFF 0x004
+#define LINUX_FPSTATE_TAG_OFF 0x008
+#define LINUX_FPSTATE_IPOFF_OFF 0x00c
+#define LINUX_FPSTATE_CSSEL_OFF 0x010
+#define LINUX_FPSTATE_DATAOFF_OFF 0x014
+#define LINUX_FPSTATE_DATASEL_OFF 0x018
+#define LINUX_FPSTATE_ST0_OFF 0x01c
+#define LINUX_FPSTATE_ST1_OFF 0x026
+#define LINUX_FPSTATE_ST2_OFF 0x030
+#define LINUX_FPSTATE_ST3_OFF 0x03a
+#define LINUX_FPSTATE_ST4_OFF 0x044
+#define LINUX_FPSTATE_ST5_OFF 0x04e
+#define LINUX_FPSTATE_ST6_OFF 0x058
+#define LINUX_FPSTATE_ST7_OFF 0x062
+#define LINUX_FPSTATE_STATUS_OFF 0x06c
+#define LINUX_FPSTATE_MAGIC_OFF 0x06e
+#define LINUX_FPSTATE_FXSR_ENV_OFF 0x070
+#define LINUX_FPSTATE_MXCSR_OFF 0x088
+#define LINUX_FPSTATE_FXSR_ST0_OFF 0x090
+#define LINUX_FPSTATE_FXSR_ST1_OFF 0x0a0
+#define LINUX_FPSTATE_FXSR_ST2_OFF 0x0b0
+#define LINUX_FPSTATE_FXSR_ST3_OFF 0x0c0
+#define LINUX_FPSTATE_FXSR_ST4_OFF 0x0d0
+#define LINUX_FPSTATE_FXSR_ST5_OFF 0x0e0
+#define LINUX_FPSTATE_FXSR_ST6_OFF 0x0f0
+#define LINUX_FPSTATE_FXSR_ST7_OFF 0x100
+#define LINUX_FPSTATE_XMM0_OFF 0x110
+#define LINUX_FPSTATE_XMM1_OFF 0x120
+#define LINUX_FPSTATE_XMM2_OFF 0x130
+#define LINUX_FPSTATE_XMM3_OFF 0x140
+#define LINUX_FPSTATE_XMM4_OFF 0x150
+#define LINUX_FPSTATE_XMM5_OFF 0x160
+#define LINUX_FPSTATE_XMM6_OFF 0x170
+#define LINUX_FPSTATE_XMM7_OFF 0x180
+
+/* FreeBSD-specific definitions: */
+
+#define FREEBSD_SC_UCONTEXT_OFF 0x20
+#define FREEBSD_UC_MCONTEXT_OFF 0x10
+
+#define FREEBSD_UC_MCONTEXT_GS_OFF 0x14
+#define FREEBSD_UC_MCONTEXT_FS_OFF 0x18
+#define FREEBSD_UC_MCONTEXT_ES_OFF 0x1c
+#define FREEBSD_UC_MCONTEXT_DS_OFF 0x20
+#define FREEBSD_UC_MCONTEXT_EDI_OFF 0x24
+#define FREEBSD_UC_MCONTEXT_ESI_OFF 0x28
+#define FREEBSD_UC_MCONTEXT_EBP_OFF 0x2c
+#define FREEBSD_UC_MCONTEXT_EBX_OFF 0x34
+#define FREEBSD_UC_MCONTEXT_EDX_OFF 0x38
+#define FREEBSD_UC_MCONTEXT_ECX_OFF 0x3c
+#define FREEBSD_UC_MCONTEXT_EAX_OFF 0x40
+#define FREEBSD_UC_MCONTEXT_TRAPNO_OFF 0x44
+#define FREEBSD_UC_MCONTEXT_EIP_OFF 0x4c
+#define FREEBSD_UC_MCONTEXT_ESP_OFF 0x58
+#define FREEBSD_UC_MCONTEXT_CS_OFF 0x50
+#define FREEBSD_UC_MCONTEXT_EFLAGS_OFF 0x54
+#define FREEBSD_UC_MCONTEXT_SS_OFF 0x5c
+#define FREEBSD_UC_MCONTEXT_MC_LEN_OFF 0x60
+#define FREEBSD_UC_MCONTEXT_FPFORMAT_OFF 0x64
+#define FREEBSD_UC_MCONTEXT_OWNEDFP_OFF 0x68
+#define FREEBSD_UC_MCONTEXT_FPSTATE_OFF 0x70
+
+#define FREEBSD_UC_MCONTEXT_CW_OFF 0x70
+#define FREEBSD_UC_MCONTEXT_SW_OFF 0x74
+#define FREEBSD_UC_MCONTEXT_TAG_OFF 0x78
+#define FREEBSD_UC_MCONTEXT_IPOFF_OFF 0x7c
+#define FREEBSD_UC_MCONTEXT_CSSEL_OFF 0x80
+#define FREEBSD_UC_MCONTEXT_DATAOFF_OFF 0x84
+#define FREEBSD_US_MCONTEXT_DATASEL_OFF 0x88
+#define FREEBSD_UC_MCONTEXT_ST0_OFF 0x8c
+
+#define FREEBSD_UC_MCONTEXT_CW_XMM_OFF 0x70
+#define FREEBSD_UC_MCONTEXT_SW_XMM_OFF 0x72
+#define FREEBSD_UC_MCONTEXT_TAG_XMM_OFF 0x74
+#define FREEBSD_UC_MCONTEXT_IPOFF_XMM_OFF 0x78
+#define FREEBSD_UC_MCONTEXT_CSSEL_XMM_OFF 0x7c
+#define FREEBSD_UC_MCONTEXT_DATAOFF_XMM_OFF 0x80
+#define FREEBSD_US_MCONTEXT_DATASEL_XMM_OFF 0x84
+#define FREEBSD_UC_MCONTEXT_MXCSR_XMM_OFF 0x88
+#define FREEBSD_UC_MCONTEXT_ST0_XMM_OFF 0x90
+#define FREEBSD_UC_MCONTEXT_XMM0_OFF 0x110
+
+#define FREEBSD_UC_MCONTEXT_MC_LEN_VAL 0x280
+#define FREEBSD_UC_MCONTEXT_FPFMT_NODEV 0x10000
+#define FREEBSD_UC_MCONTEXT_FPFMT_387 0x10001
+#define FREEBSD_UC_MCONTEXT_FPFMT_XMM 0x10002
+#define FREEBSD_UC_MCONTEXT_FPOWNED_NONE 0x20000
+#define FREEBSD_UC_MCONTEXT_FPOWNED_FPU 0x20001
+#define FREEBSD_UC_MCONTEXT_FPOWNED_PCB 0x20002
+
diff --git a/src/pal/src/libunwind/src/x86/regname.c b/src/pal/src/libunwind/src/x86/regname.c
new file mode 100644
index 0000000000..11f6228041
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/regname.c
@@ -0,0 +1,27 @@
+#include "unwind_i.h"
+
+static const char *regname[] =
+ {
+ "eax", "edx", "ecx", "ebx", "esi", "edi", "ebp", "esp", "eip",
+ "eflags", "trapno",
+ "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7",
+ "fcw", "fsw", "ftw", "fop", "fcs", "fip", "fea", "fds",
+ "xmm0_lo", "xmm0_hi", "xmm1_lo", "xmm1_hi",
+ "xmm2_lo", "xmm2_hi", "xmm3_lo", "xmm3_hi",
+ "xmm4_lo", "xmm4_hi", "xmm5_lo", "xmm5_hi",
+ "xmm6_lo", "xmm6_hi", "xmm7_lo", "xmm7_hi",
+ "mxcsr",
+ "gs", "fs", "es", "ds", "ss", "cs",
+ "tss", "ldt",
+ "cfi",
+ "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
+ };
+
+const char *
+unw_regname (unw_regnum_t reg)
+{
+ if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
+ return regname[reg];
+ else
+ return "???";
+}
diff --git a/src/pal/src/libunwind/src/x86/siglongjmp.S b/src/pal/src/libunwind/src/x86/siglongjmp.S
new file mode 100644
index 0000000000..32bba3b3b6
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/siglongjmp.S
@@ -0,0 +1,92 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+ Copyright (C) 2011 Konstantin Belousov <kib@FreeBSD.org>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+ .globl _UI_siglongjmp_cont
+
+#if defined(__linux__)
+#define SIG_SETMASK 2
+#elif defined(__FreeBSD__)
+#define SIG_SETMASK 3
+#endif
+
+ /* Stack layout at this point:
+
+ +------------+ <- original $esp (at time of setjmp() call)
+ | sigmask[1] |
+ +------------+
+ | sigmask[0] |
+ +------------+
+ */
+
+ .type _UI_siglongjmp_cont, @function
+_UI_siglongjmp_cont:
+ .cfi_startproc
+#ifdef __linux__
+ .cfi_register 8, 0 /* IP saved in EAX */
+ .cfi_def_cfa_offset 8
+ mov %esp, %ecx /* pass address of signal mask in 3rd sc arg */
+ push %eax /* save target IP */
+ .cfi_adjust_cfa_offset 4
+ .cfi_offset 8, -12
+ push %edx /* save return value */
+ .cfi_adjust_cfa_offset 4
+ push %ebx /* save %ebx (preserved) */
+ .cfi_adjust_cfa_offset 4
+ .cfi_offset 3, -20
+ mov $SIG_SETMASK, %ebx /* 1st syscall arg (how) */
+ xor %edx, %edx /* pass NULL as 3rd syscall arg (old maskp) */
+ int $0x80
+ pop %ebx /* restore %ebx */
+ .cfi_adjust_cfa_offset -4
+ .cfi_restore 3
+ pop %eax /* fetch return value */
+ .cfi_adjust_cfa_offset -4
+ pop %edx /* pop target IP */
+ .cfi_adjust_cfa_offset -4
+ .cfi_register 8, 2 /* saved IP is now n EDX */
+ lea 8(%esp), %esp /* pop sigmask */
+ .cfi_adjust_cfa_offset -4
+ jmp *%edx
+#elif defined(__FreeBSD__)
+ pushl %eax
+ pushl %edx
+ pushl $0
+ pushl %ecx
+ pushl $SIG_SETMASK
+ movl $340,%eax
+ pushl %eax
+ int $0x80
+ addl $16,%esp
+ popl %eax
+ popl %edx
+ jmp *%edx
+#else
+#error Port me
+#endif
+ .cfi_endproc
+ .size _UI_siglongjmp_cont, .-_UI_siglongjmp_cont
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
diff --git a/src/pal/src/libunwind/src/x86/unwind_i.h b/src/pal/src/libunwind/src/x86/unwind_i.h
new file mode 100644
index 0000000000..caa7e02dee
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86/unwind_i.h
@@ -0,0 +1,68 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef unwind_i_h
+#define unwind_i_h
+
+#include <stdint.h>
+
+#include <libunwind-x86.h>
+
+#include "libunwind_i.h"
+
+/* DWARF column numbers: */
+#define EAX 0
+#define ECX 1
+#define EDX 2
+#define EBX 3
+#define ESP 4
+#define EBP 5
+#define ESI 6
+#define EDI 7
+#define EIP 8
+#define EFLAGS 9
+#define TRAPNO 10
+#define ST0 11
+
+#define x86_lock UNW_OBJ(lock)
+#define x86_local_resume UNW_OBJ(local_resume)
+#define x86_local_addr_space_init UNW_OBJ(local_addr_space_init)
+#define x86_scratch_loc UNW_OBJ(scratch_loc)
+#define x86_get_scratch_loc UNW_OBJ(get_scratch_loc)
+#define x86_r_uc_addr UNW_OBJ(r_uc_addr)
+#define x86_sigreturn UNW_OBJ(sigreturn)
+
+extern void x86_local_addr_space_init (void);
+extern int x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
+ void *arg);
+extern dwarf_loc_t x86_scratch_loc (struct cursor *c, unw_regnum_t reg);
+extern dwarf_loc_t x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg);
+extern void *x86_r_uc_addr (ucontext_t *uc, int reg);
+
+extern void x86_sigreturn (unw_cursor_t *cursor);
+#define x86_handle_signal_frame UNW_OBJ(handle_signal_frame)
+extern int x86_handle_signal_frame(unw_cursor_t *cursor);
+
+#endif /* unwind_i_h */
diff --git a/src/pal/src/libunwind/src/x86_64/Gapply_reg_state.c b/src/pal/src/libunwind/src/x86_64/Gapply_reg_state.c
new file mode 100644
index 0000000000..82f056da67
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Gapply_reg_state.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+ void *reg_states_data)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
diff --git a/src/pal/src/libunwind/src/x86_64/Gcreate_addr_space.c b/src/pal/src/libunwind/src/x86_64/Gcreate_addr_space.c
new file mode 100644
index 0000000000..9b2db9810a
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Gcreate_addr_space.c
@@ -0,0 +1,61 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+
+#include "unwind_i.h"
+
+#if defined(_LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN)
+#define __LITTLE_ENDIAN _LITTLE_ENDIAN
+#endif
+
+unw_addr_space_t
+unw_create_addr_space (unw_accessors_t *a, int byte_order)
+{
+#ifdef UNW_LOCAL_ONLY
+ return NULL;
+#else
+ unw_addr_space_t as;
+
+ /*
+ * x86_64 supports only little-endian.
+ */
+ if (byte_order != 0 && byte_order != __LITTLE_ENDIAN)
+ return NULL;
+
+ as = malloc (sizeof (*as));
+ if (!as)
+ return NULL;
+
+ memset (as, 0, sizeof (*as));
+
+ as->acc = *a;
+
+ return as;
+#endif
+}
diff --git a/src/pal/src/libunwind/src/x86_64/Gget_proc_info.c b/src/pal/src/libunwind/src/x86_64/Gget_proc_info.c
new file mode 100644
index 0000000000..50de1e423c
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Gget_proc_info.c
@@ -0,0 +1,48 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (dwarf_make_proc_info (&c->dwarf) < 0)
+ {
+ /* On x86-64, some key routines such as _start() and _dl_start()
+ are missing DWARF unwind info. We don't want to fail in that
+ case, because those frames are uninteresting and just mark
+ the end of the frame-chain anyhow. */
+ memset (pi, 0, sizeof (*pi));
+ pi->start_ip = c->dwarf.ip;
+ pi->end_ip = c->dwarf.ip + 1;
+ return 0;
+ }
+ *pi = c->dwarf.pi;
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/x86_64/Gget_save_loc.c b/src/pal/src/libunwind/src/x86_64/Gget_save_loc.c
new file mode 100644
index 0000000000..0057c62d64
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Gget_save_loc.c
@@ -0,0 +1,73 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ dwarf_loc_t loc;
+
+ loc = DWARF_NULL_LOC; /* default to "not saved" */
+
+ switch (reg)
+ {
+ case UNW_X86_64_RBX: loc = c->dwarf.loc[RBX]; break;
+ case UNW_X86_64_RSP: loc = c->dwarf.loc[RSP]; break;
+ case UNW_X86_64_RBP: loc = c->dwarf.loc[RBP]; break;
+ case UNW_X86_64_R12: loc = c->dwarf.loc[R12]; break;
+ case UNW_X86_64_R13: loc = c->dwarf.loc[R13]; break;
+ case UNW_X86_64_R14: loc = c->dwarf.loc[R14]; break;
+ case UNW_X86_64_R15: loc = c->dwarf.loc[R15]; break;
+
+ default:
+ break;
+ }
+
+ memset (sloc, 0, sizeof (*sloc));
+
+ if (DWARF_IS_NULL_LOC (loc))
+ {
+ sloc->type = UNW_SLT_NONE;
+ return 0;
+ }
+
+#if !defined(UNW_LOCAL_ONLY)
+ if (DWARF_IS_REG_LOC (loc))
+ {
+ sloc->type = UNW_SLT_REG;
+ sloc->u.regnum = DWARF_GET_LOC (loc);
+ }
+ else
+#endif
+ {
+ sloc->type = UNW_SLT_MEMORY;
+ sloc->u.addr = DWARF_GET_LOC (loc);
+ }
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/x86_64/Gglobal.c b/src/pal/src/libunwind/src/x86_64/Gglobal.c
new file mode 100644
index 0000000000..8d1fbb4b0a
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Gglobal.c
@@ -0,0 +1,102 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "config.h"
+#include "unwind_i.h"
+#include "dwarf_i.h"
+
+HIDDEN define_lock (x86_64_lock);
+HIDDEN int tdep_init_done;
+
+/* See comments for svr4_dbx_register_map[] in gcc/config/i386/i386.c. */
+
+HIDDEN const uint8_t dwarf_to_unw_regnum_map[DWARF_NUM_PRESERVED_REGS] =
+ {
+ UNW_X86_64_RAX,
+ UNW_X86_64_RDX,
+ UNW_X86_64_RCX,
+ UNW_X86_64_RBX,
+ UNW_X86_64_RSI,
+ UNW_X86_64_RDI,
+ UNW_X86_64_RBP,
+ UNW_X86_64_RSP,
+ UNW_X86_64_R8,
+ UNW_X86_64_R9,
+ UNW_X86_64_R10,
+ UNW_X86_64_R11,
+ UNW_X86_64_R12,
+ UNW_X86_64_R13,
+ UNW_X86_64_R14,
+ UNW_X86_64_R15,
+ UNW_X86_64_RIP,
+#ifdef CONFIG_MSABI_SUPPORT
+ UNW_X86_64_XMM0,
+ UNW_X86_64_XMM1,
+ UNW_X86_64_XMM2,
+ UNW_X86_64_XMM3,
+ UNW_X86_64_XMM4,
+ UNW_X86_64_XMM5,
+ UNW_X86_64_XMM6,
+ UNW_X86_64_XMM7,
+ UNW_X86_64_XMM8,
+ UNW_X86_64_XMM9,
+ UNW_X86_64_XMM10,
+ UNW_X86_64_XMM11,
+ UNW_X86_64_XMM12,
+ UNW_X86_64_XMM13,
+ UNW_X86_64_XMM14,
+ UNW_X86_64_XMM15
+#endif
+ };
+
+HIDDEN void
+tdep_init (void)
+{
+ intrmask_t saved_mask;
+
+ sigfillset (&unwi_full_mask);
+
+ lock_acquire (&x86_64_lock, saved_mask);
+ {
+ if (tdep_init_done)
+ /* another thread else beat us to it... */
+ goto out;
+
+ mi_init ();
+
+ dwarf_init ();
+
+ tdep_init_mem_validate ();
+
+#ifndef UNW_REMOTE_ONLY
+ x86_64_local_addr_space_init ();
+#endif
+ tdep_init_done = 1; /* signal that we're initialized... */
+ }
+ out:
+ lock_release (&x86_64_lock, saved_mask);
+}
diff --git a/src/pal/src/libunwind/src/x86_64/Ginit.c b/src/pal/src/libunwind/src/x86_64/Ginit.c
new file mode 100644
index 0000000000..2a84a1eec7
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Ginit.c
@@ -0,0 +1,342 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002 Hewlett-Packard Co
+ Copyright (C) 2007 David Mosberger-Tang
+ Contributed by David Mosberger-Tang <dmosberger@gmail.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+
+#include "unwind_i.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+/* unw_local_addr_space is a NULL pointer in this case. */
+unw_addr_space_t unw_local_addr_space;
+
+#else /* !UNW_REMOTE_ONLY */
+
+static struct unw_addr_space local_addr_space;
+
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
+
+HIDDEN unw_dyn_info_list_t _U_dyn_info_list;
+
+/* XXX fix me: there is currently no way to locate the dyn-info list
+ by a remote unwinder. On ia64, this is done via a special
+ unwind-table entry. Perhaps something similar can be done with
+ DWARF2 unwind info. */
+
+static void
+put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
+{
+ /* it's a no-op */
+}
+
+static int
+get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
+ void *arg)
+{
+ *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list;
+ return 0;
+}
+
+#define PAGE_SIZE 4096
+#define PAGE_START(a) ((a) & ~(PAGE_SIZE-1))
+
+static int mem_validate_pipe[2] = {-1, -1};
+
+static inline void
+open_pipe (void)
+{
+ /* ignore errors for closing invalid fd's */
+ close (mem_validate_pipe[0]);
+ close (mem_validate_pipe[1]);
+
+ pipe2 (mem_validate_pipe, O_CLOEXEC | O_NONBLOCK);
+}
+
+ALWAYS_INLINE
+static int
+write_validate (void *addr)
+{
+ int ret = -1;
+ ssize_t bytes = 0;
+
+ do
+ {
+ char buf;
+ bytes = read (mem_validate_pipe[0], &buf, 1);
+ }
+ while ( errno == EINTR );
+
+ int valid_read = (bytes > 0 || errno == EAGAIN || errno == EWOULDBLOCK);
+ if (!valid_read)
+ {
+ // re-open closed pipe
+ open_pipe ();
+ }
+
+ do
+ {
+ /* use syscall insteadof write() so that ASAN does not complain */
+ ret = syscall (SYS_write, mem_validate_pipe[1], addr, 1);
+ }
+ while ( errno == EINTR );
+
+ return ret;
+}
+
+static int (*mem_validate_func) (void *addr, size_t len);
+static int msync_validate (void *addr, size_t len)
+{
+ if (msync (addr, len, MS_ASYNC) != 0)
+ {
+ return -1;
+ }
+
+ return write_validate (addr);
+}
+
+#ifdef HAVE_MINCORE
+static int mincore_validate (void *addr, size_t len)
+{
+ unsigned char mvec[2]; /* Unaligned access may cross page boundary */
+ size_t i;
+
+ /* mincore could fail with EAGAIN but we conservatively return -1
+ instead of looping. */
+ if (mincore (addr, len, mvec) != 0)
+ {
+ return -1;
+ }
+
+ for (i = 0; i < (len + PAGE_SIZE - 1) / PAGE_SIZE; i++)
+ {
+ if (!(mvec[i] & 1)) return -1;
+ }
+
+ return write_validate (addr);
+}
+#endif
+
+/* Initialise memory validation method. On linux kernels <2.6.21,
+ mincore() returns incorrect value for MAP_PRIVATE mappings,
+ such as stacks. If mincore() was available at compile time,
+ check if we can actually use it. If not, use msync() instead. */
+HIDDEN void
+tdep_init_mem_validate (void)
+{
+ open_pipe ();
+
+#ifdef HAVE_MINCORE
+ unsigned char present = 1;
+ unw_word_t addr = PAGE_START((unw_word_t)&present);
+ unsigned char mvec[1];
+ int ret;
+ while ((ret = mincore ((void*)addr, PAGE_SIZE, mvec)) == -1 &&
+ errno == EAGAIN) {}
+ if (ret == 0 && (mvec[0] & 1))
+ {
+ Debug(1, "using mincore to validate memory\n");
+ mem_validate_func = mincore_validate;
+ }
+ else
+#endif
+ {
+ Debug(1, "using msync to validate memory\n");
+ mem_validate_func = msync_validate;
+ }
+}
+
+/* Cache of already validated addresses */
+#define NLGA 4
+static unw_word_t last_good_addr[NLGA];
+static int lga_victim;
+
+static int
+validate_mem (unw_word_t addr)
+{
+ int i, victim;
+ size_t len;
+
+ if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr))
+ len = PAGE_SIZE;
+ else
+ len = PAGE_SIZE * 2;
+
+ addr = PAGE_START(addr);
+
+ if (addr == 0)
+ return -1;
+
+ for (i = 0; i < NLGA; i++)
+ {
+ if (last_good_addr[i] && (addr == last_good_addr[i]))
+ return 0;
+ }
+
+ if (mem_validate_func ((void *) addr, len) == -1)
+ return -1;
+
+ victim = lga_victim;
+ for (i = 0; i < NLGA; i++) {
+ if (!last_good_addr[victim]) {
+ last_good_addr[victim++] = addr;
+ return 0;
+ }
+ victim = (victim + 1) % NLGA;
+ }
+
+ /* All slots full. Evict the victim. */
+ last_good_addr[victim] = addr;
+ victim = (victim + 1) % NLGA;
+ lga_victim = victim;
+
+ return 0;
+}
+
+static int
+access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
+ void *arg)
+{
+ if (unlikely (write))
+ {
+ Debug (16, "mem[%016lx] <- %lx\n", addr, *val);
+ *(unw_word_t *) addr = *val;
+ }
+ else
+ {
+ /* validate address */
+ const struct cursor *c = (const struct cursor *)arg;
+ if (likely (c != NULL) && unlikely (c->validate)
+ && unlikely (validate_mem (addr))) {
+ Debug (16, "mem[%016lx] -> invalid\n", addr);
+ return -1;
+ }
+ *val = *(unw_word_t *) addr;
+ Debug (16, "mem[%016lx] -> %lx\n", addr, *val);
+ }
+ return 0;
+}
+
+static int
+access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
+ void *arg)
+{
+ unw_word_t *addr;
+ ucontext_t *uc = ((struct cursor *)arg)->uc;
+
+ if (unw_is_fpreg (reg))
+ goto badreg;
+
+ if (!(addr = x86_64_r_uc_addr (uc, reg)))
+ goto badreg;
+
+ if (write)
+ {
+ *(unw_word_t *) addr = *val;
+ Debug (12, "%s <- 0x%016lx\n", unw_regname (reg), *val);
+ }
+ else
+ {
+ *val = *(unw_word_t *) addr;
+ Debug (12, "%s -> 0x%016lx\n", unw_regname (reg), *val);
+ }
+ return 0;
+
+ badreg:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+}
+
+static int
+access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
+ int write, void *arg)
+{
+ ucontext_t *uc = ((struct cursor *)arg)->uc;
+ unw_fpreg_t *addr;
+
+ if (!unw_is_fpreg (reg))
+ goto badreg;
+
+ if (!(addr = x86_64_r_uc_addr (uc, reg)))
+ goto badreg;
+
+ if (write)
+ {
+ Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg),
+ ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
+ *(unw_fpreg_t *) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_fpreg_t *) addr;
+ Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg),
+ ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
+ }
+ return 0;
+
+ badreg:
+ Debug (1, "bad register number %u\n", reg);
+ /* attempt to access a non-preserved register */
+ return -UNW_EBADREG;
+}
+
+static int
+get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
+ char *buf, size_t buf_len, unw_word_t *offp,
+ void *arg)
+{
+ return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
+}
+
+HIDDEN void
+x86_64_local_addr_space_init (void)
+{
+ memset (&local_addr_space, 0, sizeof (local_addr_space));
+ local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
+ local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
+ local_addr_space.acc.put_unwind_info = put_unwind_info;
+ local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
+ local_addr_space.acc.access_mem = access_mem;
+ local_addr_space.acc.access_reg = access_reg;
+ local_addr_space.acc.access_fpreg = access_fpreg;
+ local_addr_space.acc.resume = x86_64_local_resume;
+ local_addr_space.acc.get_proc_name = get_static_proc_name;
+ unw_flush_cache (&local_addr_space, 0, 0);
+
+ memset (last_good_addr, 0, sizeof (unw_word_t) * NLGA);
+ lga_victim = 0;
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/x86_64/Ginit_local.c b/src/pal/src/libunwind/src/x86_64/Ginit_local.c
new file mode 100644
index 0000000000..5eaead0f84
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Ginit_local.c
@@ -0,0 +1,81 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "init.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+int
+unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+{
+ return -UNW_EINVAL;
+}
+
+#else /* !UNW_REMOTE_ONLY */
+
+static int
+unw_init_local_common (unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (unlikely (!tdep_init_done))
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->dwarf.as = unw_local_addr_space;
+ c->dwarf.as_arg = c;
+ c->uc = uc;
+ c->validate = 0;
+ return common_init (c, use_prev_instr);
+}
+
+int
+unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+{
+ return unw_init_local_common(cursor, uc, 1);
+}
+
+int
+unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
+{
+ if (!flag)
+ {
+ return unw_init_local_common(cursor, uc, 1);
+ }
+ else if (flag == UNW_INIT_SIGNAL_FRAME)
+ {
+ return unw_init_local_common(cursor, uc, 0);
+ }
+ else
+ {
+ return -UNW_EINVAL;
+ }
+}
+
+#endif /* !UNW_REMOTE_ONLY */
diff --git a/src/pal/src/libunwind/src/x86_64/Ginit_remote.c b/src/pal/src/libunwind/src/x86_64/Ginit_remote.c
new file mode 100644
index 0000000000..efd61d64d4
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Ginit_remote.c
@@ -0,0 +1,57 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "init.h"
+#include "unwind_i.h"
+
+int
+unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
+{
+#ifdef UNW_LOCAL_ONLY
+ return -UNW_EINVAL;
+#else /* !UNW_LOCAL_ONLY */
+ struct cursor *c = (struct cursor *) cursor;
+
+ if (!tdep_init_done)
+ tdep_init ();
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ c->dwarf.as = as;
+ if (as == unw_local_addr_space)
+ {
+ c->dwarf.as_arg = c;
+ c->uc = as_arg;
+ }
+ else
+ {
+ c->dwarf.as_arg = as_arg;
+ c->uc = NULL;
+ }
+ return common_init (c, 0);
+#endif /* !UNW_LOCAL_ONLY */
+}
diff --git a/src/pal/src/libunwind/src/x86_64/Gos-freebsd.c b/src/pal/src/libunwind/src/x86_64/Gos-freebsd.c
new file mode 100644
index 0000000000..883025c88d
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Gos-freebsd.c
@@ -0,0 +1,218 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/ucontext.h>
+#include <machine/sigframe.h>
+#include <signal.h>
+#include <stddef.h>
+#include "unwind_i.h"
+#include "ucontext_i.h"
+
+int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+ /* XXXKIB */
+ struct cursor *c = (struct cursor *) cursor;
+ unw_word_t w0, w1, w2, b0, ip;
+ unw_addr_space_t as;
+ unw_accessors_t *a;
+ void *arg;
+ int ret;
+
+ as = c->dwarf.as;
+ a = unw_get_accessors_int (as);
+ arg = c->dwarf.as_arg;
+
+ /* Check if RIP points at sigreturn sequence.
+48 8d 7c 24 10 lea SIGF_UC(%rsp),%rdi
+6a 00 pushq $0
+48 c7 c0 a1 01 00 00 movq $SYS_sigreturn,%rax
+0f 05 syscall
+f4 0: hlt
+eb fd jmp 0b
+ */
+
+ ip = c->dwarf.ip;
+ c->sigcontext_format = X86_64_SCF_NONE;
+ if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0
+ || (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0
+ || (ret = (*a->access_mem) (as, ip + 16, &w2, 0, arg)) < 0)
+ return 0;
+ w2 &= 0xffffff;
+ if (w0 == 0x48006a10247c8d48 &&
+ w1 == 0x050f000001a1c0c7 &&
+ w2 == 0x0000000000fdebf4)
+ {
+ c->sigcontext_format = X86_64_SCF_FREEBSD_SIGFRAME;
+ return (c->sigcontext_format);
+ }
+ /* Check if RIP points at standard syscall sequence.
+49 89 ca mov %rcx,%r10
+0f 05 syscall
+ */
+ if ((ret = (*a->access_mem) (as, ip - 5, &b0, 0, arg)) < 0)
+ return (0);
+ Debug (12, "b0 0x%lx\n", b0);
+ if ((b0 & 0xffffffffffffff) == 0x050fca89490000 ||
+ (b0 & 0xffffffffff) == 0x050fca8949)
+ {
+ c->sigcontext_format = X86_64_SCF_FREEBSD_SYSCALL;
+ return (c->sigcontext_format);
+ }
+ return (X86_64_SCF_NONE);
+}
+
+HIDDEN int
+x86_64_handle_signal_frame (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ unw_word_t ucontext;
+ int ret;
+
+ if (c->sigcontext_format == X86_64_SCF_FREEBSD_SIGFRAME)
+ {
+ ucontext = c->dwarf.cfa + offsetof(struct sigframe, sf_uc);
+ c->sigcontext_addr = c->dwarf.cfa;
+ Debug(1, "signal frame, skip over trampoline\n");
+
+ struct dwarf_loc rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0);
+ ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa);
+ if (ret < 0)
+ {
+ Debug (2, "returning %d\n", ret);
+ return ret;
+ }
+
+ c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0);
+ c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0);
+ c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0);
+ c->dwarf.loc[RBX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBX, 0);
+ c->dwarf.loc[RSI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSI, 0);
+ c->dwarf.loc[RDI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDI, 0);
+ c->dwarf.loc[RBP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0);
+ c->dwarf.loc[RSP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0);
+ c->dwarf.loc[ R8] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0);
+ c->dwarf.loc[ R9] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0);
+ c->dwarf.loc[R10] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0);
+ c->dwarf.loc[R11] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0);
+ c->dwarf.loc[R12] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0);
+ c->dwarf.loc[R13] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0);
+ c->dwarf.loc[R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0);
+ c->dwarf.loc[R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0);
+ c->dwarf.loc[RIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0);
+
+ return 0;
+ }
+ else if (c->sigcontext_format == X86_64_SCF_FREEBSD_SYSCALL)
+ {
+ c->dwarf.loc[RCX] = c->dwarf.loc[R10];
+ /* rsp_loc = DWARF_LOC(c->dwarf.cfa - 8, 0); */
+ /* rbp_loc = c->dwarf.loc[RBP]; */
+ c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0);
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip);
+ Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n",
+ (unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RIP]),
+ (unsigned long long) c->dwarf.ip);
+ if (ret < 0)
+ {
+ Debug (2, "returning %d\n", ret);
+ return ret;
+ }
+ c->dwarf.cfa += 8;
+ c->dwarf.use_prev_instr = 1;
+ return 1;
+ }
+ else
+ return -UNW_EBADFRAME;
+
+}
+
+#ifndef UNW_REMOTE_ONLY
+HIDDEN void *
+x86_64_r_uc_addr (ucontext_t *uc, int reg)
+{
+ /* NOTE: common_init() in init.h inlines these for fast path access. */
+ void *addr;
+
+ switch (reg)
+ {
+ case UNW_X86_64_R8: addr = &uc->uc_mcontext.mc_r8; break;
+ case UNW_X86_64_R9: addr = &uc->uc_mcontext.mc_r9; break;
+ case UNW_X86_64_R10: addr = &uc->uc_mcontext.mc_r10; break;
+ case UNW_X86_64_R11: addr = &uc->uc_mcontext.mc_r11; break;
+ case UNW_X86_64_R12: addr = &uc->uc_mcontext.mc_r12; break;
+ case UNW_X86_64_R13: addr = &uc->uc_mcontext.mc_r13; break;
+ case UNW_X86_64_R14: addr = &uc->uc_mcontext.mc_r14; break;
+ case UNW_X86_64_R15: addr = &uc->uc_mcontext.mc_r15; break;
+ case UNW_X86_64_RDI: addr = &uc->uc_mcontext.mc_rdi; break;
+ case UNW_X86_64_RSI: addr = &uc->uc_mcontext.mc_rsi; break;
+ case UNW_X86_64_RBP: addr = &uc->uc_mcontext.mc_rbp; break;
+ case UNW_X86_64_RBX: addr = &uc->uc_mcontext.mc_rbx; break;
+ case UNW_X86_64_RDX: addr = &uc->uc_mcontext.mc_rdx; break;
+ case UNW_X86_64_RAX: addr = &uc->uc_mcontext.mc_rax; break;
+ case UNW_X86_64_RCX: addr = &uc->uc_mcontext.mc_rcx; break;
+ case UNW_X86_64_RSP: addr = &uc->uc_mcontext.mc_rsp; break;
+ case UNW_X86_64_RIP: addr = &uc->uc_mcontext.mc_rip; break;
+
+ default:
+ addr = NULL;
+ }
+ return addr;
+}
+
+HIDDEN NORETURN void
+x86_64_sigreturn (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ ucontext_t *uc = (ucontext_t *)(c->sigcontext_addr +
+ offsetof(struct sigframe, sf_uc));
+
+ uc->uc_mcontext.mc_r8 = c->uc->uc_mcontext.mc_r8;
+ uc->uc_mcontext.mc_r9 = c->uc->uc_mcontext.mc_r9;
+ uc->uc_mcontext.mc_r10 = c->uc->uc_mcontext.mc_r10;
+ uc->uc_mcontext.mc_r11 = c->uc->uc_mcontext.mc_r11;
+ uc->uc_mcontext.mc_r12 = c->uc->uc_mcontext.mc_r12;
+ uc->uc_mcontext.mc_r13 = c->uc->uc_mcontext.mc_r13;
+ uc->uc_mcontext.mc_r14 = c->uc->uc_mcontext.mc_r14;
+ uc->uc_mcontext.mc_r15 = c->uc->uc_mcontext.mc_r15;
+ uc->uc_mcontext.mc_rdi = c->uc->uc_mcontext.mc_rdi;
+ uc->uc_mcontext.mc_rsi = c->uc->uc_mcontext.mc_rsi;
+ uc->uc_mcontext.mc_rbp = c->uc->uc_mcontext.mc_rbp;
+ uc->uc_mcontext.mc_rbx = c->uc->uc_mcontext.mc_rbx;
+ uc->uc_mcontext.mc_rdx = c->uc->uc_mcontext.mc_rdx;
+ uc->uc_mcontext.mc_rax = c->uc->uc_mcontext.mc_rax;
+ uc->uc_mcontext.mc_rcx = c->uc->uc_mcontext.mc_rcx;
+ uc->uc_mcontext.mc_rsp = c->uc->uc_mcontext.mc_rsp;
+ uc->uc_mcontext.mc_rip = c->uc->uc_mcontext.mc_rip;
+
+ Debug (8, "resuming at ip=%llx via sigreturn(%p)\n",
+ (unsigned long long) c->dwarf.ip, uc);
+ sigreturn(uc);
+ abort();
+}
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/Gos-linux.c b/src/pal/src/libunwind/src/x86_64/Gos-linux.c
new file mode 100644
index 0000000000..bd142345ed
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Gos-linux.c
@@ -0,0 +1,156 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "ucontext_i.h"
+
+#include <sys/syscall.h>
+
+HIDDEN void
+tdep_fetch_frame (struct dwarf_cursor *dw, unw_word_t ip, int need_unwind_info)
+{
+ struct cursor *c = (struct cursor *) dw;
+ assert(! need_unwind_info || dw->pi_valid);
+ assert(! need_unwind_info || dw->pi.unwind_info);
+ if (dw->pi_valid
+ && dw->pi.unwind_info
+ && ((struct dwarf_cie_info *) dw->pi.unwind_info)->signal_frame)
+ c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME;
+ else
+ c->sigcontext_format = X86_64_SCF_NONE;
+
+ Debug(5, "fetch frame ip=0x%lx cfa=0x%lx format=%d\n",
+ dw->ip, dw->cfa, c->sigcontext_format);
+}
+
+HIDDEN int
+tdep_cache_frame (struct dwarf_cursor *dw)
+{
+ struct cursor *c = (struct cursor *) dw;
+
+ Debug(5, "cache frame ip=0x%lx cfa=0x%lx format=%d\n",
+ dw->ip, dw->cfa, c->sigcontext_format);
+ return c->sigcontext_format;
+}
+
+HIDDEN void
+tdep_reuse_frame (struct dwarf_cursor *dw, int frame)
+{
+ struct cursor *c = (struct cursor *) dw;
+ c->sigcontext_format = frame;
+ if (c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME)
+ {
+ c->frame_info.frame_type = UNW_X86_64_FRAME_SIGRETURN;
+ /* Offset from cfa to ucontext_t in signal frame. */
+ c->frame_info.cfa_reg_offset = 0;
+ c->sigcontext_addr = dw->cfa;
+ }
+
+ Debug(5, "reuse frame ip=0x%lx cfa=0x%lx format=%d addr=0x%lx offset=%+d\n",
+ dw->ip, dw->cfa, c->sigcontext_format, c->sigcontext_addr,
+ (c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME
+ ? c->frame_info.cfa_reg_offset : 0));
+}
+
+int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ return c->sigcontext_format != X86_64_SCF_NONE;
+}
+
+HIDDEN int
+x86_64_handle_signal_frame (unw_cursor_t *cursor)
+{
+#if UNW_DEBUG /* To silence compiler warnings */
+ /* Should not get here because we now use kernel-provided dwarf
+ information for the signal trampoline and dwarf_step() works.
+ Hence unw_step() should never call this function. Maybe
+ restore old non-dwarf signal handling here, but then the
+ gating on unw_is_signal_frame() needs to be removed. */
+ struct cursor *c = (struct cursor *) cursor;
+ Debug(1, "old format signal frame? format=%d addr=0x%lx cfa=0x%lx\n",
+ c->sigcontext_format, c->sigcontext_addr, c->dwarf.cfa);
+#endif
+ return -UNW_EBADFRAME;
+}
+
+#ifndef UNW_REMOTE_ONLY
+HIDDEN void *
+x86_64_r_uc_addr (ucontext_t *uc, int reg)
+{
+ /* NOTE: common_init() in init.h inlines these for fast path access. */
+ void *addr;
+
+ switch (reg)
+ {
+ case UNW_X86_64_R8: addr = &uc->uc_mcontext.gregs[REG_R8]; break;
+ case UNW_X86_64_R9: addr = &uc->uc_mcontext.gregs[REG_R9]; break;
+ case UNW_X86_64_R10: addr = &uc->uc_mcontext.gregs[REG_R10]; break;
+ case UNW_X86_64_R11: addr = &uc->uc_mcontext.gregs[REG_R11]; break;
+ case UNW_X86_64_R12: addr = &uc->uc_mcontext.gregs[REG_R12]; break;
+ case UNW_X86_64_R13: addr = &uc->uc_mcontext.gregs[REG_R13]; break;
+ case UNW_X86_64_R14: addr = &uc->uc_mcontext.gregs[REG_R14]; break;
+ case UNW_X86_64_R15: addr = &uc->uc_mcontext.gregs[REG_R15]; break;
+ case UNW_X86_64_RDI: addr = &uc->uc_mcontext.gregs[REG_RDI]; break;
+ case UNW_X86_64_RSI: addr = &uc->uc_mcontext.gregs[REG_RSI]; break;
+ case UNW_X86_64_RBP: addr = &uc->uc_mcontext.gregs[REG_RBP]; break;
+ case UNW_X86_64_RBX: addr = &uc->uc_mcontext.gregs[REG_RBX]; break;
+ case UNW_X86_64_RDX: addr = &uc->uc_mcontext.gregs[REG_RDX]; break;
+ case UNW_X86_64_RAX: addr = &uc->uc_mcontext.gregs[REG_RAX]; break;
+ case UNW_X86_64_RCX: addr = &uc->uc_mcontext.gregs[REG_RCX]; break;
+ case UNW_X86_64_RSP: addr = &uc->uc_mcontext.gregs[REG_RSP]; break;
+ case UNW_X86_64_RIP: addr = &uc->uc_mcontext.gregs[REG_RIP]; break;
+
+ default:
+ addr = NULL;
+ }
+ return addr;
+}
+
+/* sigreturn() is a no-op on x86_64 glibc. */
+HIDDEN NORETURN void
+x86_64_sigreturn (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
+ mcontext_t *sc_mcontext = &((ucontext_t*)sc)->uc_mcontext;
+ /* Copy in saved uc - all preserved regs are at the start of sigcontext */
+ memcpy(sc_mcontext, &c->uc->uc_mcontext,
+ DWARF_NUM_PRESERVED_REGS * sizeof(unw_word_t));
+
+ Debug (8, "resuming at ip=%llx via sigreturn(%p)\n",
+ (unsigned long long) c->dwarf.ip, sc);
+ __asm__ __volatile__ ("mov %0, %%rsp;"
+ "mov %1, %%rax;"
+ "syscall"
+ :: "r"(sc), "i"(SYS_rt_sigreturn)
+ : "memory");
+ abort();
+}
+
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/Greg_states_iterate.c b/src/pal/src/libunwind/src/x86_64/Greg_states_iterate.c
new file mode 100644
index 0000000000..a17dc1b561
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Greg_states_iterate.c
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+ unw_reg_states_callback cb, void *token)
+{
+ struct cursor *c = (struct cursor *) cursor;
+
+ return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
diff --git a/src/pal/src/libunwind/src/x86_64/Gregs.c b/src/pal/src/libunwind/src/x86_64/Gregs.c
new file mode 100644
index 0000000000..baf8a24f0b
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Gregs.c
@@ -0,0 +1,138 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2004 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+#if 0
+static inline dwarf_loc_t
+linux_scratch_loc (struct cursor *c, unw_regnum_t reg)
+{
+ unw_word_t addr = c->sigcontext_addr;
+
+ switch (c->sigcontext_format)
+ {
+ case X86_64_SCF_NONE:
+ return DWARF_REG_LOC (&c->dwarf, reg);
+
+ case X86_64_SCF_LINUX_RT_SIGFRAME:
+ addr += LINUX_UC_MCONTEXT_OFF;
+ break;
+
+ case X86_64_SCF_FREEBSD_SIGFRAME:
+ addr += FREEBSD_UC_MCONTEXT_OFF;
+ break;
+ }
+
+ return DWARF_REG_LOC (&c->dwarf, reg);
+
+}
+
+HIDDEN dwarf_loc_t
+x86_64_scratch_loc (struct cursor *c, unw_regnum_t reg)
+{
+ if (c->sigcontext_addr)
+ return linux_scratch_loc (c, reg);
+ else
+ return DWARF_REG_LOC (&c->dwarf, reg);
+}
+#endif
+
+HIDDEN int
+tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
+ int write)
+{
+ dwarf_loc_t loc = DWARF_NULL_LOC;
+ unsigned int mask;
+ int arg_num;
+
+ switch (reg)
+ {
+
+ case UNW_X86_64_RIP:
+ if (write)
+ c->dwarf.ip = *valp; /* also update the RIP cache */
+ loc = c->dwarf.loc[RIP];
+ break;
+
+ case UNW_X86_64_CFA:
+ case UNW_X86_64_RSP:
+ if (write)
+ return -UNW_EREADONLYREG;
+ *valp = c->dwarf.cfa;
+ return 0;
+
+ case UNW_X86_64_RAX:
+ case UNW_X86_64_RDX:
+ arg_num = reg - UNW_X86_64_RAX;
+ mask = (1 << arg_num);
+ if (write)
+ {
+ c->dwarf.eh_args[arg_num] = *valp;
+ c->dwarf.eh_valid_mask |= mask;
+ return 0;
+ }
+ else if ((c->dwarf.eh_valid_mask & mask) != 0)
+ {
+ *valp = c->dwarf.eh_args[arg_num];
+ return 0;
+ }
+ else
+ loc = c->dwarf.loc[(reg == UNW_X86_64_RAX) ? RAX : RDX];
+ break;
+
+ case UNW_X86_64_RCX: loc = c->dwarf.loc[RCX]; break;
+ case UNW_X86_64_RBX: loc = c->dwarf.loc[RBX]; break;
+
+ case UNW_X86_64_RBP: loc = c->dwarf.loc[RBP]; break;
+ case UNW_X86_64_RSI: loc = c->dwarf.loc[RSI]; break;
+ case UNW_X86_64_RDI: loc = c->dwarf.loc[RDI]; break;
+ case UNW_X86_64_R8: loc = c->dwarf.loc[R8]; break;
+ case UNW_X86_64_R9: loc = c->dwarf.loc[R9]; break;
+ case UNW_X86_64_R10: loc = c->dwarf.loc[R10]; break;
+ case UNW_X86_64_R11: loc = c->dwarf.loc[R11]; break;
+ case UNW_X86_64_R12: loc = c->dwarf.loc[R12]; break;
+ case UNW_X86_64_R13: loc = c->dwarf.loc[R13]; break;
+ case UNW_X86_64_R14: loc = c->dwarf.loc[R14]; break;
+ case UNW_X86_64_R15: loc = c->dwarf.loc[R15]; break;
+
+ default:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+ }
+
+ if (write)
+ return dwarf_put (&c->dwarf, loc, *valp);
+ else
+ return dwarf_get (&c->dwarf, loc, valp);
+}
+
+HIDDEN int
+tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
+ int write)
+{
+ return -UNW_EBADREG;
+}
diff --git a/src/pal/src/libunwind/src/x86_64/Gresume.c b/src/pal/src/libunwind/src/x86_64/Gresume.c
new file mode 100644
index 0000000000..944cdaae19
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Gresume.c
@@ -0,0 +1,123 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2002-2004 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdlib.h>
+
+#include "offsets.h"
+#include "unwind_i.h"
+
+#ifndef UNW_REMOTE_ONLY
+
+HIDDEN inline int
+x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ ucontext_t *uc = c->uc;
+
+ /* Ensure c->pi is up-to-date. On x86-64, it's relatively common to
+ be missing DWARF unwind info. We don't want to fail in that
+ case, because the frame-chain still would let us do a backtrace
+ at least. */
+ dwarf_make_proc_info (&c->dwarf);
+
+ if (unlikely (c->sigcontext_addr != X86_64_SCF_NONE))
+ {
+ x86_64_sigreturn(cursor);
+ abort();
+ }
+ else
+ {
+ Debug (8, "resuming at ip=%llx via setcontext()\n",
+ (unsigned long long) c->dwarf.ip);
+ setcontext (uc);
+ }
+ return -UNW_EINVAL;
+}
+
+#endif /* !UNW_REMOTE_ONLY */
+
+/* This routine is responsible for copying the register values in
+ cursor C and establishing them as the current machine state. */
+
+static inline int
+establish_machine_state (struct cursor *c)
+{
+ int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *,
+ int write, void *);
+ int (*access_fpreg) (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *,
+ int write, void *);
+ unw_addr_space_t as = c->dwarf.as;
+ void *arg = c->dwarf.as_arg;
+ unw_fpreg_t fpval;
+ unw_word_t val;
+ int reg;
+
+ access_reg = as->acc.access_reg;
+ access_fpreg = as->acc.access_fpreg;
+
+ Debug (8, "copying out cursor state\n");
+
+ for (reg = 0; reg <= UNW_REG_LAST; ++reg)
+ {
+ Debug (16, "copying %s %d\n", unw_regname (reg), reg);
+ if (unw_is_fpreg (reg))
+ {
+ if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0)
+ (*access_fpreg) (as, reg, &fpval, 1, arg);
+ }
+ else
+ {
+ if (tdep_access_reg (c, reg, &val, 0) >= 0)
+ (*access_reg) (as, reg, &val, 1, arg);
+ }
+ }
+
+ if (c->dwarf.args_size)
+ {
+ if (tdep_access_reg (c, UNW_X86_64_RSP, &val, 0) >= 0)
+ {
+ val += c->dwarf.args_size;
+ (*access_reg) (as, UNW_X86_64_RSP, &val, 1, arg);
+ }
+ }
+ return 0;
+}
+
+int
+unw_resume (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret;
+
+ Debug (1, "(cursor=%p)\n", c);
+
+ if ((ret = establish_machine_state (c)) < 0)
+ return ret;
+
+ return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c,
+ c->dwarf.as_arg);
+}
diff --git a/src/pal/src/libunwind/src/x86_64/Gstash_frame.c b/src/pal/src/libunwind/src/x86_64/Gstash_frame.c
new file mode 100644
index 0000000000..2c7bc312e2
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Gstash_frame.c
@@ -0,0 +1,119 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "ucontext_i.h"
+
+HIDDEN void
+tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs)
+{
+ struct cursor *c = (struct cursor *) dwarf_to_cursor (d);
+ unw_tdep_frame_t *f = &c->frame_info;
+
+ Debug (4, "ip=0x%lx cfa=0x%lx type %d cfa [where=%d val=%ld] cfaoff=%ld"
+ " ra=0x%lx rbp [where=%d val=%ld @0x%lx] rsp [where=%d val=%ld @0x%lx]\n",
+ d->ip, d->cfa, f->frame_type,
+ rs->reg.where[DWARF_CFA_REG_COLUMN],
+ rs->reg.val[DWARF_CFA_REG_COLUMN],
+ rs->reg.val[DWARF_CFA_OFF_COLUMN],
+ DWARF_GET_LOC(d->loc[rs->ret_addr_column]),
+ rs->reg.where[RBP], rs->reg.val[RBP], DWARF_GET_LOC(d->loc[RBP]),
+ rs->reg.where[RSP], rs->reg.val[RSP], DWARF_GET_LOC(d->loc[RSP]));
+
+ if (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_EXPR &&
+ rs->reg.where[RBP] == DWARF_WHERE_EXPR) {
+ /* Check for GCC generated alignment frame for rsp. A simple
+ * def_cfa_expr that loads a constant offset from rbp, where the
+ * addres of the rip was pushed on the stack */
+ unw_word_t cfa_addr = rs->reg.val[DWARF_CFA_REG_COLUMN];
+ unw_word_t rbp_addr = rs->reg.val[RBP];
+ unw_word_t cfa_offset;
+
+ int ret = dwarf_stack_aligned(d, cfa_addr, rbp_addr, &cfa_offset);
+ if (ret) {
+ f->frame_type = UNW_X86_64_FRAME_ALIGNED;
+ f->cfa_reg_offset = cfa_offset;
+ f->cfa_reg_rsp = 0;
+ }
+ }
+
+ /* A standard frame is defined as:
+ - CFA is register-relative offset off RBP or RSP;
+ - Return address is saved at CFA-8;
+ - RBP is unsaved or saved at CFA+offset, offset != -1;
+ - RSP is unsaved or saved at CFA+offset, offset != -1. */
+ if (f->frame_type == UNW_X86_64_FRAME_OTHER
+ && (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG)
+ && (rs->reg.val[DWARF_CFA_REG_COLUMN] == RBP
+ || rs->reg.val[DWARF_CFA_REG_COLUMN] == RSP)
+ && labs((long) rs->reg.val[DWARF_CFA_OFF_COLUMN]) < (1 << 28)
+ && DWARF_GET_LOC(d->loc[rs->ret_addr_column]) == d->cfa-8
+ && (rs->reg.where[RBP] == DWARF_WHERE_UNDEF
+ || rs->reg.where[RBP] == DWARF_WHERE_SAME
+ || (rs->reg.where[RBP] == DWARF_WHERE_CFAREL
+ && labs((long) rs->reg.val[RBP]) < (1 << 14)
+ && rs->reg.val[RBP]+1 != 0))
+ && (rs->reg.where[RSP] == DWARF_WHERE_UNDEF
+ || rs->reg.where[RSP] == DWARF_WHERE_SAME
+ || (rs->reg.where[RSP] == DWARF_WHERE_CFAREL
+ && labs((long) rs->reg.val[RSP]) < (1 << 14)
+ && rs->reg.val[RSP]+1 != 0)))
+ {
+ /* Save information for a standard frame. */
+ f->frame_type = UNW_X86_64_FRAME_STANDARD;
+ f->cfa_reg_rsp = (rs->reg.val[DWARF_CFA_REG_COLUMN] == RSP);
+ f->cfa_reg_offset = rs->reg.val[DWARF_CFA_OFF_COLUMN];
+ if (rs->reg.where[RBP] == DWARF_WHERE_CFAREL)
+ f->rbp_cfa_offset = rs->reg.val[RBP];
+ if (rs->reg.where[RSP] == DWARF_WHERE_CFAREL)
+ f->rsp_cfa_offset = rs->reg.val[RSP];
+ Debug (4, " standard frame\n");
+ }
+
+ /* Signal frame was detected via augmentation in tdep_fetch_frame() */
+ else if (f->frame_type == UNW_X86_64_FRAME_SIGRETURN)
+ {
+ /* Later we are going to fish out {RBP,RSP,RIP} from sigcontext via
+ their ucontext_t offsets. Confirm DWARF info agrees with the
+ offsets we expect. */
+
+#ifndef NDEBUG
+ const unw_word_t uc = c->sigcontext_addr;
+
+ assert (DWARF_GET_LOC(d->loc[RIP]) - uc == UC_MCONTEXT_GREGS_RIP);
+ assert (DWARF_GET_LOC(d->loc[RBP]) - uc == UC_MCONTEXT_GREGS_RBP);
+ assert (DWARF_GET_LOC(d->loc[RSP]) - uc == UC_MCONTEXT_GREGS_RSP);
+#endif
+
+ Debug (4, " sigreturn frame\n");
+ }
+
+ else if (f->frame_type == UNW_X86_64_FRAME_ALIGNED) {
+ Debug (4, " aligned frame, offset %li\n", f->cfa_reg_offset);
+ }
+
+ /* PLT and guessed RBP-walked frames are handled in unw_step(). */
+ else
+ Debug (4, " unusual frame\n");
+}
diff --git a/src/pal/src/libunwind/src/x86_64/Gstep.c b/src/pal/src/libunwind/src/x86_64/Gstep.c
new file mode 100644
index 0000000000..10498170ac
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Gstep.c
@@ -0,0 +1,227 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include <signal.h>
+
+/* Recognise PLT entries such as:
+ 3bdf0: ff 25 e2 49 13 00 jmpq *0x1349e2(%rip)
+ 3bdf6: 68 ae 03 00 00 pushq $0x3ae
+ 3bdfb: e9 00 c5 ff ff jmpq 38300 <_init+0x18> */
+static int
+is_plt_entry (struct dwarf_cursor *c)
+{
+ unw_word_t w0, w1;
+ unw_accessors_t *a;
+ int ret;
+
+ a = unw_get_accessors_int (c->as);
+ if ((ret = (*a->access_mem) (c->as, c->ip, &w0, 0, c->as_arg)) < 0
+ || (ret = (*a->access_mem) (c->as, c->ip + 8, &w1, 0, c->as_arg)) < 0)
+ return 0;
+
+ ret = (((w0 & 0xffff) == 0x25ff)
+ && (((w0 >> 48) & 0xff) == 0x68)
+ && (((w1 >> 24) & 0xff) == 0xe9));
+
+ Debug (14, "ip=0x%lx => 0x%016lx 0x%016lx, ret = %d\n", c->ip, w0, w1, ret);
+ return ret;
+}
+
+int
+unw_step (unw_cursor_t *cursor)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ int ret, i;
+
+#if CONSERVATIVE_CHECKS
+ int val = c->validate;
+ c->validate = 1;
+#endif
+
+ Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx)\n",
+ c, c->dwarf.ip, c->dwarf.cfa);
+
+ /* Try DWARF-based unwinding... */
+ c->sigcontext_format = X86_64_SCF_NONE;
+ ret = dwarf_step (&c->dwarf);
+
+#if CONSERVATIVE_CHECKS
+ c->validate = val;
+#endif
+
+ if (ret < 0 && ret != -UNW_ENOINFO)
+ {
+ Debug (2, "returning %d\n", ret);
+ return ret;
+ }
+
+ if (likely (ret >= 0))
+ {
+ /* x86_64 ABI specifies that end of call-chain is marked with a
+ NULL RBP or undefined return address */
+ if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP]))
+ {
+ c->dwarf.ip = 0;
+ ret = 0;
+ }
+ }
+ else
+ {
+ /* DWARF failed. There isn't much of a usable frame-chain on x86-64,
+ but we do need to handle two special-cases:
+
+ (i) signal trampoline: Old kernels and older libcs don't
+ export the vDSO needed to get proper unwind info for the
+ trampoline. Recognize that case by looking at the code
+ and filling in things by hand.
+
+ (ii) PLT (shared-library) call-stubs: PLT stubs are invoked
+ via CALLQ. Try this for all non-signal trampoline
+ code. */
+
+ unw_word_t prev_ip = c->dwarf.ip, prev_cfa = c->dwarf.cfa;
+ struct dwarf_loc rbp_loc, rsp_loc, rip_loc;
+
+ /* We could get here because of missing/bad unwind information.
+ Validate all addresses before dereferencing. */
+ c->validate = 1;
+
+ Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);
+
+ if (unw_is_signal_frame (cursor) > 0)
+ {
+ ret = x86_64_handle_signal_frame(cursor);
+ if (ret < 0)
+ {
+ Debug (2, "returning 0\n");
+ return 0;
+ }
+ }
+ else if (is_plt_entry (&c->dwarf))
+ {
+ /* Like regular frame, CFA = RSP+8, RA = [CFA-8], no regs saved. */
+ Debug (2, "found plt entry\n");
+ c->frame_info.cfa_reg_offset = 8;
+ c->frame_info.cfa_reg_rsp = -1;
+ c->frame_info.frame_type = UNW_X86_64_FRAME_STANDARD;
+ c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0);
+ c->dwarf.cfa += 8;
+ }
+ else if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP]))
+ {
+ for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
+ c->dwarf.loc[i] = DWARF_NULL_LOC;
+ }
+ else
+ {
+ unw_word_t rbp;
+
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[RBP], &rbp);
+ if (ret < 0)
+ {
+ Debug (2, "returning %d [RBP=0x%lx]\n", ret,
+ DWARF_GET_LOC (c->dwarf.loc[RBP]));
+ return ret;
+ }
+
+ if (!rbp)
+ {
+ /* Looks like we may have reached the end of the call-chain. */
+ rbp_loc = DWARF_NULL_LOC;
+ rsp_loc = DWARF_NULL_LOC;
+ rip_loc = DWARF_NULL_LOC;
+ }
+ else
+ {
+ unw_word_t rbp1 = 0;
+ rbp_loc = DWARF_LOC(rbp, 0);
+ rsp_loc = DWARF_NULL_LOC;
+ rip_loc = DWARF_LOC (rbp + 8, 0);
+ ret = dwarf_get (&c->dwarf, rbp_loc, &rbp1);
+ Debug (1, "[RBP=0x%lx] = 0x%lx (cfa = 0x%lx) -> 0x%lx\n",
+ (unsigned long) DWARF_GET_LOC (c->dwarf.loc[RBP]),
+ rbp, c->dwarf.cfa, rbp1);
+
+ /* Heuristic to determine incorrect guess. For RBP to be a
+ valid frame it needs to be above current CFA, but don't
+ let it go more than a little. Note that we can't deduce
+ anything about new RBP (rbp1) since it may not be a frame
+ pointer in the frame above. Just check we get the value. */
+ if (ret < 0
+ || rbp < c->dwarf.cfa
+ || (rbp - c->dwarf.cfa) > 0x4000)
+ {
+ rip_loc = DWARF_NULL_LOC;
+ rbp_loc = DWARF_NULL_LOC;
+ }
+
+ c->frame_info.frame_type = UNW_X86_64_FRAME_GUESSED;
+ c->frame_info.cfa_reg_rsp = 0;
+ c->frame_info.cfa_reg_offset = 16;
+ c->frame_info.rbp_cfa_offset = -16;
+ c->dwarf.cfa += 16;
+ }
+
+ /* Mark all registers unsaved */
+ for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
+ c->dwarf.loc[i] = DWARF_NULL_LOC;
+
+ c->dwarf.loc[RBP] = rbp_loc;
+ c->dwarf.loc[RSP] = rsp_loc;
+ c->dwarf.loc[RIP] = rip_loc;
+ c->dwarf.use_prev_instr = 1;
+ }
+
+ if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP]))
+ {
+ ret = 0;
+ Debug (2, "NULL %%rbp loc, returning %d\n", ret);
+ return ret;
+ }
+ if (!DWARF_IS_NULL_LOC (c->dwarf.loc[RIP]))
+ {
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip);
+ Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n",
+ (unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RIP]),
+ (unsigned long long) c->dwarf.ip);
+ if (ret < 0)
+ {
+ Debug (2, "returning %d\n", ret);
+ return ret;
+ }
+ ret = 1;
+ }
+ else
+ c->dwarf.ip = 0;
+
+ if (c->dwarf.ip == prev_ip && c->dwarf.cfa == prev_cfa)
+ return -UNW_EBADFRAME;
+ }
+ Debug (2, "returning %d\n", ret);
+ return ret;
+}
diff --git a/src/pal/src/libunwind/src/x86_64/Gtrace.c b/src/pal/src/libunwind/src/x86_64/Gtrace.c
new file mode 100644
index 0000000000..741227105e
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Gtrace.c
@@ -0,0 +1,551 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+#include "ucontext_i.h"
+#include <signal.h>
+#include <limits.h>
+
+#pragma weak pthread_once
+#pragma weak pthread_key_create
+#pragma weak pthread_getspecific
+#pragma weak pthread_setspecific
+
+/* Initial hash table size. Table expands by 2 bits (times four). */
+#define HASH_MIN_BITS 14
+
+typedef struct
+{
+ unw_tdep_frame_t *frames;
+ size_t log_size;
+ size_t used;
+ size_t dtor_count; /* Counts how many times our destructor has already
+ been called. */
+} unw_trace_cache_t;
+
+static const unw_tdep_frame_t empty_frame = { 0, UNW_X86_64_FRAME_OTHER, -1, -1, 0, -1, -1 };
+static define_lock (trace_init_lock);
+static pthread_once_t trace_cache_once = PTHREAD_ONCE_INIT;
+static sig_atomic_t trace_cache_once_happen;
+static pthread_key_t trace_cache_key;
+static struct mempool trace_cache_pool;
+static __thread unw_trace_cache_t *tls_cache;
+static __thread int tls_cache_destroyed;
+
+/* Free memory for a thread's trace cache. */
+static void
+trace_cache_free (void *arg)
+{
+ unw_trace_cache_t *cache = arg;
+ if (++cache->dtor_count < PTHREAD_DESTRUCTOR_ITERATIONS)
+ {
+ /* Not yet our turn to get destroyed. Re-install ourselves into the key. */
+ pthread_setspecific(trace_cache_key, cache);
+ Debug(5, "delayed freeing cache %p (%zx to go)\n", cache,
+ PTHREAD_DESTRUCTOR_ITERATIONS - cache->dtor_count);
+ return;
+ }
+ tls_cache_destroyed = 1;
+ tls_cache = NULL;
+ munmap (cache->frames, (1u << cache->log_size) * sizeof(unw_tdep_frame_t));
+ mempool_free (&trace_cache_pool, cache);
+ Debug(5, "freed cache %p\n", cache);
+}
+
+/* Initialise frame tracing for threaded use. */
+static void
+trace_cache_init_once (void)
+{
+ pthread_key_create (&trace_cache_key, &trace_cache_free);
+ mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0);
+ trace_cache_once_happen = 1;
+}
+
+static unw_tdep_frame_t *
+trace_cache_buckets (size_t n)
+{
+ unw_tdep_frame_t *frames;
+ size_t i;
+
+ GET_MEMORY(frames, n * sizeof (unw_tdep_frame_t));
+ if (likely(frames != NULL))
+ for (i = 0; i < n; ++i)
+ frames[i] = empty_frame;
+
+ return frames;
+}
+
+/* Allocate and initialise hash table for frame cache lookups.
+ Returns the cache initialised with (1u << HASH_LOW_BITS) hash
+ buckets, or NULL if there was a memory allocation problem. */
+static unw_trace_cache_t *
+trace_cache_create (void)
+{
+ unw_trace_cache_t *cache;
+
+ if (tls_cache_destroyed)
+ {
+ /* The current thread is in the process of exiting. Don't recreate
+ cache, as we wouldn't have another chance to free it. */
+ Debug(5, "refusing to reallocate cache: "
+ "thread-locals are being deallocated\n");
+ return NULL;
+ }
+
+ if (! (cache = mempool_alloc(&trace_cache_pool)))
+ {
+ Debug(5, "failed to allocate cache\n");
+ return NULL;
+ }
+
+ if (! (cache->frames = trace_cache_buckets(1u << HASH_MIN_BITS)))
+ {
+ Debug(5, "failed to allocate buckets\n");
+ mempool_free(&trace_cache_pool, cache);
+ return NULL;
+ }
+
+ cache->log_size = HASH_MIN_BITS;
+ cache->used = 0;
+ cache->dtor_count = 0;
+ tls_cache_destroyed = 0; /* Paranoia: should already be 0. */
+ Debug(5, "allocated cache %p\n", cache);
+ return cache;
+}
+
+/* Expand the hash table in the frame cache if possible. This always
+ quadruples the hash size, and clears all previous frame entries. */
+static int
+trace_cache_expand (unw_trace_cache_t *cache)
+{
+ size_t old_size = (1u << cache->log_size);
+ size_t new_log_size = cache->log_size + 2;
+ unw_tdep_frame_t *new_frames = trace_cache_buckets (1u << new_log_size);
+
+ if (unlikely(! new_frames))
+ {
+ Debug(5, "failed to expand cache to 2^%lu buckets\n", new_log_size);
+ return -UNW_ENOMEM;
+ }
+
+ Debug(5, "expanded cache from 2^%lu to 2^%lu buckets\n", cache->log_size, new_log_size);
+ munmap(cache->frames, old_size * sizeof(unw_tdep_frame_t));
+ cache->frames = new_frames;
+ cache->log_size = new_log_size;
+ cache->used = 0;
+ return 0;
+}
+
+static unw_trace_cache_t *
+trace_cache_get_unthreaded (void)
+{
+ unw_trace_cache_t *cache;
+ intrmask_t saved_mask;
+ static unw_trace_cache_t *global_cache = NULL;
+ lock_acquire (&trace_init_lock, saved_mask);
+ if (! global_cache)
+ {
+ mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0);
+ global_cache = trace_cache_create ();
+ }
+ cache = global_cache;
+ lock_release (&trace_init_lock, saved_mask);
+ Debug(5, "using cache %p\n", cache);
+ return cache;
+}
+
+/* Get the frame cache for the current thread. Create it if there is none. */
+static unw_trace_cache_t *
+trace_cache_get (void)
+{
+ unw_trace_cache_t *cache;
+ if (likely (pthread_once != NULL))
+ {
+ pthread_once(&trace_cache_once, &trace_cache_init_once);
+ if (!trace_cache_once_happen)
+ {
+ return trace_cache_get_unthreaded();
+ }
+ if (! (cache = tls_cache))
+ {
+ cache = trace_cache_create();
+ pthread_setspecific(trace_cache_key, cache);
+ tls_cache = cache;
+ }
+ Debug(5, "using cache %p\n", cache);
+ return cache;
+ }
+ else
+ {
+ return trace_cache_get_unthreaded();
+ }
+}
+
+/* Initialise frame properties for address cache slot F at address
+ RIP using current CFA, RBP and RSP values. Modifies CURSOR to
+ that location, performs one unw_step(), and fills F with what
+ was discovered about the location. Returns F.
+
+ FIXME: This probably should tell DWARF handling to never evaluate
+ or use registers other than RBP, RSP and RIP in case there is
+ highly unusual unwind info which uses these creatively. */
+static unw_tdep_frame_t *
+trace_init_addr (unw_tdep_frame_t *f,
+ unw_cursor_t *cursor,
+ unw_word_t cfa,
+ unw_word_t rip,
+ unw_word_t rbp,
+ unw_word_t rsp)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ struct dwarf_cursor *d = &c->dwarf;
+ int ret = -UNW_EINVAL;
+
+ /* Initialise frame properties: unknown, not last. */
+ f->virtual_address = rip;
+ f->frame_type = UNW_X86_64_FRAME_OTHER;
+ f->last_frame = 0;
+ f->cfa_reg_rsp = -1;
+ f->cfa_reg_offset = 0;
+ f->rbp_cfa_offset = -1;
+ f->rsp_cfa_offset = -1;
+
+ /* Reinitialise cursor to this instruction - but undo next/prev RIP
+ adjustment because unw_step will redo it - and force RIP, RBP
+ RSP into register locations (=~ ucontext we keep), then set
+ their desired values. Then perform the step. */
+ d->ip = rip + d->use_prev_instr;
+ d->cfa = cfa;
+ d->loc[UNW_X86_64_RIP] = DWARF_REG_LOC (d, UNW_X86_64_RIP);
+ d->loc[UNW_X86_64_RBP] = DWARF_REG_LOC (d, UNW_X86_64_RBP);
+ d->loc[UNW_X86_64_RSP] = DWARF_REG_LOC (d, UNW_X86_64_RSP);
+ c->frame_info = *f;
+
+ if (likely(dwarf_put (d, d->loc[UNW_X86_64_RIP], rip) >= 0)
+ && likely(dwarf_put (d, d->loc[UNW_X86_64_RBP], rbp) >= 0)
+ && likely(dwarf_put (d, d->loc[UNW_X86_64_RSP], rsp) >= 0)
+ && likely((ret = unw_step (cursor)) >= 0))
+ *f = c->frame_info;
+
+ /* If unw_step() stopped voluntarily, remember that, even if it
+ otherwise could not determine anything useful. This avoids
+ failing trace if we hit frames without unwind info, which is
+ common for the outermost frame (CRT stuff) on many systems.
+ This avoids failing trace in very common circumstances; failing
+ to unw_step() loop wouldn't produce any better result. */
+ if (ret == 0)
+ f->last_frame = -1;
+
+ Debug (3, "frame va %lx type %d last %d cfa %s+%d rbp @ cfa%+d rsp @ cfa%+d\n",
+ f->virtual_address, f->frame_type, f->last_frame,
+ f->cfa_reg_rsp ? "rsp" : "rbp", f->cfa_reg_offset,
+ f->rbp_cfa_offset, f->rsp_cfa_offset);
+
+ return f;
+}
+
+/* Look up and if necessary fill in frame attributes for address RIP
+ in CACHE using current CFA, RBP and RSP values. Uses CURSOR to
+ perform any unwind steps necessary to fill the cache. Returns the
+ frame cache slot which describes RIP. */
+static unw_tdep_frame_t *
+trace_lookup (unw_cursor_t *cursor,
+ unw_trace_cache_t *cache,
+ unw_word_t cfa,
+ unw_word_t rip,
+ unw_word_t rbp,
+ unw_word_t rsp)
+{
+ /* First look up for previously cached information using cache as
+ linear probing hash table with probe step of 1. Majority of
+ lookups should be completed within few steps, but it is very
+ important the hash table does not fill up, or performance falls
+ off the cliff. */
+ uint64_t i, addr;
+ uint64_t cache_size = 1u << cache->log_size;
+ uint64_t slot = ((rip * 0x9e3779b97f4a7c16) >> 43) & (cache_size-1);
+ unw_tdep_frame_t *frame;
+
+ for (i = 0; i < 16; ++i)
+ {
+ frame = &cache->frames[slot];
+ addr = frame->virtual_address;
+
+ /* Return if we found the address. */
+ if (likely(addr == rip))
+ {
+ Debug (4, "found address after %ld steps\n", i);
+ return frame;
+ }
+
+ /* If slot is empty, reuse it. */
+ if (likely(! addr))
+ break;
+
+ /* Linear probe to next slot candidate, step = 1. */
+ if (++slot >= cache_size)
+ slot -= cache_size;
+ }
+
+ /* If we collided after 16 steps, or if the hash is more than half
+ full, force the hash to expand. Fill the selected slot, whether
+ it's free or collides. Note that hash expansion drops previous
+ contents; further lookups will refill the hash. */
+ Debug (4, "updating slot %lu after %ld steps, replacing 0x%lx\n", slot, i, addr);
+ if (unlikely(addr || cache->used >= cache_size / 2))
+ {
+ if (unlikely(trace_cache_expand (cache) < 0))
+ return NULL;
+
+ cache_size = 1u << cache->log_size;
+ slot = ((rip * 0x9e3779b97f4a7c16) >> 43) & (cache_size-1);
+ frame = &cache->frames[slot];
+ addr = frame->virtual_address;
+ }
+
+ if (! addr)
+ ++cache->used;
+
+ return trace_init_addr (frame, cursor, cfa, rip, rbp, rsp);
+}
+
+/* Fast stack backtrace for x86-64.
+
+ This is used by backtrace() implementation to accelerate frequent
+ queries for current stack, without any desire to unwind. It fills
+ BUFFER with the call tree from CURSOR upwards for at most SIZE
+ stack levels. The first frame, backtrace itself, is omitted. When
+ called, SIZE should give the maximum number of entries that can be
+ stored into BUFFER. Uses an internal thread-specific cache to
+ accelerate queries.
+
+ The caller should fall back to a unw_step() loop if this function
+ fails by returning -UNW_ESTOPUNWIND, meaning the routine hit a
+ stack frame that is too complex to be traced in the fast path.
+
+ This function is tuned for clients which only need to walk the
+ stack to get the call tree as fast as possible but without any
+ other details, for example profilers sampling the stack thousands
+ to millions of times per second. The routine handles the most
+ common x86-64 ABI stack layouts: CFA is RBP or RSP plus/minus
+ constant offset, return address is at CFA-8, and RBP and RSP are
+ either unchanged or saved on stack at constant offset from the CFA;
+ the signal return frame; and frames without unwind info provided
+ they are at the outermost (final) frame or can conservatively be
+ assumed to be frame-pointer based.
+
+ Any other stack layout will cause the routine to give up. There
+ are only a handful of relatively rarely used functions which do
+ not have a stack in the standard form: vfork, longjmp, setcontext
+ and _dl_runtime_profile on common linux systems for example.
+
+ On success BUFFER and *SIZE reflect the trace progress up to *SIZE
+ stack levels or the outermost frame, which ever is less. It may
+ stop short of outermost frame if unw_step() loop would also do so,
+ e.g. if there is no more unwind information; this is not reported
+ as an error.
+
+ The function returns a negative value for errors, -UNW_ESTOPUNWIND
+ if tracing stopped because of an unusual frame unwind info. The
+ BUFFER and *SIZE reflect tracing progress up to the error frame.
+
+ Callers of this function would normally look like this:
+
+ unw_cursor_t cur;
+ unw_context_t ctx;
+ void addrs[128];
+ int depth = 128;
+ int ret;
+
+ unw_getcontext(&ctx);
+ unw_init_local(&cur, &ctx);
+ if ((ret = unw_tdep_trace(&cur, addrs, &depth)) < 0)
+ {
+ depth = 0;
+ unw_getcontext(&ctx);
+ unw_init_local(&cur, &ctx);
+ while ((ret = unw_step(&cur)) > 0 && depth < 128)
+ {
+ unw_word_t ip;
+ unw_get_reg(&cur, UNW_REG_IP, &ip);
+ addresses[depth++] = (void *) ip;
+ }
+ }
+*/
+HIDDEN int
+tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
+{
+ struct cursor *c = (struct cursor *) cursor;
+ struct dwarf_cursor *d = &c->dwarf;
+ unw_trace_cache_t *cache;
+ unw_word_t rbp, rsp, rip, cfa;
+ int maxdepth = 0;
+ int depth = 0;
+ int ret;
+
+ /* Check input parametres. */
+ if (unlikely(! cursor || ! buffer || ! size || (maxdepth = *size) <= 0))
+ return -UNW_EINVAL;
+
+ Debug (1, "begin ip 0x%lx cfa 0x%lx\n", d->ip, d->cfa);
+
+ /* Tell core dwarf routines to call back to us. */
+ d->stash_frames = 1;
+
+ /* Determine initial register values. These are direct access safe
+ because we know they come from the initial machine context. */
+ rip = d->ip;
+ rsp = cfa = d->cfa;
+ ACCESS_MEM_FAST(ret, 0, d, DWARF_GET_LOC(d->loc[UNW_X86_64_RBP]), rbp);
+ assert(ret == 0);
+
+ /* Get frame cache. */
+ if (unlikely(! (cache = trace_cache_get())))
+ {
+ Debug (1, "returning %d, cannot get trace cache\n", -UNW_ENOMEM);
+ *size = 0;
+ d->stash_frames = 0;
+ return -UNW_ENOMEM;
+ }
+
+ /* Trace the stack upwards, starting from current RIP. Adjust
+ the RIP address for previous/next instruction as the main
+ unwinding logic would also do. We undo this before calling
+ back into unw_step(). */
+ while (depth < maxdepth)
+ {
+ rip -= d->use_prev_instr;
+ Debug (2, "depth %d cfa 0x%lx rip 0x%lx rsp 0x%lx rbp 0x%lx\n",
+ depth, cfa, rip, rsp, rbp);
+
+ /* See if we have this address cached. If not, evaluate enough of
+ the dwarf unwind information to fill the cache line data, or to
+ decide this frame cannot be handled in fast trace mode. We
+ cache negative results too to prevent unnecessary dwarf parsing
+ for common failures. */
+ unw_tdep_frame_t *f = trace_lookup (cursor, cache, cfa, rip, rbp, rsp);
+
+ /* If we don't have information for this frame, give up. */
+ if (unlikely(! f))
+ {
+ ret = -UNW_ENOINFO;
+ break;
+ }
+
+ Debug (3, "frame va %lx type %d last %d cfa %s+%d rbp @ cfa%+d rsp @ cfa%+d\n",
+ f->virtual_address, f->frame_type, f->last_frame,
+ f->cfa_reg_rsp ? "rsp" : "rbp", f->cfa_reg_offset,
+ f->rbp_cfa_offset, f->rsp_cfa_offset);
+
+ assert (f->virtual_address == rip);
+
+ /* Stop if this was the last frame. In particular don't evaluate
+ new register values as it may not be safe - we don't normally
+ run with full validation on, and do not want to - and there's
+ enough bad unwind info floating around that we need to trust
+ what unw_step() previously said, in potentially bogus frames. */
+ if (f->last_frame)
+ break;
+
+ /* Evaluate CFA and registers for the next frame. */
+ switch (f->frame_type)
+ {
+ case UNW_X86_64_FRAME_GUESSED:
+ /* Fall thru to standard processing after forcing validation. */
+ c->validate = 1;
+
+ case UNW_X86_64_FRAME_STANDARD:
+ /* Advance standard traceable frame. */
+ cfa = (f->cfa_reg_rsp ? rsp : rbp) + f->cfa_reg_offset;
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa - 8, rip);
+ if (likely(ret >= 0) && likely(f->rbp_cfa_offset != -1))
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->rbp_cfa_offset, rbp);
+
+ /* Don't bother reading RSP from DWARF, CFA becomes new RSP. */
+ rsp = cfa;
+
+ /* Next frame needs to back up for unwind info lookup. */
+ d->use_prev_instr = 1;
+ break;
+
+ case UNW_X86_64_FRAME_SIGRETURN:
+ cfa = cfa + f->cfa_reg_offset; /* cfa now points to ucontext_t. */
+
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa + UC_MCONTEXT_GREGS_RIP, rip);
+ if (likely(ret >= 0))
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa + UC_MCONTEXT_GREGS_RBP, rbp);
+ if (likely(ret >= 0))
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa + UC_MCONTEXT_GREGS_RSP, rsp);
+
+ /* Resume stack at signal restoration point. The stack is not
+ necessarily continuous here, especially with sigaltstack(). */
+ cfa = rsp;
+
+ /* Next frame should not back up. */
+ d->use_prev_instr = 0;
+ break;
+
+ case UNW_X86_64_FRAME_ALIGNED:
+ /* Address of RIP was pushed on the stack via a simple
+ * def_cfa_expr - result stack offset stored in cfa_reg_offset */
+ cfa = (f->cfa_reg_rsp ? rsp : rbp) + f->cfa_reg_offset;
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa, cfa);
+ if (likely(ret >= 0))
+ ACCESS_MEM_FAST(ret, c->validate, d, cfa - 8, rip);
+ if (likely(ret >= 0))
+ ACCESS_MEM_FAST(ret, c->validate, d, rbp, rbp);
+
+ /* Don't bother reading RSP from DWARF, CFA becomes new RSP. */
+ rsp = cfa;
+
+ /* Next frame needs to back up for unwind info lookup. */
+ d->use_prev_instr = 1;
+
+ break;
+
+ default:
+ /* We cannot trace through this frame, give up and tell the
+ caller we had to stop. Data collected so far may still be
+ useful to the caller, so let it know how far we got. */
+ ret = -UNW_ESTOPUNWIND;
+ break;
+ }
+
+ Debug (4, "new cfa 0x%lx rip 0x%lx rsp 0x%lx rbp 0x%lx\n",
+ cfa, rip, rsp, rbp);
+
+ /* If we failed or ended up somewhere bogus, stop. */
+ if (unlikely(ret < 0 || rip < 0x4000))
+ break;
+
+ /* Record this address in stack trace. We skipped the first address. */
+ buffer[depth++] = (void *) (rip - d->use_prev_instr);
+ }
+
+#if UNW_DEBUG
+ Debug (1, "returning %d, depth %d\n", ret, depth);
+#endif
+ *size = depth;
+ return ret;
+}
diff --git a/src/pal/src/libunwind/src/x86_64/Lapply_reg_state.c b/src/pal/src/libunwind/src/x86_64/Lapply_reg_state.c
new file mode 100644
index 0000000000..7ebada480e
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Lapply_reg_state.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/Lcreate_addr_space.c b/src/pal/src/libunwind/src/x86_64/Lcreate_addr_space.c
new file mode 100644
index 0000000000..0f2dc6be90
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Lcreate_addr_space.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gcreate_addr_space.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/Lget_proc_info.c b/src/pal/src/libunwind/src/x86_64/Lget_proc_info.c
new file mode 100644
index 0000000000..69028b019f
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Lget_proc_info.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_proc_info.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/Lget_save_loc.c b/src/pal/src/libunwind/src/x86_64/Lget_save_loc.c
new file mode 100644
index 0000000000..9ea048a907
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Lget_save_loc.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_save_loc.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/Lglobal.c b/src/pal/src/libunwind/src/x86_64/Lglobal.c
new file mode 100644
index 0000000000..8c43a67c0f
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Lglobal.c
@@ -0,0 +1,6 @@
+#define UNW_LOCAL_ONLY
+#include "config.h"
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gglobal.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/Linit.c b/src/pal/src/libunwind/src/x86_64/Linit.c
new file mode 100644
index 0000000000..e9abfdd46a
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Linit.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/Linit_local.c b/src/pal/src/libunwind/src/x86_64/Linit_local.c
new file mode 100644
index 0000000000..68a1687e85
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Linit_local.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_local.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/Linit_remote.c b/src/pal/src/libunwind/src/x86_64/Linit_remote.c
new file mode 100644
index 0000000000..58cb04ab7c
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Linit_remote.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_remote.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/Los-freebsd.c b/src/pal/src/libunwind/src/x86_64/Los-freebsd.c
new file mode 100644
index 0000000000..a75a205df1
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Los-freebsd.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gos-freebsd.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/Los-linux.c b/src/pal/src/libunwind/src/x86_64/Los-linux.c
new file mode 100644
index 0000000000..3cc18aabcc
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Los-linux.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gos-linux.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/Lreg_states_iterate.c b/src/pal/src/libunwind/src/x86_64/Lreg_states_iterate.c
new file mode 100644
index 0000000000..f1eb1e79dc
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Lreg_states_iterate.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/Lregs.c b/src/pal/src/libunwind/src/x86_64/Lregs.c
new file mode 100644
index 0000000000..2c9c75cd7d
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Lregs.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gregs.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/Lresume.c b/src/pal/src/libunwind/src/x86_64/Lresume.c
new file mode 100644
index 0000000000..41a8cf003d
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Lresume.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gresume.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/Lstash_frame.c b/src/pal/src/libunwind/src/x86_64/Lstash_frame.c
new file mode 100644
index 0000000000..77587803d0
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Lstash_frame.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gstash_frame.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/Lstep.c b/src/pal/src/libunwind/src/x86_64/Lstep.c
new file mode 100644
index 0000000000..c1ac3c7547
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Lstep.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gstep.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/Ltrace.c b/src/pal/src/libunwind/src/x86_64/Ltrace.c
new file mode 100644
index 0000000000..fcd3f239c9
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/Ltrace.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gtrace.c"
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/getcontext.S b/src/pal/src/libunwind/src/x86_64/getcontext.S
new file mode 100644
index 0000000000..7a8b5664bd
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/getcontext.S
@@ -0,0 +1,134 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 Google, Inc
+ Contributed by Paul Pluzhnikov <ppluzhnikov@google.com>
+ Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "ucontext_i.h"
+
+/* int _Ux86_64_getcontext (ucontext_t *ucp)
+
+ Saves the machine context in UCP necessary for libunwind.
+ Unlike the libc implementation, we don't save the signal mask
+ and hence avoid the cost of a system call per unwind.
+
+*/
+
+ .global _Ux86_64_getcontext
+ .type _Ux86_64_getcontext, @function
+_Ux86_64_getcontext:
+ .cfi_startproc
+
+ /* Callee saved: RBX, RBP, R12-R15 */
+ movq %r12, UC_MCONTEXT_GREGS_R12(%rdi)
+ movq %r13, UC_MCONTEXT_GREGS_R13(%rdi)
+ movq %r14, UC_MCONTEXT_GREGS_R14(%rdi)
+ movq %r15, UC_MCONTEXT_GREGS_R15(%rdi)
+ movq %rbp, UC_MCONTEXT_GREGS_RBP(%rdi)
+ movq %rbx, UC_MCONTEXT_GREGS_RBX(%rdi)
+
+ /* Save argument registers (not strictly needed, but setcontext
+ restores them, so don't restore garbage). */
+ movq %r8, UC_MCONTEXT_GREGS_R8(%rdi)
+ movq %r9, UC_MCONTEXT_GREGS_R9(%rdi)
+ movq %rdi, UC_MCONTEXT_GREGS_RDI(%rdi)
+ movq %rsi, UC_MCONTEXT_GREGS_RSI(%rdi)
+ movq %rdx, UC_MCONTEXT_GREGS_RDX(%rdi)
+ movq %rax, UC_MCONTEXT_GREGS_RAX(%rdi)
+ movq %rcx, UC_MCONTEXT_GREGS_RCX(%rdi)
+
+#if defined __linux__
+ /* Save fp state (not needed, except for setcontext not
+ restoring garbage). */
+ leaq UC_MCONTEXT_FPREGS_MEM(%rdi),%r8
+ movq %r8, UC_MCONTEXT_FPREGS_PTR(%rdi)
+ fnstenv (%r8)
+ stmxcsr FPREGS_OFFSET_MXCSR(%r8)
+#elif defined __FreeBSD__
+ fxsave UC_MCONTEXT_FPSTATE(%rdi)
+ movq $UC_MCONTEXT_FPOWNED_FPU,UC_MCONTEXT_OWNEDFP(%rdi)
+ movq $UC_MCONTEXT_FPFMT_XMM,UC_MCONTEXT_FPFORMAT(%rdi)
+ /* Save rflags and segment registers, so that sigreturn(2)
+ does not complain. */
+ pushfq
+ .cfi_adjust_cfa_offset 8
+ popq UC_MCONTEXT_RFLAGS(%rdi)
+ .cfi_adjust_cfa_offset -8
+ movl $0, UC_MCONTEXT_FLAGS(%rdi)
+ movw %cs, UC_MCONTEXT_CS(%rdi)
+ movw %ss, UC_MCONTEXT_SS(%rdi)
+#if 0
+ /* Setting the flags to 0 above disables restore of segment
+ registers from the context */
+ movw %ds, UC_MCONTEXT_DS(%rdi)
+ movw %es, UC_MCONTEXT_ES(%rdi)
+ movw %fs, UC_MCONTEXT_FS(%rdi)
+ movw %gs, UC_MCONTEXT_GS(%rdi)
+#endif
+ movq $UC_MCONTEXT_MC_LEN_VAL, UC_MCONTEXT_MC_LEN(%rdi)
+#else
+#error Port me
+#endif
+
+ leaq 8(%rsp), %rax /* exclude this call. */
+ movq %rax, UC_MCONTEXT_GREGS_RSP(%rdi)
+
+ movq 0(%rsp), %rax
+ movq %rax, UC_MCONTEXT_GREGS_RIP(%rdi)
+
+ xorq %rax, %rax
+ retq
+ .cfi_endproc
+ .size _Ux86_64_getcontext, . - _Ux86_64_getcontext
+
+/* int _Ux86_64_getcontext_trace (ucontext_t *ucp)
+
+ Saves limited machine context in UCP necessary for libunwind.
+ Unlike _Ux86_64_getcontext, saves only the parts needed for
+ fast trace. If fast trace fails, caller will have to get the
+ full context.
+*/
+
+ .global _Ux86_64_getcontext_trace
+ .hidden _Ux86_64_getcontext_trace
+ .type _Ux86_64_getcontext_trace, @function
+_Ux86_64_getcontext_trace:
+ .cfi_startproc
+
+ /* Save only RBP, RBX, RSP, RIP - exclude this call. */
+ movq %rbp, UC_MCONTEXT_GREGS_RBP(%rdi)
+ movq %rbx, UC_MCONTEXT_GREGS_RBX(%rdi)
+
+ leaq 8(%rsp), %rax
+ movq %rax, UC_MCONTEXT_GREGS_RSP(%rdi)
+
+ movq 0(%rsp), %rax
+ movq %rax, UC_MCONTEXT_GREGS_RIP(%rdi)
+
+ xorq %rax, %rax
+ retq
+ .cfi_endproc
+ .size _Ux86_64_getcontext_trace, . - _Ux86_64_getcontext_trace
+
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
diff --git a/src/pal/src/libunwind/src/x86_64/init.h b/src/pal/src/libunwind/src/x86_64/init.h
new file mode 100644
index 0000000000..a7a996f127
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/init.h
@@ -0,0 +1,89 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+/* Avoid a trip to x86_64_r_uc_addr() for purely local initialisation. */
+#if defined UNW_LOCAL_ONLY && defined __linux
+# define REG_INIT_LOC(c, rlc, ruc) \
+ DWARF_LOC ((unw_word_t) &c->uc->uc_mcontext.gregs[REG_ ## ruc], 0)
+
+#elif defined UNW_LOCAL_ONLY && defined __FreeBSD__
+# define REG_INIT_LOC(c, rlc, ruc) \
+ DWARF_LOC ((unw_word_t) &c->uc->uc_mcontext.mc_ ## rlc, 0)
+
+#else
+# define REG_INIT_LOC(c, rlc, ruc) \
+ DWARF_REG_LOC (&c->dwarf, UNW_X86_64_ ## ruc)
+#endif
+
+static inline int
+common_init (struct cursor *c, unsigned use_prev_instr)
+{
+ int ret;
+
+ c->dwarf.loc[RAX] = REG_INIT_LOC(c, rax, RAX);
+ c->dwarf.loc[RDX] = REG_INIT_LOC(c, rdx, RDX);
+ c->dwarf.loc[RCX] = REG_INIT_LOC(c, rcx, RCX);
+ c->dwarf.loc[RBX] = REG_INIT_LOC(c, rbx, RBX);
+ c->dwarf.loc[RSI] = REG_INIT_LOC(c, rsi, RSI);
+ c->dwarf.loc[RDI] = REG_INIT_LOC(c, rdi, RDI);
+ c->dwarf.loc[RBP] = REG_INIT_LOC(c, rbp, RBP);
+ c->dwarf.loc[RSP] = REG_INIT_LOC(c, rsp, RSP);
+ c->dwarf.loc[R8] = REG_INIT_LOC(c, r8, R8);
+ c->dwarf.loc[R9] = REG_INIT_LOC(c, r9, R9);
+ c->dwarf.loc[R10] = REG_INIT_LOC(c, r10, R10);
+ c->dwarf.loc[R11] = REG_INIT_LOC(c, r11, R11);
+ c->dwarf.loc[R12] = REG_INIT_LOC(c, r12, R12);
+ c->dwarf.loc[R13] = REG_INIT_LOC(c, r13, R13);
+ c->dwarf.loc[R14] = REG_INIT_LOC(c, r14, R14);
+ c->dwarf.loc[R15] = REG_INIT_LOC(c, r15, R15);
+ c->dwarf.loc[RIP] = REG_INIT_LOC(c, rip, RIP);
+
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip);
+ if (ret < 0)
+ return ret;
+
+ ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_X86_64_RSP),
+ &c->dwarf.cfa);
+ if (ret < 0)
+ return ret;
+
+ c->sigcontext_format = X86_64_SCF_NONE;
+ c->sigcontext_addr = 0;
+
+ c->dwarf.args_size = 0;
+ c->dwarf.stash_frames = 0;
+ c->dwarf.use_prev_instr = use_prev_instr;
+ c->dwarf.pi_valid = 0;
+ c->dwarf.pi_is_dynamic = 0;
+ c->dwarf.hint = 0;
+ c->dwarf.prev_rs = 0;
+ c->dwarf.eh_valid_mask = 0;
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/x86_64/is_fpreg.c b/src/pal/src/libunwind/src/x86_64/is_fpreg.c
new file mode 100644
index 0000000000..5c036137b6
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/is_fpreg.c
@@ -0,0 +1,38 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (c) 2004-2005 Hewlett-Packard Development Company, L.P.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+
+int
+unw_is_fpreg (int regnum)
+{
+#if 0
+ return ((regnum >= UNW_X86_ST0 && regnum <= UNW_X86_ST7)
+ || (regnum >= UNW_X86_XMM0_lo && regnum <= UNW_X86_XMM7_hi));
+#endif
+ return 0;
+}
diff --git a/src/pal/src/libunwind/src/x86_64/longjmp.S b/src/pal/src/libunwind/src/x86_64/longjmp.S
new file mode 100644
index 0000000000..274778fd80
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/longjmp.S
@@ -0,0 +1,34 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+ .globl _UI_longjmp_cont
+ .type _UI_longjmp_cont, @function
+_UI_longjmp_cont:
+ push %rax /* push target IP as return address */
+ mov %rdx, %rax /* set up return-value */
+ retq
+ .size _UI_longjmp_cont, .-_UI_longjmp_cont
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
diff --git a/src/pal/src/libunwind/src/x86_64/offsets.h b/src/pal/src/libunwind/src/x86_64/offsets.h
new file mode 100644
index 0000000000..0807960f30
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/offsets.h
@@ -0,0 +1,3 @@
+/* FreeBSD specific definitions */
+
+#define FREEBSD_UC_MCONTEXT_OFF 0x10
diff --git a/src/pal/src/libunwind/src/x86_64/regname.c b/src/pal/src/libunwind/src/x86_64/regname.c
new file mode 100644
index 0000000000..77660af4a2
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/regname.c
@@ -0,0 +1,56 @@
+/* libunwind - a platform-independent unwind library
+
+ Contributed by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "unwind_i.h"
+
+static const char *regname[] =
+ {
+ "RAX",
+ "RDX",
+ "RCX",
+ "RBX",
+ "RSI",
+ "RDI",
+ "RBP",
+ "RSP",
+ "R8",
+ "R9",
+ "R10",
+ "R11",
+ "R12",
+ "R13",
+ "R14",
+ "R15",
+ "RIP",
+ };
+
+const char *
+unw_regname (unw_regnum_t reg)
+{
+ if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
+ return regname[reg];
+ else
+ return "???";
+}
diff --git a/src/pal/src/libunwind/src/x86_64/setcontext.S b/src/pal/src/libunwind/src/x86_64/setcontext.S
new file mode 100644
index 0000000000..358217defb
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/setcontext.S
@@ -0,0 +1,83 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2007 Google, Inc
+ Contributed by Arun Sharma <arun.sharma@google.com>
+ Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "ucontext_i.h"
+
+/* int _Ux86_64_setcontext (const ucontext_t *ucp)
+
+ Restores the machine context provided.
+ Unlike the libc implementation, doesn't clobber %rax
+
+*/
+ .global _Ux86_64_setcontext
+ .type _Ux86_64_setcontext, @function
+
+_Ux86_64_setcontext:
+
+#if defined __linux__
+ /* restore fp state */
+ mov UC_MCONTEXT_FPREGS_PTR(%rdi),%r8
+ fldenv (%r8)
+ ldmxcsr FPREGS_OFFSET_MXCSR(%r8)
+#elif defined __FreeBSD__
+ /* restore fp state */
+ cmpq $UC_MCONTEXT_FPOWNED_FPU,UC_MCONTEXT_OWNEDFP(%rdi)
+ jne 1f
+ cmpq $UC_MCONTEXT_FPFMT_XMM,UC_MCONTEXT_FPFORMAT(%rdi)
+ jne 1f
+ fxrstor UC_MCONTEXT_FPSTATE(%rdi)
+1:
+#else
+#error Port me
+#endif
+
+ /* restore the rest of the state */
+ mov UC_MCONTEXT_GREGS_R8(%rdi),%r8
+ mov UC_MCONTEXT_GREGS_R9(%rdi),%r9
+ mov UC_MCONTEXT_GREGS_RBX(%rdi),%rbx
+ mov UC_MCONTEXT_GREGS_RBP(%rdi),%rbp
+ mov UC_MCONTEXT_GREGS_R12(%rdi),%r12
+ mov UC_MCONTEXT_GREGS_R13(%rdi),%r13
+ mov UC_MCONTEXT_GREGS_R14(%rdi),%r14
+ mov UC_MCONTEXT_GREGS_R15(%rdi),%r15
+ mov UC_MCONTEXT_GREGS_RSI(%rdi),%rsi
+ mov UC_MCONTEXT_GREGS_RDX(%rdi),%rdx
+ mov UC_MCONTEXT_GREGS_RAX(%rdi),%rax
+ mov UC_MCONTEXT_GREGS_RCX(%rdi),%rcx
+ mov UC_MCONTEXT_GREGS_RSP(%rdi),%rsp
+
+ /* push the return address on the stack */
+ mov UC_MCONTEXT_GREGS_RIP(%rdi),%rcx
+ push %rcx
+
+ mov UC_MCONTEXT_GREGS_RCX(%rdi),%rcx
+ mov UC_MCONTEXT_GREGS_RDI(%rdi),%rdi
+ retq
+
+ .size _Ux86_64_setcontext, . - _Ux86_64_setcontext
+
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
diff --git a/src/pal/src/libunwind/src/x86_64/siglongjmp.S b/src/pal/src/libunwind/src/x86_64/siglongjmp.S
new file mode 100644
index 0000000000..32489e53a9
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/siglongjmp.S
@@ -0,0 +1,32 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+ .globl _UI_siglongjmp_cont
+ .type _UI_siglongjmp_cont, @function
+_UI_siglongjmp_cont:
+ retq
+ .size _UI_siglongjmp_cont, . - _UI_siglongjmp_cont
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
diff --git a/src/pal/src/libunwind/src/x86_64/ucontext_i.h b/src/pal/src/libunwind/src/x86_64/ucontext_i.h
new file mode 100644
index 0000000000..aded941d05
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/ucontext_i.h
@@ -0,0 +1,82 @@
+/* Copyright (C) 2004 Hewlett-Packard Co.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>.
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#if defined __linux__
+#define UC_MCONTEXT_GREGS_R8 0x28
+#define UC_MCONTEXT_GREGS_R9 0x30
+#define UC_MCONTEXT_GREGS_R10 0x38
+#define UC_MCONTEXT_GREGS_R11 0x40
+#define UC_MCONTEXT_GREGS_R12 0x48
+#define UC_MCONTEXT_GREGS_R13 0x50
+#define UC_MCONTEXT_GREGS_R14 0x58
+#define UC_MCONTEXT_GREGS_R15 0x60
+#define UC_MCONTEXT_GREGS_RDI 0x68
+#define UC_MCONTEXT_GREGS_RSI 0x70
+#define UC_MCONTEXT_GREGS_RBP 0x78
+#define UC_MCONTEXT_GREGS_RBX 0x80
+#define UC_MCONTEXT_GREGS_RDX 0x88
+#define UC_MCONTEXT_GREGS_RAX 0x90
+#define UC_MCONTEXT_GREGS_RCX 0x98
+#define UC_MCONTEXT_GREGS_RSP 0xa0
+#define UC_MCONTEXT_GREGS_RIP 0xa8
+#define UC_MCONTEXT_FPREGS_PTR 0x1a8
+#define UC_MCONTEXT_FPREGS_MEM 0xe0
+#define UC_SIGMASK 0x128
+#define FPREGS_OFFSET_MXCSR 0x18
+#elif defined __FreeBSD__
+#define UC_SIGMASK 0x0
+#define UC_MCONTEXT_GREGS_RDI 0x18
+#define UC_MCONTEXT_GREGS_RSI 0x20
+#define UC_MCONTEXT_GREGS_RDX 0x28
+#define UC_MCONTEXT_GREGS_RCX 0x30
+#define UC_MCONTEXT_GREGS_R8 0x38
+#define UC_MCONTEXT_GREGS_R9 0x40
+#define UC_MCONTEXT_GREGS_RAX 0x48
+#define UC_MCONTEXT_GREGS_RBX 0x50
+#define UC_MCONTEXT_GREGS_RBP 0x58
+#define UC_MCONTEXT_GREGS_R10 0x60
+#define UC_MCONTEXT_GREGS_R11 0x68
+#define UC_MCONTEXT_GREGS_R12 0x70
+#define UC_MCONTEXT_GREGS_R13 0x78
+#define UC_MCONTEXT_GREGS_R14 0x80
+#define UC_MCONTEXT_GREGS_R15 0x88
+#define UC_MCONTEXT_FS 0x94
+#define UC_MCONTEXT_GS 0x96
+#define UC_MCONTEXT_FLAGS 0xa0
+#define UC_MCONTEXT_ES 0xa4
+#define UC_MCONTEXT_DS 0xa6
+#define UC_MCONTEXT_GREGS_RIP 0xb0
+#define UC_MCONTEXT_CS 0xb8
+#define UC_MCONTEXT_RFLAGS 0xc0
+#define UC_MCONTEXT_GREGS_RSP 0xc8
+#define UC_MCONTEXT_SS 0xd0
+#define UC_MCONTEXT_MC_LEN 0xd8
+#define UC_MCONTEXT_FPFORMAT 0xe0
+#define UC_MCONTEXT_OWNEDFP 0xe8
+#define UC_MCONTEXT_FPSTATE 0xf0
+#define UC_MCONTEXT_FPOWNED_FPU 0x20001
+#define UC_MCONTEXT_FPFMT_XMM 0x10002
+#define UC_MCONTEXT_MC_LEN_VAL 0x320
+
+#endif
diff --git a/src/pal/src/libunwind/src/x86_64/unwind_i.h b/src/pal/src/libunwind/src/x86_64/unwind_i.h
new file mode 100644
index 0000000000..e95a60ff37
--- /dev/null
+++ b/src/pal/src/libunwind/src/x86_64/unwind_i.h
@@ -0,0 +1,93 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002, 2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+ Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef unwind_i_h
+#define unwind_i_h
+
+#include <stdint.h>
+
+#include <libunwind-x86_64.h>
+
+#include "libunwind_i.h"
+#include <sys/ucontext.h>
+
+/* DWARF column numbers for x86_64: */
+#define RAX 0
+#define RDX 1
+#define RCX 2
+#define RBX 3
+#define RSI 4
+#define RDI 5
+#define RBP 6
+#define RSP 7
+#define R8 8
+#define R9 9
+#define R10 10
+#define R11 11
+#define R12 12
+#define R13 13
+#define R14 14
+#define R15 15
+#define RIP 16
+
+#define x86_64_lock UNW_OBJ(lock)
+#define x86_64_local_resume UNW_OBJ(local_resume)
+#define x86_64_local_addr_space_init UNW_OBJ(local_addr_space_init)
+#define setcontext UNW_ARCH_OBJ (setcontext)
+#if 0
+#define x86_64_scratch_loc UNW_OBJ(scratch_loc)
+#endif
+#define x86_64_r_uc_addr UNW_OBJ(r_uc_addr)
+#define x86_64_sigreturn UNW_OBJ(sigreturn)
+
+/* By-pass calls to access_mem() when known to be safe. */
+#ifdef UNW_LOCAL_ONLY
+# undef ACCESS_MEM_FAST
+# define ACCESS_MEM_FAST(ret,validate,cur,addr,to) \
+ do { \
+ if (unlikely(validate)) \
+ (ret) = dwarf_get ((cur), DWARF_MEM_LOC ((cur), (addr)), &(to)); \
+ else \
+ (ret) = 0, (to) = *(unw_word_t *)(addr); \
+ } while (0)
+#endif
+
+extern void x86_64_local_addr_space_init (void);
+extern int x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
+ void *arg);
+extern int setcontext (const ucontext_t *ucp);
+
+#if 0
+extern dwarf_loc_t x86_64_scratch_loc (struct cursor *c, unw_regnum_t reg);
+#endif
+
+extern void *x86_64_r_uc_addr (ucontext_t *uc, int reg);
+extern NORETURN void x86_64_sigreturn (unw_cursor_t *cursor);
+#define x86_64_handle_signal_frame UNW_OBJ(handle_signal_frame)
+extern int x86_64_handle_signal_frame(unw_cursor_t *cursor);
+
+#endif /* unwind_i_h */
diff --git a/src/pal/src/libunwind/tests/Gia64-test-nat.c b/src/pal/src/libunwind/tests/Gia64-test-nat.c
new file mode 100644
index 0000000000..89df54e0b0
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Gia64-test-nat.c
@@ -0,0 +1,626 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* This file tests corner-cases of NaT-bit handling. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libunwind.h>
+#include "compiler.h"
+
+#ifdef HAVE_SYS_UC_ACCESS_H
+# include <sys/uc_access.h>
+#endif
+
+#include "tdep-ia64/rse.h"
+
+#define NUM_RUNS 1024
+//#define NUM_RUNS 1
+#define MAX_CHECKS 1024
+//#define MAX_CHECKS 2
+#define MAX_VALUES_PER_FUNC 4
+
+#define panic(args...) \
+ do { printf (args); ++nerrors; } while (0)
+
+typedef void save_func_t (void *funcs, unsigned long *vals);
+typedef unw_word_t *check_func_t (unw_cursor_t *c, unsigned long *vals);
+
+extern void flushrs (void);
+
+extern save_func_t save_static_to_stacked;
+static check_func_t check_static_to_stacked;
+
+extern save_func_t save_static_to_fr;
+static check_func_t check_static_to_fr;
+
+extern save_func_t save_static_to_br;
+static check_func_t check_static_to_br;
+
+extern save_func_t save_static_to_mem;
+static check_func_t check_static_to_mem;
+
+extern save_func_t save_static_to_mem2;
+static check_func_t check_static_to_mem2;
+
+extern save_func_t save_static_to_mem3;
+static check_func_t check_static_to_mem3;
+
+extern save_func_t save_static_to_mem4;
+static check_func_t check_static_to_mem4;
+
+extern save_func_t save_static_to_mem5;
+static check_func_t check_static_to_mem5;
+
+extern save_func_t save_static_to_scratch;
+static check_func_t check_static_to_scratch;
+
+extern save_func_t rotate_regs;
+static check_func_t check_rotate_regs;
+
+extern save_func_t save_pr;
+static check_func_t check_pr;
+
+static int verbose;
+static int nerrors;
+
+static int num_checks;
+static save_func_t *funcs[MAX_CHECKS + 1];
+static check_func_t *checks[MAX_CHECKS];
+static unw_word_t values[MAX_CHECKS*MAX_VALUES_PER_FUNC];
+
+static struct
+ {
+ save_func_t *func;
+ check_func_t *check;
+ }
+all_funcs[] =
+ {
+ { save_static_to_stacked, check_static_to_stacked },
+ { save_static_to_fr, check_static_to_fr },
+ { save_static_to_br, check_static_to_br },
+ { save_static_to_mem, check_static_to_mem },
+ { save_static_to_mem2, check_static_to_mem2 },
+ { save_static_to_mem3, check_static_to_mem3 },
+ { save_static_to_mem4, check_static_to_mem4 },
+ { save_static_to_mem5, check_static_to_mem5 },
+ { save_static_to_scratch, check_static_to_scratch },
+ { save_pr, check_pr },
+ { rotate_regs, check_rotate_regs },
+ };
+
+static unw_word_t
+random_word (void)
+{
+ unw_word_t val = random ();
+
+ if (sizeof (unw_word_t) > 4)
+ val |= ((unw_word_t) random ()) << 32;
+
+ return val;
+}
+
+void
+sighandler (int signal, void *siginfo, void *context)
+{
+ unsigned long *bsp, *arg1;
+ save_func_t **arg0;
+ ucontext_t *uc = context;
+
+#if defined(__linux)
+ {
+ long sof;
+ int sp;
+
+ if (verbose)
+ printf ("sighandler: signal %d sp=%p nat=%08lx pr=%lx\n",
+ signal, &sp, uc->uc_mcontext.sc_nat, uc->uc_mcontext.sc_pr);
+ sof = uc->uc_mcontext.sc_cfm & 0x7f;
+ bsp = (unsigned long *) rse_skip_regs (uc->uc_mcontext.sc_ar_bsp, -sof);
+ }
+#elif defined(__hpux)
+ if (__uc_get_ar (uc, UNW_IA64_AR_BSP - UNW_IA64_AR, &bsp) != 0)
+ {
+ panic ("%s: reading of ar.bsp failed, errno=%d", __FUNCTION__, errno);
+ return;
+ }
+#endif
+
+ flushrs ();
+ arg0 = (save_func_t **) *bsp;
+ bsp = (unsigned long *) rse_skip_regs ((uint64_t) bsp, 1);
+ arg1 = (unsigned long *) *bsp;
+
+ (*arg0[0]) (arg0 + 1, arg1);
+
+ /* skip over the instruction which triggered sighandler() */
+#if defined(__linux)
+ ++uc->uc_mcontext.sc_ip;
+#elif defined(HAVE_SYS_UC_ACCESS_H)
+ {
+ unsigned long ip;
+
+ if (__uc_get_ip (uc, &ip) != 0)
+ {
+ panic ("%s: reading of ip failed, errno=%d", __FUNCTION__, errno);
+ return;
+ }
+ if (__uc_set_ip (uc, ip) != 0)
+ {
+ panic ("%s: writing of ip failed, errno=%d", __FUNCTION__, errno);
+ return;
+ }
+ }
+#endif
+}
+
+static void
+enable_sighandler (void)
+{
+ struct sigaction act;
+
+ memset (&act, 0, sizeof (act));
+ act.sa_handler = (void (*)(int)) sighandler;
+ act.sa_flags = SA_SIGINFO | SA_NODEFER;
+ if (sigaction (SIGSEGV, &act, NULL) < 0)
+ panic ("sigaction: %s\n", strerror (errno));
+}
+
+static void
+disable_sighandler (void)
+{
+ struct sigaction act;
+
+ memset (&act, 0, sizeof (act));
+ act.sa_handler = SIG_DFL;
+ act.sa_flags = SA_SIGINFO | SA_NODEFER;
+ if (sigaction (SIGSEGV, &act, NULL) < 0)
+ panic ("sigaction: %s\n", strerror (errno));
+}
+
+static unw_word_t *
+check_static_to_stacked (unw_cursor_t *c, unw_word_t *vals)
+{
+ unw_word_t r[4];
+ unw_word_t nat[4];
+ int i, ret;
+
+ if (verbose)
+ printf (" %s()\n", __FUNCTION__);
+
+ vals -= 4;
+
+ for (i = 0; i < 4; ++i)
+ if ((ret = unw_get_reg (c, UNW_IA64_GR + 4 + i, &r[i])) < 0)
+ panic ("%s: failed to read register r%d, error=%d\n",
+ __FUNCTION__, 4 + i, ret);
+
+ for (i = 0; i < 4; ++i)
+ if ((ret = unw_get_reg (c, UNW_IA64_NAT + 4 + i, &nat[i])) < 0)
+ panic ("%s: failed to read register nat%d, error=%d\n",
+ __FUNCTION__, 4 + i, ret);
+
+ for (i = 0; i < 4; ++i)
+ {
+ if (verbose)
+ printf (" r%d = %c%016lx (expected %c%016lx)\n",
+ 4 + i, nat[i] ? '*' : ' ', r[i],
+ (vals[i] & 1) ? '*' : ' ', vals[i]);
+
+ if (vals[i] & 1)
+ {
+ if (!nat[i])
+ panic ("%s: r%d not a NaT!\n", __FUNCTION__, 4 + i);
+ }
+ else
+ {
+ if (nat[i])
+ panic ("%s: r%d a NaT!\n", __FUNCTION__, 4 + i);
+ if (r[i] != vals[i])
+ panic ("%s: r%d=%lx instead of %lx!\n",
+ __FUNCTION__, 4 + i, r[i], vals[i]);
+ }
+ }
+ return vals;
+}
+
+static unw_word_t *
+check_static_to_fr (unw_cursor_t *c, unw_word_t *vals)
+{
+ unw_word_t r4;
+ unw_word_t nat4;
+ int ret;
+
+ if (verbose)
+ printf (" %s()\n", __FUNCTION__);
+
+ vals -= 1;
+
+ if ((ret = unw_get_reg (c, UNW_IA64_GR + 4, &r4)) < 0)
+ panic ("%s: failed to read register r4, error=%d\n", __FUNCTION__, ret);
+
+ if ((ret = unw_get_reg (c, UNW_IA64_NAT + 4, &nat4)) < 0)
+ panic ("%s: failed to read register nat4, error=%d\n", __FUNCTION__, ret);
+
+ if (verbose)
+ printf (" r4 = %c%016lx (expected %c%016lx)\n",
+ nat4 ? '*' : ' ', r4, (vals[0] & 1) ? '*' : ' ', vals[0]);
+
+ if (vals[0] & 1)
+ {
+ if (!nat4)
+ panic ("%s: r4 not a NaT!\n", __FUNCTION__);
+ }
+ else
+ {
+ if (nat4)
+ panic ("%s: r4 a NaT!\n", __FUNCTION__);
+ if (r4 != vals[0])
+ panic ("%s: r4=%lx instead of %lx!\n", __FUNCTION__, r4, vals[0]);
+ }
+ return vals;
+}
+
+static unw_word_t *
+check_static_to_br (unw_cursor_t *c, unw_word_t *vals)
+{
+ unw_word_t r4, nat4;
+ int ret;
+
+ if (verbose)
+ printf (" %s()\n", __FUNCTION__);
+
+ vals -= 1;
+
+ if ((ret = unw_get_reg (c, UNW_IA64_GR + 4, &r4)) < 0)
+ panic ("%s: failed to read register r4, error=%d\n", __FUNCTION__, ret);
+
+ if ((ret = unw_get_reg (c, UNW_IA64_NAT + 4, &nat4)) < 0)
+ panic ("%s: failed to read register nat4, error=%d\n", __FUNCTION__, ret);
+
+ if (verbose)
+ printf (" r4 = %c%016lx (expected %c%016lx)\n",
+ nat4 ? '*' : ' ', r4, (vals[0] & 1) ? '*' : ' ', vals[0]);
+
+ if (vals[0] & 1)
+ {
+ if (!nat4)
+ panic ("%s: r4 not a NaT!\n", __FUNCTION__);
+ }
+ else
+ {
+ if (nat4)
+ panic ("%s: r4 a NaT!\n", __FUNCTION__);
+ if (r4 != vals[0])
+ panic ("%s: r4=%lx instead of %lx!\n", __FUNCTION__, r4, vals[0]);
+ }
+ return vals;
+}
+
+static unw_word_t *
+check_static_to_mem (unw_cursor_t *c, unw_word_t *vals)
+{
+ unw_word_t r5, nat5;
+ int ret;
+
+ if (verbose)
+ printf (" %s()\n", __FUNCTION__);
+
+ vals -= 1;
+
+ if ((ret = unw_get_reg (c, UNW_IA64_GR + 5, &r5)) < 0)
+ panic ("%s: failed to read register r5, error=%d\n", __FUNCTION__, ret);
+
+ if ((ret = unw_get_reg (c, UNW_IA64_NAT + 5, &nat5)) < 0)
+ panic ("%s: failed to read register nat5, error=%d\n", __FUNCTION__, ret);
+
+ if (verbose)
+ printf (" r5 = %c%016lx (expected %c%016lx)\n",
+ nat5 ? '*' : ' ', r5, (vals[0] & 1) ? '*' : ' ', vals[0]);
+
+ if (vals[0] & 1)
+ {
+ if (!nat5)
+ panic ("%s: r5 not a NaT!\n", __FUNCTION__);
+ }
+ else
+ {
+ if (nat5)
+ panic ("%s: r5 a NaT!\n", __FUNCTION__);
+ if (r5 != vals[0])
+ panic ("%s: r5=%lx instead of %lx!\n", __FUNCTION__, r5, vals[0]);
+ }
+ return vals;
+}
+
+static unw_word_t *
+check_static_to_memN (unw_cursor_t *c, unw_word_t *vals, const char *func)
+{
+ unw_word_t r6, nat6;
+ int ret;
+
+ if (verbose)
+ printf (" %s()\n", func);
+
+ vals -= 1;
+
+ if ((ret = unw_get_reg (c, UNW_IA64_GR + 6, &r6)) < 0)
+ panic ("%s: failed to read register r6, error=%d\n", __FUNCTION__, ret);
+
+ if ((ret = unw_get_reg (c, UNW_IA64_NAT + 6, &nat6)) < 0)
+ panic ("%s: failed to read register nat6, error=%d\n", __FUNCTION__, ret);
+
+ if (verbose)
+ printf (" r6 = %c%016lx (expected %c%016lx)\n",
+ nat6 ? '*' : ' ', r6, (vals[0] & 1) ? '*' : ' ', vals[0]);
+
+ if (vals[0] & 1)
+ {
+ if (!nat6)
+ panic ("%s: r6 not a NaT!\n", __FUNCTION__);
+ }
+ else
+ {
+ if (nat6)
+ panic ("%s: r6 a NaT!\n", __FUNCTION__);
+ if (r6 != vals[0])
+ panic ("%s: r6=%lx instead of %lx!\n", __FUNCTION__, r6, vals[0]);
+ }
+ return vals;
+}
+
+static unw_word_t *
+check_static_to_mem2 (unw_cursor_t *c, unw_word_t *vals)
+{
+ return check_static_to_memN (c, vals, __FUNCTION__);
+}
+
+static unw_word_t *
+check_static_to_mem3 (unw_cursor_t *c, unw_word_t *vals)
+{
+ return check_static_to_memN (c, vals, __FUNCTION__);
+}
+
+static unw_word_t *
+check_static_to_mem4 (unw_cursor_t *c, unw_word_t *vals)
+{
+ return check_static_to_memN (c, vals, __FUNCTION__);
+}
+
+static unw_word_t *
+check_static_to_mem5 (unw_cursor_t *c, unw_word_t *vals)
+{
+ return check_static_to_memN (c, vals, __FUNCTION__);
+}
+
+static unw_word_t *
+check_static_to_scratch (unw_cursor_t *c, unw_word_t *vals)
+{
+ unw_word_t r[4], nat[4], ec, expected;
+ unw_fpreg_t f4;
+ int i, ret;
+
+ if (verbose)
+ printf (" %s()\n", __FUNCTION__);
+
+ vals -= 4;
+
+ while (!unw_is_signal_frame (c))
+ if ((ret = unw_step (c)) < 0)
+ panic ("%s: unw_step (ret=%d): Failed to skip over signal handler\n",
+ __FUNCTION__, ret);
+ if ((ret = unw_step (c)) < 0)
+ panic ("%s: unw_step (ret=%d): Failed to skip over signal handler\n",
+ __FUNCTION__, ret);
+
+ for (i = 0; i < 4; ++i)
+ if ((ret = unw_get_reg (c, UNW_IA64_GR + 4 + i, &r[i])) < 0)
+ panic ("%s: failed to read register r%d, error=%d\n",
+ __FUNCTION__, 4 + i, ret);
+
+ for (i = 0; i < 4; ++i)
+ if ((ret = unw_get_reg (c, UNW_IA64_NAT + 4 + i, &nat[i])) < 0)
+ panic ("%s: failed to read register nat%d, error=%d\n",
+ __FUNCTION__, 4 + i, ret);
+
+ for (i = 0; i < 4; ++i)
+ {
+ if (verbose)
+ printf (" r%d = %c%016lx (expected %c%016lx)\n",
+ 4 + i, nat[i] ? '*' : ' ', r[i],
+ (vals[i] & 1) ? '*' : ' ', vals[i]);
+
+ if (vals[i] & 1)
+ {
+ if (!nat[i])
+ panic ("%s: r%d not a NaT!\n", __FUNCTION__, 4 + i);
+ }
+ else
+ {
+ if (nat[i])
+ panic ("%s: r%d a NaT!\n", __FUNCTION__, 4 + i);
+ if (r[i] != vals[i])
+ panic ("%s: r%d=%lx instead of %lx!\n",
+ __FUNCTION__, 4 + i, r[i], vals[i]);
+ }
+ }
+ if ((ret = unw_get_fpreg (c, UNW_IA64_FR + 4, &f4)) < 0)
+ panic ("%s: failed to read f4, error=%d\n", __FUNCTION__, ret);
+
+ /* These tests are little-endian specific: */
+ if (nat[0])
+ {
+ if (f4.raw.bits[0] != 0 || f4.raw.bits[1] != 0x1fffe)
+ panic ("%s: f4=%016lx.%016lx instead of NaTVal!\n",
+ __FUNCTION__, f4.raw.bits[1], f4.raw.bits[0]);
+ }
+ else
+ {
+ if (f4.raw.bits[0] != r[0] || f4.raw.bits[1] != 0x1003e)
+ panic ("%s: f4=%016lx.%016lx instead of %lx!\n",
+ __FUNCTION__, f4.raw.bits[1], f4.raw.bits[0], r[0]);
+ }
+
+ if ((unw_get_reg (c, UNW_IA64_AR_EC, &ec)) < 0)
+ panic ("%s: failed to read register ar.ec, error=%d\n", __FUNCTION__, ret);
+
+ expected = vals[0] & 0x3f;
+ if (ec != expected)
+ panic ("%s: ar.ec=%016lx instead of %016lx!\n",
+ __FUNCTION__, ec, expected);
+
+ return vals;
+}
+
+static unw_word_t *
+check_pr (unw_cursor_t *c, unw_word_t *vals)
+{
+ unw_word_t pr, expected;
+ int ret;
+# define BIT(n) ((unw_word_t) 1 << (n))
+# define DONTCARE (BIT( 6) | BIT( 7) | BIT( 8) | BIT( 9) | BIT(10) \
+ | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15))
+
+ if (verbose)
+ printf (" %s()\n", __FUNCTION__);
+
+ vals -= 1;
+
+ if ((ret = unw_get_reg (c, UNW_IA64_PR, &pr)) < 0)
+ panic ("%s: failed to read register pr, error=%d\n", __FUNCTION__, ret);
+
+ pr &= ~DONTCARE;
+ expected = (vals[0] & ~DONTCARE) | 1;
+
+ if (verbose)
+ printf (" pr = %016lx (expected %016lx)\n", pr, expected);
+
+ if (pr != expected)
+ panic ("%s: pr=%lx instead of %lx!\n", __FUNCTION__, pr, expected);
+
+ if ((ret = unw_set_reg (c, UNW_IA64_PR, vals[0])) < 0)
+ panic ("%s: failed to write register pr, error=%d\n", __FUNCTION__, ret);
+
+ if ((ret = unw_get_reg (c, UNW_IA64_PR, &pr)) < 0)
+ panic ("%s: failed to read register pr, error=%d\n", __FUNCTION__, ret);
+
+ if (pr != vals[0])
+ panic ("%s: secondary pr=%lx instead of %lx!\n",
+ __FUNCTION__, pr, vals[0]);
+ return vals;
+}
+
+static unw_word_t *
+check_rotate_regs (unw_cursor_t *c, unw_word_t *vals)
+{
+ if (verbose)
+ printf (" %s()\n", __FUNCTION__);
+ return check_pr (c, vals - 1);
+}
+
+static void
+start_checks (void *funcs, unsigned long *vals)
+{
+ unw_context_t uc;
+ unw_cursor_t c;
+ int i, ret;
+
+ disable_sighandler ();
+
+ unw_getcontext (&uc);
+
+ if ((ret = unw_init_local (&c, &uc)) < 0)
+ panic ("%s: unw_init_local (ret=%d)\n", __FUNCTION__, ret);
+
+ if ((ret = unw_step (&c)) < 0)
+ panic ("%s: unw_step (ret=%d)\n", __FUNCTION__, ret);
+
+ for (i = 0; i < num_checks; ++i)
+ {
+ vals = (*checks[num_checks - 1 - i]) (&c, vals);
+
+ if ((ret = unw_step (&c)) < 0)
+ panic ("%s: unw_step (ret=%d)\n", __FUNCTION__, ret);
+ }
+}
+
+static void
+run_check (int test)
+{
+ int index, i;
+
+ if (test == 1)
+ /* Make first test always go the full depth... */
+ num_checks = MAX_CHECKS;
+ else
+ num_checks = (random () % MAX_CHECKS) + 1;
+
+ for (i = 0; i < num_checks * MAX_VALUES_PER_FUNC; ++i)
+ values[i] = random_word ();
+
+ for (i = 0; i < num_checks; ++i)
+ {
+ if (test == 1)
+ /* Make first test once go through each test... */
+ index = i % (int) ARRAY_SIZE (all_funcs);
+ else
+ index = random () % (int) ARRAY_SIZE (all_funcs);
+ funcs[i] = all_funcs[index].func;
+ checks[i] = all_funcs[index].check;
+ }
+
+ funcs[num_checks] = start_checks;
+
+ enable_sighandler ();
+ (*funcs[0]) (funcs + 1, values);
+}
+
+int
+main (int argc, char **argv)
+{
+ int i;
+
+ if (argc > 1)
+ verbose = 1;
+
+ for (i = 0; i < NUM_RUNS; ++i)
+ {
+ if (verbose)
+ printf ("Run %d\n", i + 1);
+ run_check (i + 1);
+ }
+
+ if (nerrors > 0)
+ {
+ fprintf (stderr, "FAILURE: detected %d errors\n", nerrors);
+ exit (-1);
+ }
+ if (verbose)
+ printf ("SUCCESS.\n");
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/Gia64-test-rbs.c b/src/pal/src/libunwind/tests/Gia64-test-rbs.c
new file mode 100644
index 0000000000..2181e70fd3
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Gia64-test-rbs.c
@@ -0,0 +1,193 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* This file tests corner-cases of unwinding across multiple stacks.
+ In particular, it verifies that the extreme case with a frame of 96
+ stacked registers that are all backed up by separate stacks works
+ as expected. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <libunwind.h>
+#include "compiler.h"
+
+#include "ia64-test-rbs.h"
+
+#define panic(args...) \
+ do { fprintf (stderr, args); ++nerrors; return -9999; } while (0)
+
+/* The loadrs field in ar.rsc is 14 bits wide, which limits all ia64
+ implementations to at most 2048 physical stacked registers
+ (actually, slightly less than that, because loadrs also counts RNaT
+ slots). Since we can dirty 93 stacked registers per recursion, we
+ need to recurse RECURSION_DEPTH times to ensure all physical
+ stacked registers are in use. */
+#define MAX_PHYS_STACKED 2048
+#define RECURSION_DEPTH ((MAX_PHYS_STACKED + 92) / 93)
+
+typedef int spill_func_t (long iteration, int (*next_func[])());
+
+extern int loadup (long iteration, int *values, int (*next_func[])());
+extern char resumption_point_label;
+
+#define DCL(n) \
+ extern int rbs_spill_##n (long iteration, int (*next_func[])())
+ DCL(2); DCL(3); DCL(4); DCL(5); DCL(6); DCL(7);
+ DCL(8); DCL(9); DCL(10); DCL(11); DCL(12); DCL(13); DCL(14); DCL(15);
+ DCL(16); DCL(17); DCL(18); DCL(19); DCL(20); DCL(21); DCL(22); DCL(23);
+ DCL(24); DCL(25); DCL(26); DCL(27); DCL(28); DCL(29); DCL(30); DCL(31);
+ DCL(32); DCL(33); DCL(34); DCL(35); DCL(36); DCL(37); DCL(38); DCL(39);
+ DCL(40); DCL(41); DCL(42); DCL(43); DCL(44); DCL(45); DCL(46); DCL(47);
+ DCL(48); DCL(49); DCL(50); DCL(51); DCL(52); DCL(53); DCL(54); DCL(55);
+ DCL(56); DCL(57); DCL(58); DCL(59); DCL(60); DCL(61); DCL(62); DCL(63);
+ DCL(64); DCL(65); DCL(66); DCL(67); DCL(68); DCL(69); DCL(70); DCL(71);
+ DCL(72); DCL(73); DCL(74); DCL(75); DCL(76); DCL(77); DCL(78); DCL(79);
+ DCL(80); DCL(81); DCL(82); DCL(83); DCL(84); DCL(85); DCL(86); DCL(87);
+ DCL(88); DCL(89); DCL(90); DCL(91); DCL(92); DCL(93); DCL(94);
+
+#define SPL(n) rbs_spill_##n
+spill_func_t *spill_funcs[] =
+ {
+ SPL(2), SPL(3), SPL(4), SPL(5), SPL(6), SPL(7),
+ SPL(8), SPL(9), SPL(10), SPL(11), SPL(12), SPL(13), SPL(14), SPL(15),
+ SPL(16), SPL(17), SPL(18), SPL(19), SPL(20), SPL(21), SPL(22), SPL(23),
+ SPL(24), SPL(25), SPL(26), SPL(27), SPL(28), SPL(29), SPL(30), SPL(31),
+ SPL(32), SPL(33), SPL(34), SPL(35), SPL(36), SPL(37), SPL(38), SPL(39),
+ SPL(40), SPL(41), SPL(42), SPL(43), SPL(44), SPL(45), SPL(46), SPL(47),
+ SPL(48), SPL(49), SPL(50), SPL(51), SPL(52), SPL(53), SPL(54), SPL(55),
+ SPL(56), SPL(57), SPL(58), SPL(59), SPL(60), SPL(61), SPL(62), SPL(63),
+ SPL(64), SPL(65), SPL(66), SPL(67), SPL(68), SPL(69), SPL(70), SPL(71),
+ SPL(72), SPL(73), SPL(74), SPL(75), SPL(76), SPL(77), SPL(78), SPL(79),
+ SPL(80), SPL(81), SPL(82), SPL(83), SPL(84), SPL(85), SPL(86), SPL(87),
+ SPL(88), SPL(89), SPL(90), SPL(91), SPL(92), SPL(93), SPL(94)
+ };
+
+static int verbose;
+static int nerrors;
+static int unwind_count;
+
+static int
+unwind_and_resume (long iteration, int (*next_func[])())
+{
+ unw_context_t uc;
+ unw_cursor_t c;
+ unw_word_t ip;
+ int i, ret;
+
+ if (verbose)
+ printf (" %s(iteration=%ld, next_func=%p)\n",
+ __FUNCTION__, iteration, next_func);
+
+ unw_getcontext (&uc);
+ if ((ret = unw_init_local (&c, &uc)) < 0)
+ panic ("unw_init_local (ret=%d)", ret);
+
+ for (i = 0; i < unwind_count; ++i)
+ if ((ret = unw_step (&c)) < 0)
+ panic ("unw_step (ret=%d)", ret);
+
+ if (unw_get_reg (&c, UNW_REG_IP, &ip) < 0
+ || unw_set_reg (&c, UNW_REG_IP, (unw_word_t) &resumption_point_label) < 0
+ || unw_set_reg (&c, UNW_REG_EH + 0, 0) /* ret val */
+ || unw_set_reg (&c, UNW_REG_EH + 1, ip))
+ panic ("failed to redirect to resumption_point\n");
+
+ if (verbose)
+ {
+ unw_word_t bsp;
+ if (unw_get_reg (&c, UNW_IA64_BSP, &bsp) < 0)
+ panic ("unw_get_reg() failed\n");
+ printf (" bsp=%lx, old ip=%lx, new ip=%p\n", bsp,
+ ip, &resumption_point_label);
+ }
+
+ ret = unw_resume (&c);
+ panic ("unw_resume() returned (ret=%d)!!\n", ret);
+ return 0;
+}
+
+static int
+run_check (int test)
+{
+ int nfuncs, nspills, n, ret, i, reg_values[88];
+ spill_func_t *func[NSTACKS + 1];
+
+ /* First, generate a set of 88 random values which loadup() will load
+ into loc2-loc89 (r37-r124). */
+ for (i = 0; i < (int) ARRAY_SIZE (reg_values); ++i)
+ {
+ reg_values[i] = random ();
+ /* Generate NaTs with a reasonably probability (1/16th): */
+ if (reg_values[i] < 0x10000000)
+ reg_values[i] = 0;
+ }
+
+ nspills = 0;
+ nfuncs = 0;
+ do
+ {
+ n = random () % (int) ARRAY_SIZE (spill_funcs);
+ func[nfuncs++] = spill_funcs[n];
+ nspills += 2 + n;
+ }
+ while (nspills < 128);
+ func[nfuncs++] = unwind_and_resume;
+
+ unwind_count = 1 + (random () % (nfuncs + RECURSION_DEPTH - 1));
+
+ if (verbose)
+ printf ("test%d: nfuncs=%d, unwind_count=%d\n",
+ test, nfuncs, unwind_count);
+
+ ret = loadup (RECURSION_DEPTH, reg_values, func);
+ if (ret < 0)
+ panic ("test%d: load() returned %d\n", test, ret);
+ else if (ret != RECURSION_DEPTH + nfuncs - unwind_count)
+ panic ("test%d: resumed wrong frame: expected %d, got %d\n",
+ test, RECURSION_DEPTH + nfuncs - unwind_count, ret);
+ return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+ int i;
+
+ if (argc > 1)
+ verbose = 1;
+
+ for (i = 0; i < 100000; ++i)
+ run_check (i + 1);
+
+ if (nerrors > 0)
+ {
+ fprintf (stderr, "FAILURE: detected %d errors\n", nerrors);
+ exit (-1);
+ }
+ if (verbose)
+ printf ("SUCCESS.\n");
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/Gia64-test-readonly.c b/src/pal/src/libunwind/tests/Gia64-test-readonly.c
new file mode 100644
index 0000000000..25f0506102
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Gia64-test-readonly.c
@@ -0,0 +1,89 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* This file verifies that read-only registers cannot be written to. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libunwind.h>
+
+#define panic(args...) \
+ do { printf (args); ++nerrors; } while (0)
+
+static int verbose;
+static int nerrors;
+
+extern void test_func (void (*) (void));
+
+void
+checker (void)
+{
+ unw_fpreg_t fpval;
+ unw_context_t uc;
+ unw_cursor_t c;
+ int ret;
+
+ fpval.raw.bits[0] = 100;
+ fpval.raw.bits[1] = 101;
+
+ unw_getcontext (&uc);
+
+ if ((ret = unw_init_local (&c, &uc)) < 0)
+ panic ("%s: unw_init_local (ret=%d)\n", __FUNCTION__, ret);
+
+ if ((ret = unw_step (&c)) < 0)
+ panic ("%s: unw_step (ret=%d)\n", __FUNCTION__, ret);
+
+ if ((ret = unw_step (&c)) < 0)
+ panic ("%s: unw_step (ret=%d)\n", __FUNCTION__, ret);
+
+ if ((ret = unw_set_reg (&c, UNW_IA64_IP, 99)) != -UNW_EREADONLYREG)
+ panic ("%s: unw_set_reg (ip) returned %d instead of %d\n",
+ __FUNCTION__, ret, -UNW_EREADONLYREG);
+ if ((ret = unw_set_reg (&c, UNW_IA64_AR_LC, 99)) != -UNW_EREADONLYREG)
+ panic ("%s: unw_set_reg (ar.lc) returned %d instead of %d\n",
+ __FUNCTION__, ret, -UNW_EREADONLYREG);
+}
+
+int
+main (int argc, char **argv)
+{
+ if (argc > 1)
+ verbose = 1;
+
+ test_func (checker);
+
+ if (nerrors > 0)
+ {
+ fprintf (stderr, "FAILURE: detected %d errors\n", nerrors);
+ exit (-1);
+ }
+ if (verbose)
+ printf ("SUCCESS.\n");
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/Gia64-test-stack.c b/src/pal/src/libunwind/tests/Gia64-test-stack.c
new file mode 100644
index 0000000000..05874b291f
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Gia64-test-stack.c
@@ -0,0 +1,176 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* This file tests corner-cases of unwinding across multiple stacks.
+ In particular, it verifies that the extreme case with a frame of 96
+ stacked registers that are all backed up by separate stacks works
+ as expected. */
+
+#include <libunwind.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "ia64-test-stack.h"
+
+#define panic(args...) \
+ { printf (args); ++nerrors; }
+
+/* The loadrs field in ar.rsc is 14 bits wide, which limits all ia64
+ implementations to at most 2048 physical stacked registers
+ (actually, slightly less than that, because loadrs also counts RNaT
+ slots). Since we can dirty 95 stacked registers per recursion, we
+ need to recurse RECURSION_DEPTH times to ensure all physical
+ stacked registers are in use. */
+#define MAX_PHYS_STACKED 2048
+#define RECURSION_DEPTH ((MAX_PHYS_STACKED + 94) / 95)
+
+extern void touch_all (unsigned long recursion_depth);
+extern void flushrs (void);
+
+int nerrors;
+int verbose;
+
+void
+do_unwind_tests (void)
+{
+ unw_word_t ip, sp, bsp, v0, v1, v2, v3, n0, n1, n2, n3, cfm, sof, sol, r32;
+ int ret, reg, i, l;
+ unw_context_t uc;
+ unw_cursor_t c;
+
+ if (verbose)
+ printf ("do_unwind_tests: here we go!\n");
+
+ /* do a full stack-dump: */
+ unw_getcontext (&uc);
+ unw_init_local (&c, &uc);
+ i = 0;
+ do
+ {
+ if (verbose)
+ {
+ if ((ret = unw_get_reg (&c, UNW_IA64_IP, &ip)) < 0
+ || (ret = unw_get_reg (&c, UNW_IA64_SP, &sp)) < 0
+ || (ret = unw_get_reg (&c, UNW_IA64_BSP, &bsp)) < 0)
+ break;
+ printf ("ip=0x%16lx sp=0x%16lx bsp=0x%16lx\n", ip, sp, bsp);
+
+ for (reg = 32; reg < 128; reg += 4)
+ {
+ v0 = v1 = v2 = v3 = 0;
+ n0 = n1 = n2 = n3 = 0;
+ (void)
+ ((ret = unw_get_reg (&c, UNW_IA64_GR + reg, &v0)) < 0
+ || (ret = unw_get_reg (&c, UNW_IA64_NAT + reg, &n0)) < 0
+ || (ret = unw_get_reg (&c, UNW_IA64_GR + reg + 1, &v1)) < 0
+ || (ret = unw_get_reg (&c, UNW_IA64_NAT + reg + 1, &n1)) < 0
+ || (ret = unw_get_reg (&c, UNW_IA64_GR + reg + 2, &v2)) < 0
+ || (ret = unw_get_reg (&c, UNW_IA64_NAT + reg + 2, &n2)) < 0
+ || (ret = unw_get_reg (&c, UNW_IA64_GR + reg + 3, &v3)) < 0
+ || (ret = unw_get_reg (&c, UNW_IA64_NAT + reg + 3, &n3)) < 0);
+ if (reg < 100)
+ printf (" r%d", reg);
+ else
+ printf (" r%d", reg);
+ printf (" %c%016lx %c%016lx %c%016lx %c%016lx\n",
+ n0 ? '*' : ' ', v0, n1 ? '*' : ' ', v1,
+ n2 ? '*' : ' ', v2, n3 ? '*' : ' ', v3);
+ if (ret < 0)
+ break;
+ }
+ }
+
+ if (i >= 1 && i <= NSTACKS)
+ {
+ if ((ret = unw_get_reg (&c, UNW_IA64_CFM, &cfm)) < 0)
+ break;
+ sof = cfm & 0x7f;
+ if (sof != (unw_word_t) (i & 1))
+ panic ("\texpected sof=%d, found sof=%lu\n", i - 1, sof);
+ if (sof == 1)
+ {
+ if ((ret = unw_get_reg (&c, UNW_IA64_GR + 32, &r32)) < 0)
+ break;
+ if (r32 != (unw_word_t) (i - 1))
+ panic ("\texpected r32=%d, found r32=%lu\n", i - 1, r32);
+ }
+ }
+ else if (i > NSTACKS && i <= NSTACKS + RECURSION_DEPTH)
+ {
+ if ((ret = unw_get_reg (&c, UNW_IA64_CFM, &cfm)) < 0)
+ break;
+ sof = cfm & 0x7f;
+ sol = (cfm >> 7) & 0x7f;
+ if (sof != 96)
+ panic ("\texpected sof=96, found sof=%lu\n", sof);
+ if (sol != 95)
+ panic ("\texpected sol=95, found sol=%lu\n", sol);
+
+ for (l = 2; l <= 93; ++l)
+ {
+ if ((ret = unw_get_reg (&c, UNW_IA64_GR + 33 + l, &v0)) < 0
+ || (ret = unw_get_reg (&c, UNW_IA64_NAT + 33 + l, &n0)) < 0)
+ break;
+ switch (l)
+ {
+ case 2: case 31: case 73: case 93:
+ if (!n0)
+ panic ("\texpected loc%d to be a NaT!\n", l);
+ break;
+
+ default:
+ if (n0)
+ panic ("\tloc%d is unexpectedly a NaT!\n", l);
+ v1 = ((unw_word_t) (i - NSTACKS) << 32) + l;
+ if (v0 != v1)
+ panic ("\tloc%d expected to be %lx, found to be %lx\n",
+ l, v1, v0);
+ }
+ }
+ }
+ ++i;
+ }
+ while ((ret = unw_step (&c)) > 0);
+
+ if (ret < 0)
+ panic ("libunwind returned %d\n", ret);
+}
+
+int
+main (int argc, char **argv)
+{
+ if (argc > 1)
+ ++verbose;
+
+ touch_all (RECURSION_DEPTH);
+ if (nerrors)
+ {
+ printf ("FAILURE: detected %d errors\n", nerrors);
+ exit (-1);
+ }
+ if (verbose)
+ printf ("SUCCESS\n");
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/Gperf-simple.c b/src/pal/src/libunwind/tests/Gperf-simple.c
new file mode 100644
index 0000000000..e181918214
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Gperf-simple.c
@@ -0,0 +1,264 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <libunwind.h>
+#include "compiler.h"
+
+#include <sys/resource.h>
+#include <sys/time.h>
+
+#define panic(args...) \
+ do { fprintf (stderr, args); exit (-1); } while (0)
+
+long dummy;
+
+static long iterations = 10000;
+static int maxlevel = 100;
+
+#define KB 1024
+#define MB (1024*1024)
+
+static char big[64*MB]; /* should be >> max. cache size */
+
+static inline double
+gettime (void)
+{
+ struct timeval tv;
+
+ gettimeofday (&tv, NULL);
+ return tv.tv_sec + 1e-6*tv.tv_usec;
+}
+
+static int NOINLINE
+measure_unwind (int maxlevel, double *step)
+{
+ double stop, start;
+ unw_cursor_t cursor;
+ unw_context_t uc;
+ int ret, level = 0;
+
+ unw_getcontext (&uc);
+ if (unw_init_local (&cursor, &uc) < 0)
+ panic ("unw_init_local() failed\n");
+
+ start = gettime ();
+
+ do
+ {
+ ret = unw_step (&cursor);
+ if (ret < 0)
+ panic ("unw_step() failed\n");
+ ++level;
+ }
+ while (ret > 0);
+
+ stop = gettime ();
+
+ if (level <= maxlevel)
+ panic ("Unwound only %d levels, expected at least %d levels\n",
+ level, maxlevel);
+
+ *step = (stop - start) / (double) level;
+ return 0;
+}
+
+static int f1 (int, int, double *);
+
+static int NOINLINE
+g1 (int level, int maxlevel, double *step)
+{
+ if (level == maxlevel)
+ return measure_unwind (maxlevel, step);
+ else
+ /* defeat last-call/sibcall optimization */
+ return f1 (level + 1, maxlevel, step) + level;
+}
+
+static int NOINLINE
+f1 (int level, int maxlevel, double *step)
+{
+ if (level == maxlevel)
+ return measure_unwind (maxlevel, step);
+ else
+ /* defeat last-call/sibcall optimization */
+ return g1 (level + 1, maxlevel, step) + level;
+}
+
+static void
+doit (const char *label)
+{
+ double step, min_step, first_step, sum_step;
+ int i;
+
+ sum_step = first_step = 0.0;
+ min_step = 1e99;
+ for (i = 0; i < iterations; ++i)
+ {
+ f1 (0, maxlevel, &step);
+
+ sum_step += step;
+
+ if (step < min_step)
+ min_step = step;
+
+ if (i == 0)
+ first_step = step;
+ }
+ printf ("%s: unw_step : 1st=%9.3f min=%9.3f avg=%9.3f nsec\n", label,
+ 1e9*first_step, 1e9*min_step, 1e9*sum_step/iterations);
+}
+
+static long
+sum (void *buf, size_t size)
+{
+ long s = 0;
+ char *cp = buf;
+ size_t i;
+
+ for (i = 0; i < size; i += 8)
+ s += cp[i];
+ return s;
+}
+
+static void
+measure_init (void)
+{
+# define N 100
+# define M 10 /* must be at least 2 to get steady-state */
+ double stop, start, get_cold, get_warm, init_cold, init_warm, delta;
+ struct
+ {
+ unw_cursor_t c;
+ char padding[1024]; /* should be > 2 * max. cacheline size */
+ }
+ cursor[N];
+ struct
+ {
+ unw_context_t uc;
+ char padding[1024]; /* should be > 2 * max. cacheline size */
+ }
+ uc[N];
+ int i, j;
+
+ /* Run each test M times and take the minimum to filter out noise
+ such dynamic linker resolving overhead, context-switches,
+ page-in, cache, and TLB effects. */
+
+ get_cold = 1e99;
+ for (j = 0; j < M; ++j)
+ {
+ dummy += sum (big, sizeof (big)); /* flush the cache */
+ for (i = 0; i < N; ++i)
+ uc[i].padding[511] = i; /* warm up the TLB */
+ start = gettime ();
+ for (i = 0; i < N; ++i)
+ unw_getcontext (&uc[i].uc);
+ stop = gettime ();
+ delta = (stop - start) / N;
+ if (delta < get_cold)
+ get_cold = delta;
+ }
+
+ init_cold = 1e99;
+ for (j = 0; j < M; ++j)
+ {
+ dummy += sum (big, sizeof (big)); /* flush cache */
+ for (i = 0; i < N; ++i)
+ uc[i].padding[511] = i; /* warm up the TLB */
+ start = gettime ();
+ for (i = 0; i < N; ++i)
+ unw_init_local (&cursor[i].c, &uc[i].uc);
+ stop = gettime ();
+ delta = (stop - start) / N;
+ if (delta < init_cold)
+ init_cold = delta;
+ }
+
+ get_warm = 1e99;
+ for (j = 0; j < M; ++j)
+ {
+ start = gettime ();
+ for (i = 0; i < N; ++i)
+ unw_getcontext (&uc[0].uc);
+ stop = gettime ();
+ delta = (stop - start) / N;
+ if (delta < get_warm)
+ get_warm = delta;
+ }
+
+ init_warm = 1e99;
+ for (j = 0; j < M; ++j)
+ {
+ start = gettime ();
+ for (i = 0; i < N; ++i)
+ unw_init_local (&cursor[0].c, &uc[0].uc);
+ stop = gettime ();
+ delta = (stop - start) / N;
+ if (delta < init_warm)
+ init_warm = delta;
+ }
+
+ printf ("unw_getcontext : cold avg=%9.3f nsec, warm avg=%9.3f nsec\n",
+ 1e9 * get_cold, 1e9 * get_warm);
+ printf ("unw_init_local : cold avg=%9.3f nsec, warm avg=%9.3f nsec\n",
+ 1e9 * init_cold, 1e9 * init_warm);
+}
+
+int
+main (int argc, char **argv)
+{
+ struct rlimit rlim;
+
+ rlim.rlim_cur = RLIM_INFINITY;
+ rlim.rlim_max = RLIM_INFINITY;
+ setrlimit (RLIMIT_STACK, &rlim);
+
+ memset (big, 0xaa, sizeof (big));
+
+ if (argc > 1)
+ {
+ maxlevel = atol (argv[1]);
+ if (argc > 2)
+ iterations = atol (argv[2]);
+ }
+
+ measure_init ();
+
+ doit ("default ");
+
+ unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_NONE);
+ doit ("no cache ");
+
+ unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_GLOBAL);
+ doit ("global cache ");
+
+ unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_PER_THREAD);
+ doit ("per-thread cache");
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/Gperf-trace.c b/src/pal/src/libunwind/tests/Gperf-trace.c
new file mode 100644
index 0000000000..4d24fa5ca8
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Gperf-trace.c
@@ -0,0 +1,250 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <libunwind.h>
+#include "compiler.h"
+
+#include <sys/resource.h>
+#include <sys/time.h>
+
+#define panic(args...) \
+ do { fprintf (stderr, args); exit (-1); } while (0)
+
+long dummy;
+
+static long iterations = 10000;
+static int maxlevel = 100;
+
+#define KB 1024
+#define MB (1024*1024)
+
+static char big[64*MB]; /* should be >> max. cache size */
+
+static inline double
+gettime (void)
+{
+ struct timeval tv;
+
+ gettimeofday (&tv, NULL);
+ return tv.tv_sec + 1e-6*tv.tv_usec;
+}
+
+static int NOINLINE
+measure_unwind (int maxlevel, double *step)
+{
+ double stop, start;
+ int level = 0;
+ void *buffer[128];
+
+ start = gettime ();
+ level = unw_backtrace(buffer, 128);
+ stop = gettime ();
+
+ if (level <= maxlevel)
+ panic ("Unwound only %d levels, expected at least %d levels\n",
+ level, maxlevel);
+
+ *step = (stop - start) / (double) level;
+ return 0;
+}
+
+static int f1 (int, int, double *);
+
+static int NOINLINE
+g1 (int level, int maxlevel, double *step)
+{
+ if (level == maxlevel)
+ return measure_unwind (maxlevel, step);
+ else
+ /* defeat last-call/sibcall optimization */
+ return f1 (level + 1, maxlevel, step) + level;
+}
+
+static int NOINLINE
+f1 (int level, int maxlevel, double *step)
+{
+ if (level == maxlevel)
+ return measure_unwind (maxlevel, step);
+ else
+ /* defeat last-call/sibcall optimization */
+ return g1 (level + 1, maxlevel, step) + level;
+}
+
+static void
+doit (const char *label)
+{
+ double step, min_step, first_step, sum_step;
+ int i;
+
+ sum_step = first_step = 0.0;
+ min_step = 1e99;
+ for (i = 0; i < iterations; ++i)
+ {
+ f1 (0, maxlevel, &step);
+
+ sum_step += step;
+
+ if (step < min_step)
+ min_step = step;
+
+ if (i == 0)
+ first_step = step;
+ }
+ printf ("%s: unw_step : 1st=%9.3f min=%9.3f avg=%9.3f nsec\n", label,
+ 1e9*first_step, 1e9*min_step, 1e9*sum_step/iterations);
+}
+
+static long
+sum (void *buf, size_t size)
+{
+ long s = 0;
+ char *cp = buf;
+ size_t i;
+
+ for (i = 0; i < size; i += 8)
+ s += cp[i];
+ return s;
+}
+
+static void
+measure_init (void)
+{
+# define N 100
+# define M 10 /* must be at least 2 to get steady-state */
+ double stop, start, get_cold, get_warm, init_cold, init_warm, delta;
+ struct
+ {
+ unw_cursor_t c;
+ char padding[1024]; /* should be > 2 * max. cacheline size */
+ }
+ cursor[N];
+ struct
+ {
+ unw_context_t uc;
+ char padding[1024]; /* should be > 2 * max. cacheline size */
+ }
+ uc[N];
+ int i, j;
+
+ /* Run each test M times and take the minimum to filter out noise
+ such dynamic linker resolving overhead, context-switches,
+ page-in, cache, and TLB effects. */
+
+ get_cold = 1e99;
+ for (j = 0; j < M; ++j)
+ {
+ dummy += sum (big, sizeof (big)); /* flush the cache */
+ for (i = 0; i < N; ++i)
+ uc[i].padding[511] = i; /* warm up the TLB */
+ start = gettime ();
+ for (i = 0; i < N; ++i)
+ unw_getcontext (&uc[i].uc);
+ stop = gettime ();
+ delta = (stop - start) / N;
+ if (delta < get_cold)
+ get_cold = delta;
+ }
+
+ init_cold = 1e99;
+ for (j = 0; j < M; ++j)
+ {
+ dummy += sum (big, sizeof (big)); /* flush cache */
+ for (i = 0; i < N; ++i)
+ uc[i].padding[511] = i; /* warm up the TLB */
+ start = gettime ();
+ for (i = 0; i < N; ++i)
+ unw_init_local (&cursor[i].c, &uc[i].uc);
+ stop = gettime ();
+ delta = (stop - start) / N;
+ if (delta < init_cold)
+ init_cold = delta;
+ }
+
+ get_warm = 1e99;
+ for (j = 0; j < M; ++j)
+ {
+ start = gettime ();
+ for (i = 0; i < N; ++i)
+ unw_getcontext (&uc[0].uc);
+ stop = gettime ();
+ delta = (stop - start) / N;
+ if (delta < get_warm)
+ get_warm = delta;
+ }
+
+ init_warm = 1e99;
+ for (j = 0; j < M; ++j)
+ {
+ start = gettime ();
+ for (i = 0; i < N; ++i)
+ unw_init_local (&cursor[0].c, &uc[0].uc);
+ stop = gettime ();
+ delta = (stop - start) / N;
+ if (delta < init_warm)
+ init_warm = delta;
+ }
+
+ printf ("unw_getcontext : cold avg=%9.3f nsec, warm avg=%9.3f nsec\n",
+ 1e9 * get_cold, 1e9 * get_warm);
+ printf ("unw_init_local : cold avg=%9.3f nsec, warm avg=%9.3f nsec\n",
+ 1e9 * init_cold, 1e9 * init_warm);
+}
+
+int
+main (int argc, char **argv)
+{
+ struct rlimit rlim;
+
+ rlim.rlim_cur = RLIM_INFINITY;
+ rlim.rlim_max = RLIM_INFINITY;
+ setrlimit (RLIMIT_STACK, &rlim);
+
+ memset (big, 0xaa, sizeof (big));
+
+ if (argc > 1)
+ {
+ maxlevel = atol (argv[1]);
+ if (argc > 2)
+ iterations = atol (argv[2]);
+ }
+
+ measure_init ();
+
+ doit ("default ");
+
+ unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_NONE);
+ doit ("no cache ");
+
+ unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_GLOBAL);
+ doit ("global cache ");
+
+ unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_PER_THREAD);
+ doit ("per-thread cache");
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/Gtest-bt.c b/src/pal/src/libunwind/tests/Gtest-bt.c
new file mode 100644
index 0000000000..beae2a3ccd
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Gtest-bt.c
@@ -0,0 +1,263 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "compiler.h"
+
+#include <errno.h>
+#if HAVE_EXECINFO_H
+# include <execinfo.h>
+#else
+ extern int backtrace (void **, int);
+#endif
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ucontext.h>
+#include <unistd.h>
+#include <libunwind.h>
+
+#define panic(args...) \
+ { fprintf (stderr, args); exit (-1); }
+
+#define SIG_STACK_SIZE 0x100000
+
+int verbose;
+int num_errors;
+
+/* These variables are global because they
+ * cause the signal stack to overflow */
+char buf[512], name[256];
+unw_cursor_t cursor;
+unw_context_t uc;
+
+static void
+do_backtrace (void)
+{
+ unw_word_t ip, sp, off;
+ unw_proc_info_t pi;
+ int ret;
+
+ if (verbose)
+ printf ("\texplicit backtrace:\n");
+
+ unw_getcontext (&uc);
+ if (unw_init_local (&cursor, &uc) < 0)
+ panic ("unw_init_local failed!\n");
+
+ do
+ {
+ unw_get_reg (&cursor, UNW_REG_IP, &ip);
+ unw_get_reg (&cursor, UNW_REG_SP, &sp);
+ buf[0] = '\0';
+ if (unw_get_proc_name (&cursor, name, sizeof (name), &off) == 0)
+ {
+ if (off)
+ snprintf (buf, sizeof (buf), "<%s+0x%lx>", name, (long) off);
+ else
+ snprintf (buf, sizeof (buf), "<%s>", name);
+ }
+ if (verbose)
+ {
+ printf ("%016lx %-32s (sp=%016lx)\n", (long) ip, buf, (long) sp);
+
+ if (unw_get_proc_info (&cursor, &pi) == 0)
+ {
+ printf ("\tproc=0x%lx-0x%lx\n\thandler=0x%lx lsda=0x%lx gp=0x%lx",
+ (long) pi.start_ip, (long) pi.end_ip,
+ (long) pi.handler, (long) pi.lsda, (long) pi.gp);
+ }
+
+#if UNW_TARGET_IA64
+ {
+ unw_word_t bsp;
+
+ unw_get_reg (&cursor, UNW_IA64_BSP, &bsp);
+ printf (" bsp=%lx", bsp);
+ }
+#endif
+ printf ("\n");
+ }
+
+ ret = unw_step (&cursor);
+ if (ret < 0)
+ {
+ unw_get_reg (&cursor, UNW_REG_IP, &ip);
+ printf ("FAILURE: unw_step() returned %d for ip=%lx\n",
+ ret, (long) ip);
+ ++num_errors;
+ }
+ }
+ while (ret > 0);
+
+ {
+ void *buffer[20];
+ int i, n;
+
+ if (verbose)
+ printf ("\n\tvia backtrace():\n");
+ n = backtrace (buffer, 20);
+ if (verbose)
+ for (i = 0; i < n; ++i)
+ printf ("[%d] ip=%p\n", i, buffer[i]);
+ }
+}
+
+void
+foo (long val UNUSED)
+{
+ do_backtrace ();
+}
+
+void
+bar (long v)
+{
+ extern long f (long);
+ int arr[v];
+
+ /* This is a vain attempt to use up lots of registers to force
+ the frame-chain info to be saved on the memory stack on ia64.
+ It happens to work with gcc v3.3.4 and gcc v3.4.1 but perhaps
+ not with any other compiler. */
+ foo (f (arr[0]) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + f (v))
+ ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+ )))))))))))))))))))))))))))))))))))))))))))))))))))))));
+}
+
+void
+sighandler (int signal, void *siginfo UNUSED, void *context)
+{
+ ucontext_t *uc UNUSED;
+ int sp;
+
+ uc = context;
+
+ if (verbose)
+ {
+ printf ("sighandler: got signal %d, sp=%p", signal, &sp);
+#if UNW_TARGET_IA64
+# if defined(__linux__)
+ printf (" @ %lx", uc->uc_mcontext.sc_ip);
+# else
+ {
+ uint16_t reason;
+ uint64_t ip;
+
+ __uc_get_reason (uc, &reason);
+ __uc_get_ip (uc, &ip);
+ printf (" @ %lx (reason=%d)", ip, reason);
+ }
+# endif
+#elif UNW_TARGET_X86
+#if defined __linux__
+ printf (" @ %lx", (unsigned long) uc->uc_mcontext.gregs[REG_EIP]);
+#elif defined __FreeBSD__
+ printf (" @ %lx", (unsigned long) uc->uc_mcontext.mc_eip);
+#endif
+#elif UNW_TARGET_X86_64
+#if defined __linux__
+ printf (" @ %lx", (unsigned long) uc->uc_mcontext.gregs[REG_RIP]);
+#elif defined __FreeBSD__
+ printf (" @ %lx", (unsigned long) uc->uc_mcontext.mc_rip);
+#endif
+#endif
+ printf ("\n");
+ }
+ do_backtrace();
+}
+
+int
+main (int argc, char **argv UNUSED)
+{
+ struct sigaction act;
+ stack_t stk;
+
+ verbose = (argc > 1);
+
+ if (verbose)
+ printf ("Normal backtrace:\n");
+
+ bar (1);
+
+ memset (&act, 0, sizeof (act));
+ act.sa_handler = (void (*)(int)) sighandler;
+ act.sa_flags = SA_SIGINFO;
+ if (sigaction (SIGTERM, &act, NULL) < 0)
+ panic ("sigaction: %s\n", strerror (errno));
+
+ if (verbose)
+ printf ("\nBacktrace across signal handler:\n");
+ kill (getpid (), SIGTERM);
+
+ if (verbose)
+ printf ("\nBacktrace across signal handler on alternate stack:\n");
+ stk.ss_sp = malloc (SIG_STACK_SIZE);
+ if (!stk.ss_sp)
+ panic ("failed to allocate %u bytes\n", SIG_STACK_SIZE);
+ stk.ss_size = SIG_STACK_SIZE;
+ stk.ss_flags = 0;
+ if (sigaltstack (&stk, NULL) < 0)
+ panic ("sigaltstack: %s\n", strerror (errno));
+
+ memset (&act, 0, sizeof (act));
+ act.sa_handler = (void (*)(int)) sighandler;
+ act.sa_flags = SA_ONSTACK | SA_SIGINFO;
+ if (sigaction (SIGTERM, &act, NULL) < 0)
+ panic ("sigaction: %s\n", strerror (errno));
+ kill (getpid (), SIGTERM);
+
+ if (num_errors > 0)
+ {
+ fprintf (stderr, "FAILURE: detected %d errors\n", num_errors);
+ exit (-1);
+ }
+ if (verbose)
+ printf ("SUCCESS.\n");
+
+ signal (SIGTERM, SIG_DFL);
+ stk.ss_flags = SS_DISABLE;
+ sigaltstack (&stk, NULL);
+ free (stk.ss_sp);
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/Gtest-concurrent.c b/src/pal/src/libunwind/tests/Gtest-concurrent.c
new file mode 100644
index 0000000000..6f3447fd84
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Gtest-concurrent.c
@@ -0,0 +1,136 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Verify that multi-threaded concurrent unwinding works as expected. */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "compiler.h"
+
+#include <libunwind.h>
+#include <limits.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define NTHREADS 128
+
+#define panic(args...) \
+ do { fprintf (stderr, args); ++nerrors; } while (0)
+
+int verbose;
+int nerrors;
+int got_usr1, got_usr2;
+char *sigusr1_sp;
+
+void
+handler (int sig UNUSED)
+{
+ unw_word_t ip;
+ unw_context_t uc;
+ unw_cursor_t c;
+ int ret;
+
+ unw_getcontext (&uc);
+ unw_init_local (&c, &uc);
+ do
+ {
+ unw_get_reg (&c, UNW_REG_IP, &ip);
+ if (verbose)
+ printf ("%lx: IP=%lx\n", (long) pthread_self (), (unsigned long) ip);
+ }
+ while ((ret = unw_step (&c)) > 0);
+
+ if (ret < 0)
+ panic ("unw_step() returned %d\n", ret);
+}
+
+void *
+worker (void *arg UNUSED)
+{
+ signal (SIGUSR1, handler);
+
+ if (verbose)
+ printf ("sending SIGUSR1\n");
+ pthread_kill (pthread_self (), SIGUSR1);
+ return NULL;
+}
+
+static void
+doit (void)
+{
+ pthread_t th[NTHREADS];
+ pthread_attr_t attr;
+ int i;
+
+ pthread_attr_init (&attr);
+ pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN + 64*1024);
+
+ for (i = 0; i < NTHREADS; ++i)
+ if (pthread_create (th + i, &attr, worker, NULL))
+ {
+ fprintf (stderr, "FAILURE: Failed to create %u threads "
+ "(after %u threads)\n",
+ NTHREADS, i);
+ exit (-1);
+ }
+
+ for (i = 0; i < NTHREADS; ++i)
+ pthread_join (th[i], NULL);
+}
+
+int
+main (int argc, char **argv UNUSED)
+{
+ if (argc > 1)
+ verbose = 1;
+
+ if (verbose)
+ printf ("Caching: none\n");
+ unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_NONE);
+ doit ();
+
+ if (verbose)
+ printf ("Caching: global\n");
+ unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_GLOBAL);
+ doit ();
+
+ if (verbose)
+ printf ("Caching: per-thread\n");
+ unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_PER_THREAD);
+ doit ();
+
+ if (nerrors)
+ {
+ fprintf (stderr, "FAILURE: detected %d errors\n", nerrors);
+ exit (-1);
+ }
+
+ if (verbose)
+ printf ("SUCCESS\n");
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/Gtest-dyn1.c b/src/pal/src/libunwind/tests/Gtest-dyn1.c
new file mode 100644
index 0000000000..bc7dc9cf7f
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Gtest-dyn1.c
@@ -0,0 +1,223 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* This file tests dynamic code-generation via function-cloning. */
+
+#include "flush-cache.h"
+
+#include "compiler.h"
+
+#include <libunwind.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/mman.h>
+
+#if UNW_TARGET_ARM
+#define MAX_FUNC_SIZE 96 /* FIXME: arch/compiler dependent */
+#else
+#define MAX_FUNC_SIZE 2048 /* max. size of cloned function */
+#endif
+
+#define panic(args...) \
+ { fprintf (stderr, args); exit (-1); }
+
+typedef void (*template_t) (int, void (*)(),
+ int (*)(const char *, ...), const char *,
+ const char **);
+
+int verbose;
+
+static const char *strarr[] =
+ {
+ "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix", "x", NULL
+ };
+
+#ifdef __ia64__
+struct fdesc
+ {
+ long code;
+ long gp;
+ };
+# define get_fdesc(fdesc,func) (fdesc = *(struct fdesc *) &(func))
+# define get_funcp(fdesc) ((template_t) &(fdesc))
+# define get_gp(fdesc) ((fdesc).gp)
+#elif __arm__
+struct fdesc
+ {
+ long code;
+ long is_thumb;
+ };
+/* Workaround GCC bug: https://bugs.launchpad.net/gcc-linaro/+bug/721531 */
+# define get_fdesc(fdesc,func) ({long tmp = (long) &(func); \
+ (fdesc).code = (long) &(func) & ~0x1; \
+ (fdesc).is_thumb = tmp & 0x1;})
+/*# define get_fdesc(fdesc,func) ({(fdesc).code = (long) &(func) & ~0x1; \
+ (fdesc).is_thumb = (long) &(func) & 0x1;})*/
+# define get_funcp(fdesc) ((template_t) ((fdesc).code | (fdesc).is_thumb))
+# define get_gp(fdesc) (0)
+#else
+struct fdesc
+ {
+ long code;
+ };
+# define get_fdesc(fdesc,func) (fdesc.code = (long) &(func))
+# define get_funcp(fdesc) ((template_t) (fdesc).code)
+# define get_gp(fdesc) (0)
+#endif
+
+void
+template (int i, template_t self,
+ int (*printer)(const char *, ...), const char *fmt, const char **arr)
+{
+ (*printer) (fmt, arr[11 - i][0], arr[11 - i] + 1);
+ if (i > 0)
+ (*self) (i - 1, self, printer, fmt, arr);
+}
+
+static void
+sighandler (int signal)
+{
+ unw_cursor_t cursor;
+ char name[128], off[32];
+ unw_word_t ip, offset;
+ unw_context_t uc;
+ int count;
+
+ if (verbose)
+ printf ("caught signal %d\n", signal);
+
+ unw_getcontext (&uc);
+ unw_init_local (&cursor, &uc);
+
+ count = 0;
+ while (!unw_is_signal_frame (&cursor))
+ {
+ if (unw_step (&cursor) < 0)
+ panic ("failed to find signal frame!\n");
+
+ if (count++ > 20)
+ {
+ panic ("Too many steps to the signal frame (%d)\n", count);
+ break;
+ }
+ }
+ unw_step (&cursor);
+
+ count = 0;
+ do
+ {
+ unw_get_reg (&cursor, UNW_REG_IP, &ip);
+ name[0] = '\0';
+ off[0] = '\0';
+ if (unw_get_proc_name (&cursor, name, sizeof (name), &offset) == 0
+ && offset > 0)
+ snprintf (off, sizeof (off), "+0x%lx", (long) offset);
+ if (verbose)
+ printf ("ip = %lx <%s%s>\n", (long) ip, name, off);
+ ++count;
+
+ if (count > 20)
+ {
+ panic ("Too many steps (%d)\n", count);
+ break;
+ }
+
+ }
+ while (unw_step (&cursor) > 0);
+
+ if (count != 13)
+ panic ("FAILURE: expected 13, not %d frames below signal frame\n", count);
+
+ if (verbose)
+ printf ("SUCCESS\n");
+ exit (0);
+}
+
+int
+dev_null (const char *format UNUSED, ...)
+{
+ return 0;
+}
+
+int
+main (int argc, char *argv[] UNUSED)
+{
+ unw_dyn_region_info_t *region;
+ unw_dyn_info_t di;
+ struct fdesc fdesc;
+ template_t funcp;
+ void *mem;
+
+ if (argc > 1)
+ ++verbose;
+
+ mem = malloc (getpagesize ());
+
+ get_fdesc (fdesc, template);
+
+ if (verbose)
+ printf ("old code @ %p, new code @ %p\n", (void *) fdesc.code, mem);
+
+ memcpy (mem, (void *) fdesc.code, MAX_FUNC_SIZE);
+ mprotect ((void *) ((long) mem & ~(getpagesize () - 1)),
+ 2*getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC);
+
+ flush_cache (mem, MAX_FUNC_SIZE);
+
+ signal (SIGSEGV, sighandler);
+
+ /* register the new function: */
+ region = alloca (_U_dyn_region_info_size (2));
+ region->next = NULL;
+ region->insn_count = 3 * (MAX_FUNC_SIZE / 16);
+ region->op_count = 2;
+ _U_dyn_op_alias (&region->op[0], 0, -1, fdesc.code);
+ _U_dyn_op_stop (&region->op[1]);
+
+ memset (&di, 0, sizeof (di));
+ di.start_ip = (long) mem;
+ di.end_ip = (long) mem + 16*region->insn_count/3;
+ di.gp = get_gp (fdesc);
+ di.format = UNW_INFO_FORMAT_DYNAMIC;
+ di.u.pi.name_ptr = (unw_word_t) "copy_of_template";
+ di.u.pi.regions = region;
+
+ _U_dyn_register (&di);
+
+ /* call new function: */
+ fdesc.code = (long) mem;
+ funcp = get_funcp (fdesc);
+
+ if (verbose)
+ (*funcp) (10, funcp, printf, "iteration %c%s\n", strarr);
+ else
+ (*funcp) (10, funcp, dev_null, "iteration %c%s\n", strarr);
+
+ _U_dyn_cancel (&di);
+ return -1;
+}
diff --git a/src/pal/src/libunwind/tests/Gtest-exc.c b/src/pal/src/libunwind/tests/Gtest-exc.c
new file mode 100644
index 0000000000..1170bdd03f
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Gtest-exc.c
@@ -0,0 +1,162 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* This illustrates the basics of using the unwind interface for
+ exception handling. */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <libunwind.h>
+
+#ifdef HAVE_IA64INTRIN_H
+# include <ia64intrin.h>
+#endif
+
+#define panic(args...) \
+ { ++nerrors; fprintf (stderr, args); }
+
+int nerrors = 0;
+int verbose = 0;
+int depth = 13;
+volatile int got_here = 0;
+
+extern void b (int);
+
+void
+raise_exception (void)
+{
+ unw_cursor_t cursor;
+ unw_context_t uc;
+ int i;
+
+ unw_getcontext (&uc);
+ if (unw_init_local (&cursor, &uc) < 0)
+ {
+ panic ("unw_init_local() failed!\n");
+ return;
+ }
+
+ /* unwind to top-most frame a(), skipping over b() and raise_exception(): */
+ for (i = 0; i < depth + 2; ++i)
+ if (unw_step (&cursor) < 0)
+ {
+ panic ("unw_step() failed!\n");
+ return;
+ }
+ unw_resume (&cursor); /* transfer control to exception handler */
+}
+
+uintptr_t
+get_bsp (void)
+{
+#if UNW_TARGET_IA64
+# ifdef __INTEL_COMPILER
+ return __getReg (_IA64_REG_AR_BSP);
+# else
+ return (uintptr_t) __builtin_ia64_bsp ();
+# endif
+#else
+ return 0;
+#endif
+}
+
+int
+a (int n)
+{
+ long stack;
+ int result = 99;
+
+ if (verbose)
+ printf ("a(n=%d): sp=%p bsp=0x%lx\n",
+ n, &stack, (unsigned long) get_bsp ());
+
+ if (n > 0)
+ a (n - 1);
+ else
+ b (16);
+
+ if (verbose)
+ {
+ printf ("exception handler: here we go (sp=%p, bsp=0x%lx)...\n",
+ &stack, (unsigned long) get_bsp ());
+ /* This call works around a bug in gcc (up-to pre3.4) which
+ causes invalid assembly code to be generated when
+ __builtin_ia64_bsp() gets predicated. */
+ getpid ();
+ }
+ if (n == depth)
+ {
+ result = 0;
+ got_here = 1;
+ }
+ return result;
+}
+
+void
+b (int n)
+{
+ if ((n & 1) == 0)
+ {
+ if (verbose)
+ printf ("b(n=%d) calling raise_exception()\n", n);
+ raise_exception ();
+ }
+ panic ("FAILURE: b() returned from raise_exception()!!\n");
+}
+
+int
+main (int argc, char **argv)
+{
+ int result;
+
+ if (argc > 1)
+ {
+ ++verbose;
+ depth = atol (argv[1]);
+ if (depth < 1)
+ {
+ fprintf (stderr, "Usage: %s depth\n"
+ " depth must be >= 1\n", argv[0]);
+ exit (-1);
+ }
+ }
+
+ result = a (depth);
+ if (result != 0 || !got_here || nerrors > 0)
+ {
+ fprintf (stderr,
+ "FAILURE: test failed: result=%d got_here=%d nerrors=%d\n",
+ result, got_here, nerrors);
+ exit (-1);
+ }
+
+ if (verbose)
+ printf ("SUCCESS!\n");
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/Gtest-init.cxx b/src/pal/src/libunwind/tests/Gtest-init.cxx
new file mode 100644
index 0000000000..afded01927
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Gtest-init.cxx
@@ -0,0 +1,107 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2002-2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* This file tests unwinding from a constructor from within an
+ atexit() handler. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <libunwind.h>
+#include "compiler.h"
+
+int verbose, errors;
+
+#define panic(args...) \
+ { ++errors; fprintf (stderr, args); return; }
+
+class Test_Class {
+ public:
+ Test_Class (void);
+};
+
+static Test_Class t;
+
+static void
+do_backtrace (void)
+{
+ char name[128], off[32];
+ unw_word_t ip, offset;
+ unw_cursor_t cursor;
+ unw_context_t uc;
+ int ret, count = 0;
+
+ unw_getcontext (&uc);
+ unw_init_local (&cursor, &uc);
+
+ do
+ {
+ unw_get_reg (&cursor, UNW_REG_IP, &ip);
+ name[0] = '\0';
+ off[0] = '\0';
+ if (unw_get_proc_name (&cursor, name, sizeof (name), &offset) == 0
+ && offset > 0)
+ snprintf (off, sizeof (off), "+0x%lx", (long) offset);
+ if (verbose)
+ printf (" [%lx] <%s%s>\n", (long) ip, name, off);
+ if (++count > 32)
+ panic ("FAILURE: didn't reach beginning of unwind-chain\n");
+ }
+ while ((ret = unw_step (&cursor)) > 0);
+
+ if (ret < 0)
+ panic ("FAILURE: unw_step() returned %d\n", ret);
+}
+
+static void
+b (void)
+{
+ do_backtrace();
+}
+
+static void
+a (void)
+{
+ if (verbose)
+ printf ("do_backtrace() from atexit()-handler:\n");
+ b();
+ if (errors)
+ abort (); /* cannot portably call exit() from an atexit() handler */
+}
+
+Test_Class::Test_Class (void)
+{
+ if (verbose)
+ printf ("do_backtrace() from constructor:\n");
+ b();
+}
+
+int
+main (int argc, char **argv UNUSED)
+{
+ verbose = argc > 1;
+ return atexit (a);
+}
diff --git a/src/pal/src/libunwind/tests/Gtest-nomalloc.c b/src/pal/src/libunwind/tests/Gtest-nomalloc.c
new file mode 100644
index 0000000000..5b97fc7091
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Gtest-nomalloc.c
@@ -0,0 +1,110 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2009 Google, Inc
+ Contributed by Arun Sharma <arun.sharma@google.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <libunwind.h>
+
+#define panic(args...) \
+ { fprintf (stderr, args); exit (-1); }
+
+int verbose;
+int num_errors;
+int in_unwind;
+
+void *
+malloc(size_t s)
+{
+ static void * (*func)();
+
+ if(!func)
+ func = (void *(*)()) dlsym(RTLD_NEXT, "malloc");
+
+ if (in_unwind) {
+ num_errors++;
+ return NULL;
+ } else {
+ return func(s);
+ }
+}
+
+static void
+do_backtrace (void)
+{
+ unw_word_t ip, sp;
+ unw_cursor_t cursor;
+ unw_context_t uc;
+ int ret;
+
+ in_unwind = 1;
+ unw_getcontext (&uc);
+ if (unw_init_local (&cursor, &uc) < 0)
+ panic ("unw_init_local failed!\n");
+
+ do
+ {
+ unw_get_reg (&cursor, UNW_REG_IP, &ip);
+ unw_get_reg (&cursor, UNW_REG_SP, &sp);
+
+ ret = unw_step (&cursor);
+ if (ret < 0)
+ {
+ ++num_errors;
+ }
+ }
+ while (ret > 0);
+ in_unwind = 0;
+}
+
+void
+foo3 (void)
+{
+ do_backtrace ();
+}
+
+void
+foo2 (void)
+{
+ foo3 ();
+}
+
+void
+foo1 (void)
+{
+ foo2 ();
+}
+
+int
+main (void)
+{
+ foo1();
+
+ if (num_errors > 0)
+ {
+ fprintf (stderr, "FAILURE: detected %d errors\n", num_errors);
+ exit (-1);
+ }
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/Gtest-resume-sig-rt.c b/src/pal/src/libunwind/tests/Gtest-resume-sig-rt.c
new file mode 100644
index 0000000000..df515fc195
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Gtest-resume-sig-rt.c
@@ -0,0 +1,31 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* The purpose of this test is to invoke different code paths in libunwind (on
+ * some architectures), that are executed when the SA_SIGINFO sigaction() flag
+ * is used.
+ */
+
+#define TEST_WITH_SIGINFO 1
+#include "Gtest-resume-sig.c"
diff --git a/src/pal/src/libunwind/tests/Gtest-resume-sig.c b/src/pal/src/libunwind/tests/Gtest-resume-sig.c
new file mode 100644
index 0000000000..18ec65da71
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Gtest-resume-sig.c
@@ -0,0 +1,200 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Verify that unw_resume() restores the signal mask at proper time. */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "compiler.h"
+
+#include <libunwind.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#ifdef HAVE_IA64INTRIN_H
+# include <ia64intrin.h>
+#endif
+
+#define panic(args...) \
+ do { fprintf (stderr, args); ++nerrors; } while (0)
+
+int verbose;
+int nerrors;
+int got_usr1, got_usr2;
+char *sigusr1_sp;
+
+uintptr_t
+get_bsp (void)
+{
+#if UNW_TARGET_IA64
+# ifdef __INTEL_COMPILER
+ return __getReg (_IA64_REG_AR_BSP);
+# else
+ return (uintptr_t) __builtin_ia64_bsp ();
+# endif
+#else
+ return 0;
+#endif
+}
+
+#ifdef TEST_WITH_SIGINFO
+void
+handler (int sig,
+ siginfo_t *si UNUSED,
+ void *ucontext UNUSED)
+#else
+void
+handler (int sig)
+#endif
+{
+ unw_word_t ip;
+ sigset_t mask;
+ unw_context_t uc;
+ unw_cursor_t c;
+ char foo;
+ int ret;
+ // The test rely on SIGUSR2 mask to be cleared when the handler returns.
+ // For local context from the signal handler, there doesn't seem to be a way
+ // currently to set it so just clear the whole struct to make sure the signal mask is cleared.
+ // This should probably be fixed to avoid signal mask being set to random values
+ // by `unw_resume` if the context was not pre-zeroed.,
+ // Using the signal ucontext direction should also work automatically but currently doesn't
+ // on ARM/AArch64 (or any other archs that doesn't have a proper sigreturn implementation)
+ memset(&uc, 0x0, sizeof(uc));
+
+#if UNW_TARGET_IA64
+ if (verbose)
+ printf ("bsp = %llx\n", (unsigned long long) get_bsp ());
+#endif
+
+ if (verbose)
+ printf ("got signal %d\n", sig);
+
+ if (sig == SIGUSR1)
+ {
+ ++got_usr1;
+ sigusr1_sp = &foo;
+
+ sigemptyset (&mask);
+ sigaddset (&mask, SIGUSR2);
+ sigprocmask (SIG_BLOCK, &mask, NULL);
+ kill (getpid (), SIGUSR2); /* pend SIGUSR2 */
+
+ signal (SIGUSR1, SIG_IGN);
+
+ if ((ret = unw_getcontext (&uc)) < 0)
+ panic ("unw_getcontext() failed: ret=%d\n", ret);
+ if ((ret = unw_init_local (&c, &uc)) < 0)
+ panic ("unw_init_local() failed: ret=%d\n", ret);
+
+ if ((ret = unw_step (&c)) < 0) /* step to signal trampoline */
+ panic ("unw_step(1) failed: ret=%d\n", ret);
+
+ if ((ret = unw_step (&c)) < 0) /* step to kill() */
+ panic ("unw_step(2) failed: ret=%d\n", ret);
+
+#if defined(UNW_TARGET_TILEGX)
+ if ((ret = unw_step (&c)) < 0) /* step to signal trampoline */
+ panic ("unw_step(2) failed: ret=%d\n", ret);
+#endif
+
+ if ((ret = unw_get_reg (&c, UNW_REG_IP, &ip)) < 0)
+ panic ("unw_get_reg(IP) failed: ret=%d\n", ret);
+ if (verbose)
+ printf ("resuming at 0x%lx, with SIGUSR2 pending\n",
+ (unsigned long) ip);
+ unw_resume (&c);
+ }
+ else if (sig == SIGUSR2)
+ {
+ ++got_usr2;
+ if (got_usr1)
+ {
+ if (verbose)
+ printf ("OK: stack still at %p\n", &foo);
+ }
+ signal (SIGUSR2, SIG_IGN);
+ }
+ else
+ panic ("Got unexpected signal %d\n", sig);
+}
+
+int
+main (int argc, char **argv UNUSED)
+{
+ struct sigaction sa;
+ float d = 1.0;
+ int n = 0;
+
+ if (argc > 1)
+ verbose = 1;
+
+ memset (&sa, 0, sizeof(sa));
+#ifdef TEST_WITH_SIGINFO
+ sa.sa_sigaction = handler;
+ sa.sa_flags = SA_SIGINFO;
+#else
+ sa.sa_handler = handler;
+#endif
+
+ if (sigaction (SIGUSR1, &sa, NULL) != 0 ||
+ sigaction (SIGUSR2, &sa, NULL) != 0)
+ {
+ fprintf (stderr, "sigaction() failed: %s\n", strerror (errno));
+ return -1;
+ }
+
+ /* Use the FPU a bit; otherwise we get spurious errors should the
+ signal handler need to use the FPU for any reason. This seems to
+ happen on x86-64. */
+ while (d > 0.0)
+ {
+ d /= 2.0;
+ ++n;
+ }
+ if (n > 9999)
+ return -1; /* can't happen, but don't tell the compiler... */
+
+ if (verbose)
+ printf ("sending SIGUSR1\n");
+ kill (getpid (), SIGUSR1);
+
+ if (!got_usr2)
+ panic ("failed to get SIGUSR2\n");
+
+ if (nerrors)
+ {
+ fprintf (stderr, "FAILURE: detected %d errors\n", nerrors);
+ exit (-1);
+ }
+
+ if (verbose)
+ printf ("SUCCESS\n");
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/Gtest-trace.c b/src/pal/src/libunwind/tests/Gtest-trace.c
new file mode 100644
index 0000000000..fc1f646eac
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Gtest-trace.c
@@ -0,0 +1,282 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "compiler.h"
+
+#include <errno.h>
+#if HAVE_EXECINFO_H
+# include <execinfo.h>
+#else
+ extern int backtrace (void **, int);
+#endif
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ucontext.h>
+#include <unistd.h>
+#include <libunwind.h>
+
+#define panic(args...) \
+ { fprintf (stderr, args); exit (-1); }
+
+#define SIG_STACK_SIZE 0x100000
+
+int verbose;
+int num_errors;
+
+/* These variables are global because they
+ * cause the signal stack to overflow */
+char buf[512], name[256];
+void *addresses[3][128];
+unw_cursor_t cursor;
+unw_context_t uc;
+
+static void
+do_backtrace (void)
+{
+ unw_word_t ip;
+ int ret = -UNW_ENOINFO;
+ int depth = 0;
+ int i, n, m;
+
+ if (verbose)
+ printf ("\tnormal trace:\n");
+
+ unw_getcontext (&uc);
+ if (unw_init_local (&cursor, &uc) < 0)
+ panic ("unw_init_local failed!\n");
+
+ do
+ {
+ unw_get_reg (&cursor, UNW_REG_IP, &ip);
+ addresses[0][depth] = (void *) ip;
+ }
+ while ((ret = unw_step (&cursor)) > 0 && ++depth < 128);
+
+ if (ret < 0)
+ {
+ unw_get_reg (&cursor, UNW_REG_IP, &ip);
+ printf ("FAILURE: unw_step() returned %d for ip=%lx\n", ret, (long) ip);
+ ++num_errors;
+ }
+
+ if (verbose)
+ for (i = 0; i < depth; ++i)
+ printf ("\t #%-3d ip=%p\n", i, addresses[0][i]);
+
+ if (verbose)
+ printf ("\n\tvia backtrace():\n");
+
+ n = backtrace (addresses[1], 128);
+
+ if (verbose)
+ for (i = 0; i < n; ++i)
+ printf ("\t #%-3d ip=%p\n", i, addresses[1][i]);
+
+ if (verbose)
+ printf ("\n\tvia unw_backtrace():\n");
+
+ m = unw_backtrace (addresses[2], 128);
+
+ if (verbose)
+ for (i = 0; i < m; ++i)
+ printf ("\t #%-3d ip=%p\n", i, addresses[2][i]);
+
+ if (m != depth+1)
+ {
+ printf ("FAILURE: unw_step() loop and unw_backtrace() depths differ: %d vs. %d\n", depth, m);
+ ++num_errors;
+ }
+
+ if (n != depth+1)
+ {
+ printf ("FAILURE: unw_step() loop and backtrace() depths differ: %d vs. %d\n", depth, n);
+ ++num_errors;
+ }
+
+ if (n == m)
+ for (i = 1; i < n; ++i)
+ /* Allow one in difference in comparison, trace returns adjusted addresses. */
+ if (labs((unw_word_t) addresses[1][i] - (unw_word_t) addresses[2][i]) > 1)
+ {
+ printf ("FAILURE: backtrace() and unw_backtrace() addresses differ at %d: %p vs. %p\n",
+ i, addresses[1][i], addresses[2][i]);
+ ++num_errors;
+ }
+
+ if (n == depth+1)
+ for (i = 1; i < depth; ++i)
+ /* Allow one in difference in comparison, trace returns adjusted addresses. */
+ if (labs((unw_word_t) addresses[0][i] - (unw_word_t) addresses[1][i]) > 1)
+ {
+ printf ("FAILURE: unw_step() loop and backtrace() addresses differ at %d: %p vs. %p\n",
+ i, addresses[0][i], addresses[1][i]);
+ ++num_errors;
+ }
+}
+
+void
+foo (long val UNUSED)
+{
+ do_backtrace ();
+}
+
+void
+bar (long v)
+{
+ extern long f (long);
+ int arr[v];
+
+ /* This is a vain attempt to use up lots of registers to force
+ the frame-chain info to be saved on the memory stack on ia64.
+ It happens to work with gcc v3.3.4 and gcc v3.4.1 but perhaps
+ not with any other compiler. */
+ foo (f (arr[0]) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + f (v))
+ ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+ )))))))))))))))))))))))))))))))))))))))))))))))))))))));
+}
+
+void
+sighandler (int signal, void *siginfo UNUSED, void *context)
+{
+ ucontext_t *uc UNUSED;
+ int sp;
+
+ uc = context;
+
+ if (verbose)
+ {
+ printf ("sighandler: got signal %d, sp=%p", signal, &sp);
+#if UNW_TARGET_IA64
+# if defined(__linux__)
+ printf (" @ %lx", uc->uc_mcontext.sc_ip);
+# else
+ {
+ uint16_t reason;
+ uint64_t ip;
+
+ __uc_get_reason (uc, &reason);
+ __uc_get_ip (uc, &ip);
+ printf (" @ %lx (reason=%d)", ip, reason);
+ }
+# endif
+#elif UNW_TARGET_X86
+#if defined __linux__
+ printf (" @ %lx", (unsigned long) uc->uc_mcontext.gregs[REG_EIP]);
+#elif defined __FreeBSD__
+ printf (" @ %lx", (unsigned long) uc->uc_mcontext.mc_eip);
+#endif
+#elif UNW_TARGET_X86_64
+#if defined __linux__
+ printf (" @ %lx", (unsigned long) uc->uc_mcontext.gregs[REG_RIP]);
+#elif defined __FreeBSD__
+ printf (" @ %lx", (unsigned long) uc->uc_mcontext.mc_rip);
+#endif
+#elif defined UNW_TARGET_ARM
+#if defined __linux__
+ printf (" @ %lx", (unsigned long) uc->uc_mcontext.arm_pc);
+#elif defined __FreeBSD__
+ printf (" @ %lx", (unsigned long) uc->uc_mcontext.__gregs[_REG_PC]);
+#endif
+#endif
+ printf ("\n");
+ }
+ do_backtrace();
+}
+
+int
+main (int argc, char **argv UNUSED)
+{
+ struct sigaction act;
+ stack_t stk;
+
+ verbose = (argc > 1);
+
+ if (verbose)
+ printf ("Normal backtrace:\n");
+
+ bar (1);
+
+ memset (&act, 0, sizeof (act));
+ act.sa_handler = (void (*)(int)) sighandler;
+ act.sa_flags = SA_SIGINFO;
+ if (sigaction (SIGTERM, &act, NULL) < 0)
+ panic ("sigaction: %s\n", strerror (errno));
+
+ if (verbose)
+ printf ("\nBacktrace across signal handler:\n");
+ kill (getpid (), SIGTERM);
+
+ if (verbose)
+ printf ("\nBacktrace across signal handler on alternate stack:\n");
+ stk.ss_sp = malloc (SIG_STACK_SIZE);
+ if (!stk.ss_sp)
+ panic ("failed to allocate %u bytes\n", SIG_STACK_SIZE);
+ stk.ss_size = SIG_STACK_SIZE;
+ stk.ss_flags = 0;
+ if (sigaltstack (&stk, NULL) < 0)
+ panic ("sigaltstack: %s\n", strerror (errno));
+
+ memset (&act, 0, sizeof (act));
+ act.sa_handler = (void (*)(int)) sighandler;
+ act.sa_flags = SA_ONSTACK | SA_SIGINFO;
+ if (sigaction (SIGTERM, &act, NULL) < 0)
+ panic ("sigaction: %s\n", strerror (errno));
+ kill (getpid (), SIGTERM);
+
+ if (num_errors > 0)
+ {
+ fprintf (stderr, "FAILURE: detected %d errors\n", num_errors);
+ exit (-1);
+ }
+
+ if (verbose)
+ printf ("SUCCESS.\n");
+
+ signal (SIGTERM, SIG_DFL);
+ stk.ss_flags = SS_DISABLE;
+ sigaltstack (&stk, NULL);
+ free (stk.ss_sp);
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/Lia64-test-nat.c b/src/pal/src/libunwind/tests/Lia64-test-nat.c
new file mode 100644
index 0000000000..15ef0caccc
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Lia64-test-nat.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if !defined(UNW_REMOTE_ONLY)
+#include "Gia64-test-nat.c"
+#endif
diff --git a/src/pal/src/libunwind/tests/Lia64-test-rbs.c b/src/pal/src/libunwind/tests/Lia64-test-rbs.c
new file mode 100644
index 0000000000..b838ebe42f
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Lia64-test-rbs.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if !defined(UNW_REMOTE_ONLY)
+#include "Gia64-test-rbs.c"
+#endif
diff --git a/src/pal/src/libunwind/tests/Lia64-test-readonly.c b/src/pal/src/libunwind/tests/Lia64-test-readonly.c
new file mode 100644
index 0000000000..cd23e92613
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Lia64-test-readonly.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if !defined(UNW_REMOTE_ONLY)
+#include "Gia64-test-readonly.c"
+#endif
diff --git a/src/pal/src/libunwind/tests/Lia64-test-stack.c b/src/pal/src/libunwind/tests/Lia64-test-stack.c
new file mode 100644
index 0000000000..3647629c90
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Lia64-test-stack.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if !defined(UNW_REMOTE_ONLY)
+#include "Gia64-test-stack.c"
+#endif
diff --git a/src/pal/src/libunwind/tests/Lperf-simple.c b/src/pal/src/libunwind/tests/Lperf-simple.c
new file mode 100644
index 0000000000..cdf38c207a
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Lperf-simple.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if !defined(UNW_REMOTE_ONLY)
+#include "Gperf-simple.c"
+#endif
diff --git a/src/pal/src/libunwind/tests/Lperf-trace.c b/src/pal/src/libunwind/tests/Lperf-trace.c
new file mode 100644
index 0000000000..1c3cf21c21
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Lperf-trace.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if !defined(UNW_REMOTE_ONLY)
+#include "Gperf-trace.c"
+#endif
diff --git a/src/pal/src/libunwind/tests/Lrs-race.c b/src/pal/src/libunwind/tests/Lrs-race.c
new file mode 100644
index 0000000000..6fe4972020
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Lrs-race.c
@@ -0,0 +1,1514 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2005 Hewlett-Packard Co
+ Contributed by Paul Pluzhnikov <ppluzhnikov@google.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Verify that register state caches work under all caching policies
+ in a multi-threaded environment with a large number IPs */
+
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#include "compiler.h"
+
+#include <stdio.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+/* ITERS=1000, NTHREAD=10 caught some bugs in the past */
+#ifndef ITERS
+#define ITERS 100
+#endif
+
+#ifndef NTHREAD
+#define NTHREAD 2
+#endif
+
+int verbose;
+
+void
+foo_0 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_1 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_2 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_3 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_4 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_5 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_6 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_7 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_8 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_9 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_10 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_11 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_12 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_13 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_14 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_15 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_16 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_17 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_18 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_19 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_20 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_21 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_22 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_23 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_24 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_25 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_26 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_27 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_28 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_29 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_30 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_31 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_32 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_33 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_34 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_35 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_36 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_37 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_38 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_39 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_40 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_41 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_42 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_43 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_44 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_45 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_46 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_47 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_48 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_49 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_50 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_51 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_52 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_53 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_54 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_55 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_56 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_57 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_58 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_59 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_60 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_61 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_62 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_63 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_64 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_65 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_66 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_67 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_68 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_69 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_70 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_71 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_72 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_73 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_74 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_75 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_76 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_77 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_78 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_79 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_80 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_81 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_82 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_83 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_84 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_85 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_86 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_87 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_88 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_89 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_90 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_91 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_92 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_93 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_94 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_95 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_96 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_97 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_98 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_99 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_100 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_101 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_102 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_103 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_104 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_105 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_106 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_107 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_108 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_109 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_110 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_111 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_112 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_113 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_114 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_115 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_116 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_117 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_118 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_119 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_120 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_121 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_122 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_123 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_124 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_125 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_126 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_127 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void
+foo_128 (void)
+{
+ void *buf[20];
+ int n;
+
+ if ((n = unw_backtrace (buf, 20)) < 3)
+ abort ();
+}
+
+void *
+bar(void *p UNUSED)
+{
+ int i;
+ for (i = 0; i < ITERS; ++i) {
+ foo_0 ();
+ foo_1 ();
+ foo_2 ();
+ foo_3 ();
+ foo_4 ();
+ foo_5 ();
+ foo_6 ();
+ foo_7 ();
+ foo_8 ();
+ foo_9 ();
+ foo_10 ();
+ foo_11 ();
+ foo_12 ();
+ foo_13 ();
+ foo_14 ();
+ foo_15 ();
+ foo_16 ();
+ foo_17 ();
+ foo_18 ();
+ foo_19 ();
+ foo_20 ();
+ foo_21 ();
+ foo_22 ();
+ foo_23 ();
+ foo_24 ();
+ foo_25 ();
+ foo_26 ();
+ foo_27 ();
+ foo_28 ();
+ foo_29 ();
+ foo_30 ();
+ foo_31 ();
+ foo_32 ();
+ foo_33 ();
+ foo_34 ();
+ foo_35 ();
+ foo_36 ();
+ foo_37 ();
+ foo_38 ();
+ foo_39 ();
+ foo_40 ();
+ foo_41 ();
+ foo_42 ();
+ foo_43 ();
+ foo_44 ();
+ foo_45 ();
+ foo_46 ();
+ foo_47 ();
+ foo_48 ();
+ foo_49 ();
+ foo_50 ();
+ foo_51 ();
+ foo_52 ();
+ foo_53 ();
+ foo_54 ();
+ foo_55 ();
+ foo_56 ();
+ foo_57 ();
+ foo_58 ();
+ foo_59 ();
+ foo_60 ();
+ foo_61 ();
+ foo_62 ();
+ foo_63 ();
+ foo_64 ();
+ foo_65 ();
+ foo_66 ();
+ foo_67 ();
+ foo_68 ();
+ foo_69 ();
+ foo_70 ();
+ foo_71 ();
+ foo_72 ();
+ foo_73 ();
+ foo_74 ();
+ foo_75 ();
+ foo_76 ();
+ foo_77 ();
+ foo_78 ();
+ foo_79 ();
+ foo_80 ();
+ foo_81 ();
+ foo_82 ();
+ foo_83 ();
+ foo_84 ();
+ foo_85 ();
+ foo_86 ();
+ foo_87 ();
+ foo_88 ();
+ foo_89 ();
+ foo_90 ();
+ foo_91 ();
+ foo_92 ();
+ foo_93 ();
+ foo_94 ();
+ foo_95 ();
+ foo_96 ();
+ foo_97 ();
+ foo_98 ();
+ foo_99 ();
+ foo_100 ();
+ foo_101 ();
+ foo_102 ();
+ foo_103 ();
+ foo_104 ();
+ foo_105 ();
+ foo_106 ();
+ foo_107 ();
+ foo_108 ();
+ foo_109 ();
+ foo_110 ();
+ foo_111 ();
+ foo_112 ();
+ foo_113 ();
+ foo_114 ();
+ foo_115 ();
+ foo_116 ();
+ foo_117 ();
+ foo_118 ();
+ foo_119 ();
+ foo_120 ();
+ foo_121 ();
+ foo_122 ();
+ foo_123 ();
+ foo_124 ();
+ foo_125 ();
+ foo_126 ();
+ foo_127 ();
+ foo_128 ();
+ }
+ return NULL;
+}
+
+int doit (void)
+{
+ pthread_t tid[NTHREAD];
+ int i;
+
+ for (i = 0; i < NTHREAD; ++i)
+ if (pthread_create (&tid[i], NULL, bar, NULL))
+ return 1;
+
+ for (i = 0; i < NTHREAD; ++i)
+ if (pthread_join (tid[i], NULL))
+ return 1;
+
+ return 0;
+}
+
+int
+main (int argc, char **argv UNUSED)
+{
+ if (argc > 1)
+ verbose = 1;
+
+ if (verbose)
+ printf ("Caching: none\n");
+ unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_NONE);
+ doit ();
+
+ if (verbose)
+ printf ("Caching: global\n");
+ unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_GLOBAL);
+ doit ();
+
+ if (verbose)
+ printf ("Caching: per-thread\n");
+ unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_PER_THREAD);
+ doit ();
+
+ if (verbose)
+ printf ("SUCCESS\n");
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/Ltest-bt.c b/src/pal/src/libunwind/tests/Ltest-bt.c
new file mode 100644
index 0000000000..3489bf0b51
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Ltest-bt.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if !defined(UNW_REMOTE_ONLY)
+#include "Gtest-bt.c"
+#endif
diff --git a/src/pal/src/libunwind/tests/Ltest-concurrent.c b/src/pal/src/libunwind/tests/Ltest-concurrent.c
new file mode 100644
index 0000000000..9462607ec8
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Ltest-concurrent.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if !defined(UNW_REMOTE_ONLY)
+#include "Gtest-concurrent.c"
+#endif
diff --git a/src/pal/src/libunwind/tests/Ltest-cxx-exceptions.cxx b/src/pal/src/libunwind/tests/Ltest-cxx-exceptions.cxx
new file mode 100644
index 0000000000..24bcd13e3d
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Ltest-cxx-exceptions.cxx
@@ -0,0 +1,80 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2010 stefan.demharter@gmx.net
+ Copyright (C) 2010 arun.sharma@google.com
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <libunwind.h>
+#include "compiler.h"
+
+#define panic(args...) \
+ { fprintf (stderr, args); exit (-1); }
+
+static int verbose;
+
+struct Test
+{
+ public: // --- ctor/dtor ---
+ Test() { ++counter_; }
+ ~Test() { -- counter_; }
+ Test(const Test&) { ++counter_; }
+
+ public: // --- static members ---
+ static int counter_;
+};
+
+int Test::counter_ = 0;
+
+// Called by foo
+extern "C" void bar()
+{
+ Test t;
+ try {
+ Test t;
+ throw 5;
+ } catch (...) {
+ Test t;
+ if (verbose)
+ printf("Throwing an int\n");
+ throw 6;
+ }
+}
+
+int main(int argc, char **argv UNUSED)
+{
+ if (argc > 1)
+ verbose = 1;
+ try {
+ Test t;
+ bar();
+ } catch (int) {
+ // Dtor of all Test-object has to be called.
+ if (Test::counter_ != 0)
+ panic("Counter non-zero\n");
+ return Test::counter_;
+ } catch (...) {
+ // An int was thrown - we should not get here.
+ panic("Int was thrown why are we here?\n");
+ }
+ exit(0);
+}
diff --git a/src/pal/src/libunwind/tests/Ltest-dyn1.c b/src/pal/src/libunwind/tests/Ltest-dyn1.c
new file mode 100644
index 0000000000..c2cab6b9a0
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Ltest-dyn1.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if !defined(UNW_REMOTE_ONLY)
+#include "Gtest-dyn1.c"
+#endif
diff --git a/src/pal/src/libunwind/tests/Ltest-exc.c b/src/pal/src/libunwind/tests/Ltest-exc.c
new file mode 100644
index 0000000000..36a234ca82
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Ltest-exc.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if !defined(UNW_REMOTE_ONLY)
+#include "Gtest-exc.c"
+#endif
diff --git a/src/pal/src/libunwind/tests/Ltest-init-local-signal-lib.c b/src/pal/src/libunwind/tests/Ltest-init-local-signal-lib.c
new file mode 100644
index 0000000000..7474f71f49
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Ltest-init-local-signal-lib.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+/* To prevent inlining and optimizing away */
+int foo(volatile int* f) {
+ return *f;
+}
diff --git a/src/pal/src/libunwind/tests/Ltest-init-local-signal.c b/src/pal/src/libunwind/tests/Ltest-init-local-signal.c
new file mode 100644
index 0000000000..4bde218f3b
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Ltest-init-local-signal.c
@@ -0,0 +1,60 @@
+#include "libunwind.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <stdlib.h>
+
+#include <signal.h>
+#include <stdio.h>
+#include <assert.h>
+
+int stepper(unw_cursor_t* c) {
+ int steps = 0;
+ int ret = 1;
+ while (ret) {
+
+ ret = unw_step(c);
+ if (!ret) {
+ break;
+ }
+ steps++;
+ }
+ return steps;
+}
+
+/* Verify that we can step from both ucontext, and from getcontext()
+ * roughly the same. This tests that the IP from ucontext is used
+ * correctly (see impl of unw_init_local2) */
+void handler(int num, siginfo_t* info, void* ucontext) {
+ unw_cursor_t c;
+ unw_context_t context;
+ unw_getcontext(&context);
+ int ret = unw_init_local2(&c, ucontext, UNW_INIT_SIGNAL_FRAME);
+ assert(!ret);
+ int ucontext_steps = stepper(&c);
+
+ ret = unw_init_local(&c, &context);
+ (void)ret;
+ assert(!ret);
+ int getcontext_steps = stepper(&c);
+ if (ucontext_steps == getcontext_steps - 2) {
+ exit(0);
+ }
+ printf("unw_getcontext steps was %i, ucontext steps was %i, should be %i\n",
+ getcontext_steps, ucontext_steps, getcontext_steps - 2);
+ exit(-1);
+}
+
+int foo(volatile int* f);
+
+int main(){
+ struct sigaction a;
+ memset(&a, 0, sizeof(struct sigaction));
+ a.sa_sigaction = &handler;
+ a.sa_flags = SA_SIGINFO;
+ sigaction(SIGSEGV, &a, NULL);
+
+ foo(NULL);
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/Ltest-init.cxx b/src/pal/src/libunwind/tests/Ltest-init.cxx
new file mode 100644
index 0000000000..58a6ea4279
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Ltest-init.cxx
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if !defined(UNW_REMOTE_ONLY)
+#include "Gtest-init.cxx"
+#endif
diff --git a/src/pal/src/libunwind/tests/Ltest-mem-validate.c b/src/pal/src/libunwind/tests/Ltest-mem-validate.c
new file mode 100644
index 0000000000..1cacb9f028
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Ltest-mem-validate.c
@@ -0,0 +1,143 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Copyright (c) 2003 Hewlett-Packard Co.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "compiler.h"
+
+#include <libunwind.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/resource.h>
+#include <sys/mman.h>
+
+#define panic(args...) \
+ { fprintf (stderr, args); exit (-1); }
+
+void * stack_start;
+
+#define PAGE_SIZE 4096
+
+void do_backtrace (void)
+{
+ void* buffer[1024];
+ int size = 1024;
+ mprotect((void*)((uintptr_t)stack_start & ~(PAGE_SIZE - 1)),
+ PAGE_SIZE, PROT_NONE);
+
+ unw_cursor_t cursor;
+ unw_word_t ip, sp;
+ unw_context_t uc;
+ int ret;
+ int steps = 0;
+
+ unw_getcontext (&uc);
+ if (unw_init_local (&cursor, &uc) < 0)
+ panic ("unw_init_local failed!\n");
+
+ do
+ {
+ unw_get_reg (&cursor, UNW_REG_IP, &ip);
+ unw_get_reg (&cursor, UNW_REG_SP, &sp);
+
+ ret = unw_step (&cursor);
+ if (ret < 0)
+ {
+ unw_get_reg (&cursor, UNW_REG_IP, &ip);
+ }
+ steps ++;
+ }
+ while (ret > 0);
+
+ if (steps < 5)
+ {
+ exit(-1);
+ }
+
+ mprotect((void*)((uintptr_t)stack_start & ~(PAGE_SIZE - 1)),
+ PAGE_SIZE, PROT_READ|PROT_WRITE);
+}
+
+void consume_and_run (int depth)
+{
+ unw_cursor_t cursor;
+ unw_context_t uc;
+ char string[1024];
+
+ sprintf (string, "hello %p %p\n", &cursor, &uc);
+ if (depth == 0) {
+ do_backtrace();
+ } else {
+ consume_and_run(depth - 1);
+ }
+}
+
+int
+main (int argc, char **argv UNUSED)
+{
+ int start;
+ unw_context_t uc;
+ unw_cursor_t cursor;
+
+ stack_start = &start;
+
+ // Initialize pipe mem validate check, opens file descriptors
+ unw_getcontext(&uc);
+ if (unw_init_local (&cursor, &uc) < 0)
+ panic ("unw_init_local failed!\n");
+
+ int i;
+ for (i = 3; i < 10; i++)
+ {
+
+ pid_t childpid = fork();
+ if (!childpid)
+ {
+ /* Close fds and make sure we still work */
+ int ret = close(i);
+ }
+
+ int status;
+ if (childpid)
+ {
+ wait(&status);
+ if (WIFEXITED(status))
+ return WEXITSTATUS(status);
+ else
+ return -1;
+ }
+ else
+ {
+ consume_and_run (10);
+
+ return 0;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/Ltest-nocalloc.c b/src/pal/src/libunwind/tests/Ltest-nocalloc.c
new file mode 100644
index 0000000000..f5c31b2a3e
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Ltest-nocalloc.c
@@ -0,0 +1,137 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2011 Google, Inc
+ Contributed by Paul Pluzhnikov <ppluzhnikov@google.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <pthread.h>
+
+#define panic(args...) \
+ { fprintf (stderr, args); exit (-1); }
+
+int num_mallocs;
+int num_callocs;
+int in_unwind;
+
+void *
+calloc(size_t n, size_t s)
+{
+ static void * (*func)(size_t, size_t);
+
+#ifdef __GLIBC__
+ /* In glibc, dlsym() calls calloc. Calling dlsym(RTLD_NEXT, "calloc") here
+ causes infinite recursion. Instead, we simply use it by its other
+ name. */
+ extern void *__libc_calloc(size_t, size_t);
+ if (!func)
+ func = &__libc_calloc;
+#else
+ if(!func)
+ func = dlsym(RTLD_NEXT, "calloc");
+#endif
+
+ if (in_unwind) {
+ num_callocs++;
+ return NULL;
+ } else {
+ return func(n, s);
+ }
+}
+
+void *
+malloc(size_t s)
+{
+ static void * (*func)(size_t);
+
+ if(!func)
+ func = dlsym(RTLD_NEXT, "malloc");
+
+ if (in_unwind) {
+ num_mallocs++;
+ return NULL;
+ } else {
+ return func(s);
+ }
+}
+
+static void
+do_backtrace (void)
+{
+ const int num_levels = 100;
+ void *pc[num_levels];
+
+ in_unwind = 1;
+ unw_backtrace(pc, num_levels);
+ in_unwind = 0;
+}
+
+void
+foo3 (void)
+{
+ do_backtrace ();
+}
+
+void
+foo2 (void)
+{
+ foo3 ();
+}
+
+void
+foo1 (void)
+{
+ foo2 ();
+}
+
+int
+main (void)
+{
+ int i, num_errors;
+
+ /* Create (and leak) 100 TSDs, then call backtrace()
+ and check that it doesn't call malloc()/calloc(). */
+ for (i = 0; i < 100; ++i) {
+ pthread_key_t key;
+ if (pthread_key_create (&key, NULL))
+ panic ("FAILURE: unable to create key %d\n", i);
+ }
+ /* Call backtrace right after thread creation,
+ * where we are sure that we're not inside malloc */
+ do_backtrace();
+ num_mallocs = num_callocs = 0;
+ foo1 ();
+ num_errors = num_mallocs + num_callocs;
+ if (num_errors > 0)
+ {
+ fprintf (stderr,
+ "FAILURE: detected %d error%s (malloc: %d, calloc: %d)\n",
+ num_errors, num_errors > 1 ? "s" : "",
+ num_mallocs, num_callocs);
+ exit (-1);
+ }
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/Ltest-nomalloc.c b/src/pal/src/libunwind/tests/Ltest-nomalloc.c
new file mode 100644
index 0000000000..74d6331286
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Ltest-nomalloc.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if !defined(UNW_REMOTE_ONLY)
+#include "Gtest-nomalloc.c"
+#endif
diff --git a/src/pal/src/libunwind/tests/Ltest-resume-sig-rt.c b/src/pal/src/libunwind/tests/Ltest-resume-sig-rt.c
new file mode 100644
index 0000000000..01fd6dc7d7
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Ltest-resume-sig-rt.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if !defined(UNW_REMOTE_ONLY)
+#include "Gtest-resume-sig-rt.c"
+#endif
diff --git a/src/pal/src/libunwind/tests/Ltest-resume-sig.c b/src/pal/src/libunwind/tests/Ltest-resume-sig.c
new file mode 100644
index 0000000000..0047b524aa
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Ltest-resume-sig.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if !defined(UNW_REMOTE_ONLY)
+#include "Gtest-resume-sig.c"
+#endif
diff --git a/src/pal/src/libunwind/tests/Ltest-trace.c b/src/pal/src/libunwind/tests/Ltest-trace.c
new file mode 100644
index 0000000000..fb0e9c10bd
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Ltest-trace.c
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if !defined(UNW_REMOTE_ONLY)
+#include "Gtest-trace.c"
+#endif
diff --git a/src/pal/src/libunwind/tests/Ltest-varargs.c b/src/pal/src/libunwind/tests/Ltest-varargs.c
new file mode 100644
index 0000000000..17ac600be6
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Ltest-varargs.c
@@ -0,0 +1,84 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#include "compiler.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int ok;
+int verbose;
+
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 3)
+void a (int, ...) __attribute__((optimize(0)));
+void b (void) __attribute__((optimize(0)));
+void c (void) __attribute__((optimize(0)));
+#endif
+
+void NOINLINE
+b (void)
+{
+ void *v[20];
+ int i, n;
+
+ n = unw_backtrace(v, 20);
+
+ /* Check that the number of addresses given by unw_backtrace() looks
+ * reasonable. If the compiler inlined everything, then this check will also
+ * break. */
+ if (n >= 7)
+ ok = 1;
+
+ if (verbose)
+ for (i = 0; i < n; ++i)
+ printf ("[%d] %p\n", i, v[i]);
+}
+
+void NOINLINE
+c (void)
+{
+ b ();
+}
+
+void NOINLINE
+a (int d, ...)
+{
+ switch (d)
+ {
+ case 5:
+ a (4, 2,4);
+ break;
+ case 4:
+ a (3, 1,3,5);
+ break;
+ case 3:
+ a (2, 11, 13, 17, 23);
+ break;
+ case 2:
+ a (1);
+ break;
+ case 1:
+ c ();
+ }
+}
+
+int
+main (int argc, char **argv UNUSED)
+{
+ if (argc > 1)
+ verbose = 1;
+
+ a (5, 3, 4, 5, 6);
+
+ if (!ok)
+ {
+ fprintf (stderr, "FAILURE: expected deeper backtrace.\n");
+ return 1;
+ }
+
+ if (verbose)
+ printf ("SUCCESS.\n");
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/Makefile.am b/src/pal/src/libunwind/tests/Makefile.am
new file mode 100644
index 0000000000..4b0b9db7d1
--- /dev/null
+++ b/src/pal/src/libunwind/tests/Makefile.am
@@ -0,0 +1,234 @@
+AM_CPPFLAGS = -I$(top_srcdir)/include
+
+EXTRA_DIST = run-ia64-test-dyn1 run-ptrace-mapper run-ptrace-misc \
+ run-check-namespace run-coredump-unwind \
+ run-coredump-unwind-mdi check-namespace.sh.in \
+ Gtest-nomalloc.c
+
+MAINTAINERCLEANFILES = Makefile.in
+
+noinst_PROGRAMS_arch =
+noinst_PROGRAMS_cdep =
+noinst_PROGRAMS_common =
+check_PROGRAMS_arch =
+check_PROGRAMS_cdep =
+check_PROGRAMS_common = test-proc-info test-static-link \
+ test-strerror
+check_SCRIPTS_arch =
+check_SCRIPTS_cdep =
+check_SCRIPTS_common = run-check-namespace
+
+if REMOTE_ONLY
+
+perf:
+
+else
+ LIBUNWIND_local = $(top_builddir)/src/libunwind.la
+if ARCH_IA64
+ noinst_PROGRAMS_arch += ia64-test-dyn1
+ check_SCRIPTS_arch += run-ia64-test-dyn1
+ check_PROGRAMS_arch += Gia64-test-stack Lia64-test-stack \
+ Gia64-test-nat Lia64-test-nat \
+ Gia64-test-rbs Lia64-test-rbs \
+ Gia64-test-readonly Lia64-test-readonly \
+ ia64-test-setjmp ia64-test-sig
+else #!ARCH_IA64
+if ARCH_PPC64
+if USE_ALTIVEC
+ noinst_PROGRAMS_arch += ppc64-test-altivec
+endif #USE_ALTIVEC
+endif #ARCH_PPC64
+endif #!ARCH_IA64
+ check_PROGRAMS_cdep += Gtest-bt Ltest-bt Gtest-exc Ltest-exc \
+ Gtest-init Ltest-init \
+ Gtest-concurrent Ltest-concurrent \
+ Gtest-resume-sig Ltest-resume-sig \
+ Gtest-resume-sig-rt Ltest-resume-sig-rt \
+ Gtest-trace Ltest-trace \
+ Ltest-init-local-signal \
+ Ltest-mem-validate \
+ test-async-sig test-flush-cache test-init-remote \
+ test-mem test-reg-state Ltest-varargs \
+ Ltest-nomalloc Ltest-nocalloc Lrs-race
+ noinst_PROGRAMS_cdep += forker Gperf-simple Lperf-simple \
+ Gperf-trace Lperf-trace
+
+if BUILD_PTRACE
+ check_SCRIPTS_cdep += run-ptrace-mapper run-ptrace-misc
+ check_PROGRAMS_cdep += test-ptrace
+ noinst_PROGRAMS_cdep += mapper test-ptrace-misc
+endif
+
+if BUILD_SETJMP
+ check_PROGRAMS_cdep += test-setjmp
+endif
+
+if SUPPORT_CXX_EXCEPTIONS
+ check_PROGRAMS_cdep += Ltest-cxx-exceptions
+endif
+
+if OS_LINUX
+if BUILD_COREDUMP
+ check_SCRIPTS_cdep += run-coredump-unwind
+ noinst_PROGRAMS_cdep += crasher test-coredump-unwind
+
+if HAVE_LZMA
+ check_SCRIPTS_cdep += run-coredump-unwind-mdi
+endif # HAVE_LZMA
+endif # BUILD_COREDUMP
+endif # OS_LINUX
+
+perf: perf-startup Gperf-simple Lperf-simple Lperf-trace
+ @echo "########## Basic performance of generic libunwind:"
+ @./Gperf-simple
+ @echo "########## Basic performance of local-only libunwind:"
+ @./Lperf-simple
+ @echo "########## Performance of fast unwind:"
+ @./Lperf-trace
+ @echo "########## Startup overhead:"
+ @$(srcdir)/perf-startup @arch@
+
+endif
+
+check_PROGRAMS = $(check_PROGRAMS_common) $(check_PROGRAMS_cdep) \
+ $(check_PROGRAMS_arch)
+check_SCRIPTS = $(check_SCRIPTS_common) $(check_SCRIPTS_cdep) \
+ $(check_SCRIPTS_arch)
+
+
+TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
+XFAIL_TESTS =
+
+if ARCH_IA64
+ check_PROGRAMS_cdep += Gtest-dyn1 Ltest-dyn1
+endif
+
+# Use if arch defines but does not support PTRACE_SINGLESTEP
+# ptrace request used in the tests.
+XFAIL_TESTS_PTRACE_SINGLESTEP = run-ptrace-mapper run-ptrace-misc
+
+if ARCH_MIPS
+XFAIL_TESTS += $(XFAIL_TESTS_PTRACE_SINGLESTEP)
+endif
+
+if ARCH_ARM
+# ARM Linux kernel >=2.6.39 removed PTRACE_SINGLESTEP emulation
+XFAIL_TESTS += $(XFAIL_TESTS_PTRACE_SINGLESTEP)
+endif
+
+# This is meant for multilib binaries, -m32.
+# ptrace gives EBADREG when testing,
+# but generally everything else works.
+if NO_PTRACE_TEST
+ XFAIL_TESTS += run-ptrace-mapper test-ptrace Ltest-init-local-signal
+endif
+
+noinst_PROGRAMS = $(noinst_PROGRAMS_common) $(noinst_PROGRAMS_cdep) \
+ $(noinst_PROGRAMS_arch)
+
+Lia64_test_readonly_SOURCES = Lia64-test-readonly.c ia64-test-readonly-asm.S
+Gia64_test_readonly_SOURCES = Gia64-test-readonly.c ia64-test-readonly-asm.S
+Lia64_test_stack_SOURCES = Lia64-test-stack.c ia64-test-stack-asm.S \
+ ia64-test-stack.h
+Gia64_test_stack_SOURCES = Gia64-test-stack.c ia64-test-stack-asm.S \
+ ia64-test-stack.h
+Lia64_test_rbs_SOURCES = Lia64-test-rbs.c ia64-test-rbs-asm.S ia64-test-rbs.h
+Gia64_test_rbs_SOURCES = Gia64-test-rbs.c ia64-test-rbs-asm.S ia64-test-rbs.h
+Lia64_test_nat_SOURCES = Lia64-test-nat.c ia64-test-nat-asm.S
+Gia64_test_nat_SOURCES = Gia64-test-nat.c ia64-test-nat-asm.S
+ia64_test_dyn1_SOURCES = ia64-test-dyn1.c ia64-dyn-asm.S flush-cache.S \
+ flush-cache.h
+ppc64_test_altivec_SOURCES = ppc64-test-altivec.c ppc64-test-altivec-utils.c
+Gtest_init_SOURCES = Gtest-init.cxx
+Ltest_init_SOURCES = Ltest-init.cxx
+Ltest_cxx_exceptions_SOURCES = Ltest-cxx-exceptions.cxx
+
+Ltest_init_local_signal_SOURCES = Ltest-init-local-signal.c Ltest-init-local-signal-lib.c
+
+Gtest_dyn1_SOURCES = Gtest-dyn1.c flush-cache.S flush-cache.h
+Ltest_dyn1_SOURCES = Ltest-dyn1.c flush-cache.S flush-cache.h
+test_static_link_SOURCES = test-static-link-loc.c test-static-link-gen.c
+test_static_link_LDFLAGS = -static
+forker_LDFLAGS = -static
+Gtest_bt_SOURCES = Gtest-bt.c ident.c
+Ltest_bt_SOURCES = Ltest-bt.c ident.c
+test_ptrace_misc_SOURCES = test-ptrace-misc.c ident.c
+Ltest_nomalloc_SOURCES = Ltest-nomalloc.c
+Ltest_nocalloc_SOURCES = Ltest-nocalloc.c
+Gtest_trace_SOURCES = Gtest-trace.c ident.c
+Ltest_trace_SOURCES = Ltest-trace.c ident.c
+Ltest_mem_validate_SOURCES = Ltest-mem-validate.c
+
+LIBUNWIND = $(top_builddir)/src/libunwind-$(arch).la
+LIBUNWIND_ptrace = $(top_builddir)/src/libunwind-ptrace.la
+LIBUNWIND_coredump = $(top_builddir)/src/libunwind-coredump.la
+
+if USE_ELF32
+LIBUNWIND_ELF = $(top_builddir)/src/libunwind-elf32.la
+endif
+if USE_ELF64
+LIBUNWIND_ELF = $(top_builddir)/src/libunwind-elf64.la
+endif
+if USE_ELFXX
+LIBUNWIND_ELF = $(top_builddir)/src/libunwind-elfxx.la
+endif
+
+LIBUNWIND_setjmp = $(top_builddir)/src/libunwind-setjmp.la \
+ $(LIBUNWIND_ELF) $(LIBUNWIND)
+
+test_async_sig_LDADD = $(LIBUNWIND_local) -lpthread
+test_flush_cache_LDADD = $(LIBUNWIND_local)
+test_init_remote_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
+test_mem_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
+test_reg_state_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
+test_ptrace_LDADD = $(LIBUNWIND_ptrace) $(LIBUNWIND)
+test_proc_info_LDADD = $(LIBUNWIND)
+test_static_link_LDADD = $(LIBUNWIND)
+test_strerror_LDADD = $(LIBUNWIND)
+Lrs_race_LDADD = $(LIBUNWIND_local) -lpthread
+Ltest_varargs_LDADD = $(LIBUNWIND_local)
+Ltest_init_local_signal_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
+
+Gtest_bt_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
+Gtest_concurrent_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) -lpthread
+Gtest_dyn1_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
+Gtest_exc_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
+Gtest_init_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) @BACKTRACELIB@
+Gtest_resume_sig_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
+Gtest_resume_sig_rt_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
+Gperf_simple_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
+Gtest_trace_LDADD=$(LIBUNWIND) $(LIBUNWIND_local)
+Gperf_trace_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
+
+Ltest_bt_LDADD = $(LIBUNWIND_local)
+Ltest_concurrent_LDADD = $(LIBUNWIND_local) -lpthread
+Ltest_dyn1_LDADD = $(LIBUNWIND_local)
+Ltest_exc_LDADD = $(LIBUNWIND_local)
+Ltest_init_LDADD = $(LIBUNWIND_local)
+Ltest_nomalloc_LDADD = $(LIBUNWIND_local) @DLLIB@
+Ltest_nocalloc_LDADD = $(LIBUNWIND_local) @DLLIB@ -lpthread
+Ltest_resume_sig_LDADD = $(LIBUNWIND_local)
+Ltest_resume_sig_rt_LDADD = $(LIBUNWIND_local)
+Lperf_simple_LDADD = $(LIBUNWIND_local)
+Ltest_trace_LDADD = $(LIBUNWIND_local)
+Lperf_trace_LDADD = $(LIBUNWIND_local)
+Ltest_mem_validate_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
+
+test_setjmp_LDADD = $(LIBUNWIND_setjmp)
+ia64_test_setjmp_LDADD = $(LIBUNWIND_setjmp)
+
+if BUILD_COREDUMP
+test_coredump_unwind_LDADD = $(LIBUNWIND_coredump) $(LIBUNWIND) @BACKTRACELIB@
+endif
+
+Gia64_test_nat_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
+Gia64_test_stack_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
+Gia64_test_rbs_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
+Gia64_test_readonly_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
+Lia64_test_nat_LDADD = $(LIBUNWIND_local)
+Lia64_test_stack_LDADD = $(LIBUNWIND_local)
+Lia64_test_rbs_LDADD = $(LIBUNWIND_local)
+Lia64_test_readonly_LDADD = $(LIBUNWIND_local)
+ia64_test_dyn1_LDADD = $(LIBUNWIND)
+ia64_test_sig_LDADD = $(LIBUNWIND)
+ppc64_test_altivec_LDADD = $(LIBUNWIND)
diff --git a/src/pal/src/libunwind/tests/check-namespace.sh.in b/src/pal/src/libunwind/tests/check-namespace.sh.in
new file mode 100644
index 0000000000..6d0081732d
--- /dev/null
+++ b/src/pal/src/libunwind/tests/check-namespace.sh.in
@@ -0,0 +1,367 @@
+#!/bin/sh
+verbose=false
+if [ "$1" = "-v" ]; then
+ verbose=true
+ shift
+fi
+
+build_plat=@build_arch@
+plat=@arch@
+os=@target_os@
+num_errors=0
+
+LIBUNWIND=../src/.libs/libunwind.so
+LIBUNWIND_GENERIC=../src/.libs/libunwind-${plat}.so
+
+fetch_symtab () {
+ filename=$1
+
+ if [ ! -r $filename ]; then
+ return
+ fi
+
+ if $verbose; then
+ echo "Checking $filename..."
+ fi
+
+ #
+ # Unfortunately, "nm --defined" is a GNU-extension. For portability,
+ # build the list of defined symbols by hand.
+ #
+ symtab=`nm -g $filename`
+ saved_IFS="$IFS"
+ IFS=""
+ undef=`nm -g -u $filename`
+ for line in $undef; do
+ symtab=`echo "$symtab" | grep -v "^${line}"\$`
+ done;
+ IFS="$saved_IFS"
+}
+
+ignore () {
+ sym=$1
+ symtab=`echo "$symtab" | grep -v " ${sym}\$"`
+}
+
+match () {
+ sym=$1
+ if `echo "$symtab" | grep -q " ${sym}\$"`; then
+ symtab=`echo "$symtab" | grep -v " ${sym}\$"`
+ else
+ echo " ERROR: Symbol \"$sym\" missing."
+ num_errors=`expr $num_errors + 1`
+ fi
+}
+
+#
+# Filter out miscellaneous symbols that get defined by the
+# linker for each shared object.
+#
+filter_misc () {
+ ignore _DYNAMIC
+ ignore _GLOBAL_OFFSET_TABLE_
+ ignore __bss_start
+ ignore _edata
+ ignore _end
+ ignore _Uelf32_get_proc_name
+ ignore _Uelf32_valid_object
+ ignore _Uelf64_get_proc_name
+ ignore _Uelf64_valid_object
+ ignore _U.*debug_level
+ ignore ICRT.INTERNAL # ICC 8.x defines this
+
+ # Ignore symbols generated by the ARM Linux default linker script.
+ # For details see the binutils sources (src/ld/emulparams/armelf_linux.sh).
+ if [ ${plat} = "arm" ]; then
+ ignore __bss_start__
+ ignore __bss_end__
+ ignore __end__
+ ignore _bss_end__
+ fi
+
+ if [ ${plat} = "mips" ]; then
+ ignore _fbss
+ ignore _fdata
+ ignore _ftext
+ ignore _gp
+ fi
+}
+
+check_local_unw_abi () {
+ match _UL${plat}_apply_reg_state
+ match _UL${plat}_reg_states_iterate
+ match _UL${plat}_create_addr_space
+ match _UL${plat}_destroy_addr_space
+ match _UL${plat}_get_fpreg
+ match _UL${plat}_get_proc_info
+ match _UL${plat}_get_proc_info_by_ip
+ match _UL${plat}_get_proc_name
+ match _UL${plat}_get_reg
+ match _UL${plat}_get_save_loc
+ match _UL${plat}_init_local
+ match _UL${plat}_init_local2
+ match _UL${plat}_init_remote
+ match _UL${plat}_is_signal_frame
+ match _UL${plat}_local_addr_space
+ match _UL${plat}_resume
+ match _UL${plat}_set_caching_policy
+ match _UL${plat}_set_cache_size
+ match _UL${plat}_set_reg
+ match _UL${plat}_set_fpreg
+ match _UL${plat}_step
+
+ match _U${plat}_flush_cache
+ match _U${plat}_get_accessors
+ match _U${plat}_getcontext
+ match _U${plat}_regname
+ match _U${plat}_strerror
+
+ match _U_dyn_cancel
+ match _U_dyn_info_list_addr
+ match _U_dyn_register
+
+ match unw_backtrace
+ match backtrace
+
+ case ${plat} in
+ arm)
+ match _U${plat}_get_elf_image
+ match _U${plat}_get_exe_image_path
+ match _U${plat}_is_fpreg
+ match _UL${plat}_search_unwind_table
+ match _UL${plat}_dwarf_search_unwind_table
+ match _UL${plat}_dwarf_find_unwind_table
+ ;;
+ hppa)
+ match _UL${plat}_dwarf_search_unwind_table
+ match _UL${plat}_dwarf_find_unwind_table
+ match _U${plat}_get_elf_image
+ match _U${plat}_get_exe_image_path
+ match _U${plat}_setcontext
+ ;;
+ ia64)
+ match _UL${plat}_search_unwind_table
+ match _U${plat}_get_elf_image
+ match _U${plat}_get_exe_image_path
+ ;;
+ x86)
+ match _U${plat}_get_elf_image
+ match _U${plat}_get_exe_image_path
+ match _U${plat}_is_fpreg
+ match _UL${plat}_dwarf_search_unwind_table
+ match _UL${plat}_dwarf_find_unwind_table
+ ;;
+ x86_64)
+ match _U${plat}_get_elf_image
+ match _U${plat}_get_exe_image_path
+ match _U${plat}_is_fpreg
+ match _UL${plat}_dwarf_search_unwind_table
+ match _UL${plat}_dwarf_find_unwind_table
+ match _U${plat}_setcontext
+ ;;
+ ppc*)
+ match _U${plat}_get_func_addr
+ match _U${plat}_get_elf_image
+ match _U${plat}_get_exe_image_path
+ match _U${plat}_is_fpreg
+ match _UL${plat}_dwarf_search_unwind_table
+ match _UL${plat}_dwarf_find_unwind_table
+ ;;
+ tilegx)
+ match _U${plat}_is_fpreg
+ match _UL${plat}_dwarf_search_unwind_table
+ match _UL${plat}_dwarf_find_unwind_table
+ match _UL${plat}_local_addr_space_init
+ match _U${plat}_get_elf_image
+ match _U${plat}_get_exe_image_path
+ match ${plat}_lock
+ ;;
+
+ *)
+ match _U${plat}_is_fpreg
+ match _UL${plat}_dwarf_search_unwind_table
+ match _UL${plat}_dwarf_find_unwind_table
+ ;;
+ esac
+
+ if [ x@enable_debug_frame@ = xyes ]; then
+ match _UL${plat}_dwarf_find_debug_frame
+ fi
+
+}
+
+check_generic_unw_abi () {
+ match _U${plat}_apply_reg_state
+ match _U${plat}_reg_states_iterate
+ match _U${plat}_create_addr_space
+ match _U${plat}_destroy_addr_space
+ match _U${plat}_flush_cache
+ match _U${plat}_get_accessors
+ match _U${plat}_get_fpreg
+ match _U${plat}_get_proc_info
+ match _U${plat}_get_proc_info_by_ip
+ match _U${plat}_get_proc_name
+ match _U${plat}_get_reg
+ match _U${plat}_get_save_loc
+ match _U${plat}_init_local
+ match _U${plat}_init_local2
+ match _U${plat}_init_remote
+ match _U${plat}_is_signal_frame
+ match _U${plat}_local_addr_space
+ match _U${plat}_regname
+ match _U${plat}_resume
+ match _U${plat}_set_caching_policy
+ match _U${plat}_set_cache_size
+ match _U${plat}_set_fpreg
+ match _U${plat}_set_reg
+ match _U${plat}_step
+ match _U${plat}_strerror
+
+ case ${plat} in
+ arm)
+ match _U${plat}_is_fpreg
+ match _U${plat}_get_elf_image
+ match _U${plat}_get_exe_image_path
+ match _U${plat}_search_unwind_table
+ match _U${plat}_dwarf_search_unwind_table
+ match _U${plat}_dwarf_find_unwind_table
+ ;;
+ hppa)
+ match _U${plat}_dwarf_search_unwind_table
+ match _U${plat}_dwarf_find_unwind_table
+ match _U${plat}_get_elf_image
+ match _U${plat}_get_exe_image_path
+ ;;
+ ia64)
+ match _U${plat}_search_unwind_table
+ match _U${plat}_find_dyn_list
+ if [ $plat = $build_plat ]; then
+ match _U${plat}_get_elf_image
+ match _U${plat}_get_exe_image_path
+ case $os in
+ linux*)
+ match _U${plat}_get_kernel_table
+ ;;
+ esac
+ fi
+ ;;
+ x86)
+ match _U${plat}_get_elf_image
+ match _U${plat}_get_exe_image_path
+ match _U${plat}_is_fpreg
+ match _U${plat}_dwarf_search_unwind_table
+ match _U${plat}_dwarf_find_unwind_table
+ ;;
+ x86_64)
+ match _U${plat}_get_elf_image
+ match _U${plat}_get_exe_image_path
+ match _U${plat}_is_fpreg
+ match _U${plat}_dwarf_search_unwind_table
+ match _U${plat}_dwarf_find_unwind_table
+ ;;
+ ppc*)
+ match _U${plat}_get_elf_image
+ match _U${plat}_get_exe_image_path
+ match _U${plat}_get_func_addr
+ match _U${plat}_is_fpreg
+ match _U${plat}_dwarf_search_unwind_table
+ match _U${plat}_dwarf_find_unwind_table
+ ;;
+ tilegx)
+ match _U${plat}_dwarf_search_unwind_table
+ match _U${plat}_dwarf_find_unwind_table
+ match _U${plat}_get_elf_image
+ match _U${plat}_get_exe_image_path
+ match _U${plat}_is_fpreg
+ match _U${plat}_local_addr_space_init
+ match ${plat}_lock
+ ;;
+ *)
+ match _U${plat}_is_fpreg
+ match _U${plat}_dwarf_search_unwind_table
+ match _U${plat}_dwarf_find_unwind_table
+ ;;
+ esac
+
+ if [ x@enable_debug_frame@ = xyes ]; then
+ match _U${plat}_dwarf_find_debug_frame
+ fi
+}
+
+check_cxx_abi () {
+ match _Unwind_Backtrace
+ match _Unwind_DeleteException
+ match _Unwind_FindEnclosingFunction
+ match _Unwind_ForcedUnwind
+ match _Unwind_GetBSP
+ match _Unwind_GetCFA
+ match _Unwind_GetDataRelBase
+ match _Unwind_GetGR
+ match _Unwind_GetIP
+ match _Unwind_GetIPInfo
+ match _Unwind_GetLanguageSpecificData
+ match _Unwind_GetRegionStart
+ match _Unwind_GetTextRelBase
+ match _Unwind_RaiseException
+ match _Unwind_Resume
+ match _Unwind_Resume_or_Rethrow
+ match _Unwind_SetGR
+ match _Unwind_SetIP
+ match __libunwind_Unwind_Backtrace
+ match __libunwind_Unwind_DeleteException
+ match __libunwind_Unwind_FindEnclosingFunction
+ match __libunwind_Unwind_ForcedUnwind
+ match __libunwind_Unwind_GetBSP
+ match __libunwind_Unwind_GetCFA
+ match __libunwind_Unwind_GetDataRelBase
+ match __libunwind_Unwind_GetGR
+ match __libunwind_Unwind_GetIP
+ match __libunwind_Unwind_GetIPInfo
+ match __libunwind_Unwind_GetLanguageSpecificData
+ match __libunwind_Unwind_GetRegionStart
+ match __libunwind_Unwind_GetTextRelBase
+ match __libunwind_Unwind_RaiseException
+ match __libunwind_Unwind_Resume
+ match __libunwind_Unwind_Resume_or_Rethrow
+ match __libunwind_Unwind_SetGR
+ match __libunwind_Unwind_SetIP
+ case $os in
+ linux*)
+ # needed only for Intel 8.0 bug-compatibility
+ match _ReadSLEB
+ match _ReadULEB
+ ;;
+ esac
+}
+
+check_empty () {
+ if [ -n "$symtab" ]; then
+ printf " ERROR: Extraneous symbols:\n$symtab\n"
+ num_errors=`expr $num_errors + 1`
+ fi
+}
+
+if [ $plat = $build_plat ]; then
+ fetch_symtab $LIBUNWIND
+ filter_misc
+ check_local_unw_abi
+ if [ x@enable_cxx_exceptions@ = xyes ]; then
+ check_cxx_abi
+ fi
+ check_empty
+fi
+
+fetch_symtab $LIBUNWIND_GENERIC
+filter_misc
+check_generic_unw_abi
+check_empty
+
+if [ $num_errors -gt 0 ]; then
+ echo "FAILURE: Detected $num_errors errors"
+ exit 1
+fi
+
+if $verbose; then
+ echo " SUCCESS: all checks passed"
+fi
+exit 0
diff --git a/src/pal/src/libunwind/tests/crasher.c b/src/pal/src/libunwind/tests/crasher.c
new file mode 100644
index 0000000000..24c78054c9
--- /dev/null
+++ b/src/pal/src/libunwind/tests/crasher.c
@@ -0,0 +1,124 @@
+/* This program should crash and produce coredump */
+
+#include "compiler.h"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#ifdef __FreeBSD__
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#endif
+
+#if defined(__linux__)
+void write_maps(char *fname)
+{
+ char buf[512], path[128];
+ char exec;
+ uintmax_t addr;
+ FILE *maps = fopen("/proc/self/maps", "r");
+ FILE *out = fopen(fname, "w");
+
+ if (!maps || !out)
+ exit(EXIT_FAILURE);
+
+ while (fgets(buf, sizeof(buf), maps))
+ {
+ if (sscanf(buf, "%jx-%*x %*c%*c%c%*c %*x %*s %*d /%126[^\n]", &addr, &exec, path+1) != 3)
+ continue;
+
+ if (exec != 'x')
+ continue;
+
+ path[0] = '/';
+ fprintf(out, "0x%jx:%s ", addr, path);
+ }
+ fprintf(out, "\n");
+
+ fclose(out);
+ fclose(maps);
+}
+#elif defined(__FreeBSD__)
+void
+write_maps(char *fname)
+{
+ FILE *out;
+ char *buf, *bp, *eb;
+ struct kinfo_vmentry *kv;
+ int mib[4], error;
+ size_t len;
+
+ out = fopen(fname, "w");
+ if (out == NULL)
+ exit(EXIT_FAILURE);
+
+ len = 0;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_VMMAP;
+ mib[3] = getpid();
+ error = sysctl(mib, 4, NULL, &len, NULL, 0);
+ if (error == -1)
+ exit(EXIT_FAILURE);
+ len = len * 4 / 3;
+ buf = malloc(len);
+ if (buf == NULL)
+ exit(EXIT_FAILURE);
+ error = sysctl(mib, 4, buf, &len, NULL, 0);
+ if (error == -1)
+ exit(EXIT_FAILURE);
+
+ for (bp = buf, eb = buf + len; bp < eb; bp += kv->kve_structsize) {
+ kv = (struct kinfo_vmentry *)(uintptr_t)bp;
+ if (kv->kve_type == KVME_TYPE_VNODE &&
+ (kv->kve_protection & KVME_PROT_EXEC) != 0) {
+ fprintf(out, "0x%jx:%s ", kv->kve_start, kv->kve_path);
+ }
+ }
+
+ fprintf(out, "\n");
+ fclose(out);
+ free(buf);
+}
+#else
+#error Port me
+#endif
+
+#ifdef __GNUC__
+int c(int x) NOINLINE ALIAS(b);
+#define compiler_barrier() asm volatile("");
+#else
+int c(int x);
+#define compiler_barrier()
+#endif
+
+int NOINLINE a(void)
+{
+ *(volatile int *)32 = 1;
+ return 1;
+}
+
+int NOINLINE b(int x)
+{
+ int r;
+
+ compiler_barrier();
+
+ if (x)
+ r = a();
+ else
+ r = c(1);
+ return r + 1;
+}
+
+int
+main (int argc, char **argv)
+{
+ if (argc > 1)
+ write_maps(argv[1]);
+ b(0);
+ return 0;
+}
+
diff --git a/src/pal/src/libunwind/tests/flush-cache.S b/src/pal/src/libunwind/tests/flush-cache.S
new file mode 100644
index 0000000000..3ee47269e1
--- /dev/null
+++ b/src/pal/src/libunwind/tests/flush-cache.S
@@ -0,0 +1,104 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifndef HAVE__BUILTIN___CLEAR_CACHE
+
+#if defined(__ia64__)
+
+ .global flush_cache
+
+ .proc flush_cache
+flush_cache:
+ .prologue
+ alloc r2=ar.pfs,2,0,0,0
+ add r8=31,in1 // round up to 32 byte-boundary
+ ;;
+ shr.u r8=r8,5 // we flush 32 bytes per iteration
+ ;;
+ add r8=-1,r8
+ .save ar.lc, r3
+ mov r3=ar.lc // save ar.lc
+ ;;
+ .body
+
+ mov ar.lc=r8
+ ;;
+.loop: fc in0 // issuable on M0 only
+ add in0=32,in0
+ br.cloop.sptk.few .loop
+ ;;
+ sync.i
+ ;;
+ srlz.i
+ ;;
+ mov ar.lc=r3 // restore ar.lc
+ br.ret.sptk.many rp
+ .endp flush_cache
+
+#elif defined(__i386__) || defined (__x86_64__)
+
+ .globl flush_cache
+flush_cache:
+ ret
+
+#elif defined(__hppa__)
+
+# warning FIX ME!!
+
+ .globl flush_cache
+flush_cache:
+ .proc
+ .callinfo
+ bv %r0(%rp)
+ .procend
+#elif defined(__powerpc64__)
+# warning IMPLEMENT ME FOR PPC64!!
+ .globl flush_cache
+flush_cache:
+ lwz 11, 0(1) ;
+ lwz 0, 4(11) ;
+ mtlr 0 ;
+ lwz 31, -4(11) ;
+ mr 1, 11 ;
+ blr
+#elif defined(__powerpc__)
+# warning IMPLEMENT ME FOR PPC32!!
+ .globl flush_cache
+flush_cache:
+ lwz 11, 0(1) ;
+ lwz 0, 4(11) ;
+ mtlr 0 ;
+ lwz 31, -4(11) ;
+ mr 1, 11 ;
+ blr
+#elif defined(__arm__)
+ .text
+ .globl flush_cache
+flush_cache:
+ bx lr
+#elif defined(__tilegx__)
+ .text
+ .globl flush_cache
+flush_cache:
+
+ andi r0, r0, -64
+1: {
+ flush r0 ;
+ addi r0, r0, 64
+ }
+ {
+ bgtz r1, 1b ;
+ addi r1, r1, -64
+ }
+ jrp lr
+#else
+# error Need flush_cache code for this architecture.
+#endif
+
+#if defined ( __linux__) && !defined (__arm__)
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
+
+#endif
diff --git a/src/pal/src/libunwind/tests/flush-cache.h b/src/pal/src/libunwind/tests/flush-cache.h
new file mode 100644
index 0000000000..8227d85b3f
--- /dev/null
+++ b/src/pal/src/libunwind/tests/flush-cache.h
@@ -0,0 +1,38 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef FLUSH_CACHE_H
+#define FLUSH_CACHE_H
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE__BUILTIN___CLEAR_CACHE
+#define flush_cache(ADDR, LEN) \
+ __builtin___clear_cache((ADDR), (ADDR) + (LEN))
+#else
+#include <stddef.h>
+extern void flush_cache (void *addr, size_t len);
+#endif
+
+#endif /* FLUSH_CACHE_H */
diff --git a/src/pal/src/libunwind/tests/forker.c b/src/pal/src/libunwind/tests/forker.c
new file mode 100644
index 0000000000..b03f86a7f0
--- /dev/null
+++ b/src/pal/src/libunwind/tests/forker.c
@@ -0,0 +1,76 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+int
+main (int argc, char **argv, char **envp)
+{
+ char *program, **child_argv;
+ struct timeval start, stop;
+ double secs;
+ int status, i;
+ long count;
+ pid_t pid;
+
+ count = atol (argv[1]);
+ program = argv[2];
+
+ child_argv = alloca ((argc - 1) * sizeof (char *));
+ for (i = 0; i < argc - 2; ++i)
+ child_argv[i] = argv[2 + i];
+ child_argv[i] = NULL;
+
+ gettimeofday (&start, NULL);
+ for (i = 0; i < count; ++i)
+ {
+ pid = fork ();
+ if (pid == 0)
+ {
+ execve (program, child_argv, envp);
+ _exit (-1);
+ }
+ else
+ {
+ waitpid (pid, &status, 0);
+ if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
+ {
+ fprintf (stderr, "%s: child failed\n", argv[0]);
+ exit (-1);
+ }
+ }
+ }
+ gettimeofday (&stop, NULL);
+
+ secs = ((stop.tv_sec + 1e-6 * stop.tv_usec)
+ - (start.tv_sec + 1e-6 * start.tv_usec));
+ printf ("%lu nsec/execution\n",
+ (unsigned long) (1e9 * secs / (double) count));
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/ia64-dyn-asm.S b/src/pal/src/libunwind/tests/ia64-dyn-asm.S
new file mode 100644
index 0000000000..79582e9e1b
--- /dev/null
+++ b/src/pal/src/libunwind/tests/ia64-dyn-asm.S
@@ -0,0 +1,102 @@
+ .globl func_add1, func_add1_end
+ .proc func_add1
+func_add1:
+{.mib; add r8 = 1, r32
+ nop.i 0
+ br.ret.sptk.many rp
+}
+func_add1_end:
+ .endp func_add1
+
+ .globl func_add3, func_add3_end
+ .proc func_add3
+func_add3:
+{.mmi; alloc loc0 = ar.pfs, 2, 1, 2, 0
+ mov r2 = sp
+ add sp = -16, sp
+} ;;
+{.mii; ld8 r8 = [in1], 8 // load the function pointer
+ mov r3 = rp
+ mov rp = loc0 // trash rp
+} ;;
+{.mmi; ld8 r9 = [r8], 8 // load the entry-point
+ st8 [r2] = r3
+ mov out0 = in0
+} ;;
+{.mii; ld8 gp = [r8] // load the gp
+ mov b6 = r9
+ mov out1 = in1
+}
+{.mib; nop 0
+ nop 0
+ br.call.sptk rp = b6
+}
+{.mmi; add r2 = 16, sp
+ ;;
+ ld8 r3 = [r2] // r3 = saved rp
+ mov ar.pfs = loc0
+} ;;
+{.mii; nop 0
+ mov rp = r3
+ adds sp = 16, sp
+} ;;
+{.mib; st8 [sp] = in0 // trash rp save location
+ add r8 = 2, r8
+ br.ret.sptk.many rp
+}
+func_add3_end:
+ .endp func_add3
+
+ .globl func_vframe, func_vframe_end
+ .proc func_vframe
+func_vframe:
+{.mii; alloc r16 = ar.pfs, 1, 2, 0, 0 // 0
+ mov loc0 = rp
+ mov loc1 = sp
+} ;;
+{.mmi; sub sp = sp, in0
+ st8 [loc1] = r16
+ mov r2 = -99 // 0
+} ;;
+{.mii; nop 0
+ mov rp = r2
+ mov ar.pfs = r0
+}
+{.mib; mov r16 = r2
+ tbit.nz p6, p0 = in0, 4
+(p6) br.cond.sptk.many .exit
+} ;;
+{.mmi; ld8 r16 = [loc1]
+ ;;
+ mov r3 = loc0 // 8 move saved rp to r3
+ mov ar.pfs = r16
+} ;;
+{.mmi; mov sp = loc1 // 10
+ st8 [loc1] = r0 // trash saved pfs
+ mov loc0 = r2
+} ;;
+{.mib; mov r8 = 10
+ mov rp = r3
+ br.ret.sptk.many rp
+}
+.exit:
+{.mmi; ld8 r16 = [loc1]
+ ;;
+ sub sp = 32, sp
+ mov ar.pfs = r16
+} ;;
+{.mmi; mov sp = loc1
+ st8 [loc1] = r0 // trash saved pfs
+ mov rp = loc0
+}
+{.mib; nop 0
+ mov r8 = 4
+ br.ret.sptk.many rp
+}
+func_vframe_end:
+ .endp func_vframe
+
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/tests/ia64-test-dyn1.c b/src/pal/src/libunwind/tests/ia64-test-dyn1.c
new file mode 100644
index 0000000000..90127dd5b9
--- /dev/null
+++ b/src/pal/src/libunwind/tests/ia64-test-dyn1.c
@@ -0,0 +1,223 @@
+#include "flush-cache.h"
+
+#include <assert.h>
+#include <libunwind.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/mman.h>
+
+int verbose;
+
+#ifdef __ia64__
+# define GET_ENTRY(fdesc) (((uintptr_t *) (fdesc))[0])
+# define GET_GP(fdesc) (((uintptr_t *) (fdesc))[0])
+# define EXTRA 16
+#else
+# define GET_ENTRY(fdesc) ((uintptr_t ) (fdesc))
+# define GET_GP(fdesc) (0)
+# define EXTRA 0
+#endif
+
+int
+make_executable (void *addr, size_t len)
+{
+ if (mprotect ((void *) (((long) addr) & -getpagesize ()), len,
+ PROT_READ | PROT_WRITE | PROT_EXEC) < 0)
+ {
+ perror ("mprotect");
+ return -1;
+ }
+ flush_cache (addr, len);
+ return 0;
+}
+
+void *
+create_func (unw_dyn_info_t *di, const char *name, long (*func) (),
+ void *end, unw_dyn_region_info_t *region)
+{
+ void *mem, *memend, *addr, *fptr;
+ unw_word_t gp = 0;
+ size_t len;
+
+ len = (uintptr_t) end - GET_ENTRY (func) + EXTRA;
+ mem = malloc (len);
+ if (verbose)
+ printf ("%s: cloning %s at %p (%zu bytes)\n",
+ __FUNCTION__, name, mem, len);
+ memend = (char *) mem + len;
+
+#ifdef __ia64__
+ addr = (void *) GET_ENTRY (func);
+
+ /* build function descriptor: */
+ ((long *) mem)[0] = (long) mem + 16; /* entry point */
+ ((long *) mem)[1] = GET_GP (func); /* global-pointer */
+ fptr = mem;
+ mem = (void *) ((long) mem + 16);
+#else
+ fptr = mem;
+#endif
+
+ len = (char *) memend - (char *) mem;
+ memcpy (mem, addr, len);
+
+ if (make_executable (mem, len) < 0)
+ return NULL;
+
+ if (di)
+ {
+ memset (di, 0, sizeof (*di));
+ di->start_ip = (unw_word_t) mem;
+ di->end_ip = (unw_word_t) memend;
+ di->gp = gp;
+ di->format = UNW_INFO_FORMAT_DYNAMIC;
+ di->u.pi.name_ptr = (unw_word_t) name;
+ di->u.pi.regions = region;
+ }
+ return fptr;
+}
+
+int
+main (int argc, char **argv)
+{
+ extern long func_add1 (long);
+ extern char func_add1_end[];
+ extern long func_add3 (long, long (*[])());
+ extern char func_add3_end[];
+ extern long func_vframe (long);
+ extern char func_vframe_end[];
+ unw_dyn_region_info_t *r_pro, *r_epi, *r, *rtmp;
+ unw_dyn_info_t di0, di1, di2, di3;
+ long (*add1) (long);
+ long (*add3_0) (long);
+ long (*add3_1) (long, void *[]);
+ long (*vframe) (long);
+ void *flist[2];
+ long ret;
+ int i;
+
+ signal (SIGUSR1, SIG_IGN);
+ signal (SIGUSR2, SIG_IGN);
+
+ if (argc != 1)
+ verbose = 1;
+
+ add1 = (long (*)(long))
+ create_func (&di0, "func_add1", func_add1, func_add1_end, NULL);
+
+ /* Describe the epilogue of func_add3: */
+ i = 0;
+ r_epi = alloca (_U_dyn_region_info_size (5));
+ r_epi->op_count = 5;
+ r_epi->next = NULL;
+ r_epi->insn_count = -9;
+ _U_dyn_op_pop_frames (&r_epi->op[i++],
+ _U_QP_TRUE, /* when=*/ 5, /* num_frames=*/ 1);
+ _U_dyn_op_stop (&r_epi->op[i++]);
+ assert ((unsigned) i <= r_epi->op_count);
+
+ /* Describe the prologue of func_add3: */
+ i = 0;
+ r_pro = alloca (_U_dyn_region_info_size (4));
+ r_pro->op_count = 4;
+ r_pro->next = r_epi;
+ r_pro->insn_count = 8;
+ _U_dyn_op_save_reg (&r_pro->op[i++], _U_QP_TRUE, /* when=*/ 0,
+ /* reg=*/ UNW_IA64_AR_PFS, /* dst=*/ UNW_IA64_GR + 34);
+ _U_dyn_op_add (&r_pro->op[i++], _U_QP_TRUE, /* when=*/ 2,
+ /* reg= */ UNW_IA64_SP, /* val=*/ -16);
+ _U_dyn_op_save_reg (&r_pro->op[i++], _U_QP_TRUE, /* when=*/ 4,
+ /* reg=*/ UNW_IA64_RP, /* dst=*/ UNW_IA64_GR + 3);
+ _U_dyn_op_spill_sp_rel (&r_pro->op[i++], _U_QP_TRUE, /* when=*/ 7,
+ /* reg=*/ UNW_IA64_RP, /* off=*/ 16);
+ assert ((unsigned) i <= r_pro->op_count);
+
+ /* Create regions for func_vframe: */
+ i = 0;
+ r = alloca (_U_dyn_region_info_size (16));
+ r->op_count = 16;
+ r->next = NULL;
+ r->insn_count = 4;
+ _U_dyn_op_label_state (&r->op[i++], /* label=*/ 100402);
+ _U_dyn_op_pop_frames (&r->op[i++], _U_QP_TRUE, /* when=*/ 3, /* frames=*/ 1);
+ _U_dyn_op_stop (&r->op[i++]);
+ assert ((unsigned) i <= r->op_count);
+
+ i = 0;
+ rtmp = r;
+ r = alloca (_U_dyn_region_info_size (16));
+ r->op_count = 16;
+ r->next = rtmp;
+ r->insn_count = 16;
+ _U_dyn_op_save_reg (&r->op[i++], _U_QP_TRUE, /* when=*/ 8,
+ /* reg=*/ UNW_IA64_RP, /* dst=*/ UNW_IA64_GR + 3);
+ _U_dyn_op_pop_frames (&r->op[i++], _U_QP_TRUE, /* when=*/ 10,
+ /* num_frames=*/ 1);
+ _U_dyn_op_stop (&r->op[i++]);
+ assert ((unsigned) i <= r->op_count);
+
+ i = 0;
+ rtmp = r;
+ r = alloca (_U_dyn_region_info_size (16));
+ r->op_count = 16;
+ r->next = rtmp;
+ r->insn_count = 5;
+ _U_dyn_op_save_reg (&r->op[i++], _U_QP_TRUE, /* when=*/ 1,
+ /* reg=*/ UNW_IA64_RP, /* dst=*/ UNW_IA64_GR + 33);
+ _U_dyn_op_save_reg (&r->op[i++], _U_QP_TRUE, /* when=*/ 2,
+ /* reg=*/ UNW_IA64_SP, /* dst=*/ UNW_IA64_GR + 34);
+ _U_dyn_op_spill_fp_rel (&r->op[i++], _U_QP_TRUE, /* when=*/ 4,
+ /* reg=*/ UNW_IA64_AR_PFS, /* off=*/ 16);
+ _U_dyn_op_label_state (&r->op[i++], /* label=*/ 100402);
+ _U_dyn_op_stop (&r->op[i++]);
+ assert ((unsigned) i <= r->op_count);
+
+ /* Create two functions which can share the region-list: */
+ add3_0 = (long (*) (long))
+ create_func (&di1, "func_add3/0", func_add3, func_add3_end, r_pro);
+ add3_1 = (long (*) (long, void *[]))
+ create_func (&di2, "func_add3/1", func_add3, func_add3_end, r_pro);
+ vframe = (long (*) (long))
+ create_func (&di3, "func_vframe", func_vframe, func_vframe_end, r);
+
+ _U_dyn_register (&di1);
+ _U_dyn_register (&di2);
+ _U_dyn_register (&di3);
+ _U_dyn_register (&di0);
+
+ flist[0] = add3_0;
+ flist[1] = add1;
+
+ kill (getpid (), SIGUSR1); /* do something ptmon can latch onto */
+ ret = (*add3_1) (13, flist);
+ if (ret != 18)
+ {
+ fprintf (stderr, "FAILURE: (*add3_1)(13) returned %ld\n", ret);
+ exit (-1);
+ }
+
+ ret = (*vframe) (48);
+ if (ret != 4)
+ {
+ fprintf (stderr, "FAILURE: (*vframe)(16) returned %ld\n", ret);
+ exit (-1);
+ }
+ ret = (*vframe) (64);
+ if (ret != 10)
+ {
+ fprintf (stderr, "FAILURE: (*vframe)(32) returned %ld\n", ret);
+ exit (-1);
+ }
+ kill (getpid (), SIGUSR2); /* do something ptmon can latch onto */
+
+ _U_dyn_cancel (&di0);
+ _U_dyn_cancel (&di1);
+ _U_dyn_cancel (&di3);
+ _U_dyn_cancel (&di2);
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/ia64-test-nat-asm.S b/src/pal/src/libunwind/tests/ia64-test-nat-asm.S
new file mode 100644
index 0000000000..eea5ac2783
--- /dev/null
+++ b/src/pal/src/libunwind/tests/ia64-test-nat-asm.S
@@ -0,0 +1,508 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+ .text
+
+#define CALL_NEXT_PTR(gp_save_reg, arg0, arg1) \
+ ld8 r2 = [arg0], 8;; /* read the next function pointer */ \
+ ld8 r3 = [r2], 8;; /* read the function's entry-point */ \
+ ld8 r2 = [r2];; /* read the function's gp */ \
+ mov b6 = r3; \
+ mov gp_save_reg = gp; \
+ mov out0 = arg0; \
+ mov out1 = arg1; \
+ mov gp = r2; \
+ br.call.sptk.many rp = b6;; \
+ mov gp = gp_save_reg
+
+#define CALL_NEXT(gp_save_reg) CALL_NEXT_PTR(gp_save_reg, in0, in1)
+
+#define LOAD_VAL(reg) \
+ ld8 reg = [in1], 8;; \
+ tbit.nz p15, p0 = reg, 0;; \
+(p15) ld8.s reg = [r0]
+
+
+ .global flushrs
+ .proc flushrs
+flushrs:
+ flushrs;;
+ br.ret.sptk.many rp
+ .endp flushrs
+
+ /* Save r4-r7 into stacked registers, load them up with the
+ values passed via the pointer in in1 and then call the
+ function passed via the pointer in in0. */
+
+ .global save_static_to_stacked
+ .proc save_static_to_stacked
+save_static_to_stacked:
+ .prologue
+ .regstk 2, 7, 2, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 7, 2, 0
+ .save rp, loc1
+ mov loc1 = rp
+ .spillreg r4, loc2
+ mov loc2 = r4
+ .spillreg r5, loc3
+ mov loc3 = r5
+ .spillreg r6, loc4
+ mov loc4 = r6
+ .spillreg r7, loc5
+ mov loc5 = r7
+ .body
+ LOAD_VAL(r4)
+ LOAD_VAL(r5)
+ LOAD_VAL(r6)
+ LOAD_VAL(r7)
+ CALL_NEXT(loc6)
+
+ mov r4 = loc2
+ mov r5 = loc3
+ mov r6 = loc4
+ mov r7 = loc5
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ br.ret.sptk.many rp
+ .endp save_static_to_stacked
+
+ /* Save f2 to the memory stack, save r4 to f2, then load
+ r4 with the value passed via in1 and call the function
+ passed via in0. */
+
+ .global save_static_to_fr
+ .proc save_static_to_fr
+save_static_to_fr:
+ .prologue
+ .regstk 2, 3, 2, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 3, 2, 0
+ .save rp, loc1
+ mov loc1 = rp
+ .fframe 16
+ .spillpsp f2, 0
+ stf.spill [sp] = f2, -16
+ .spillreg r4, f2
+ setf.sig f2 = r4
+
+ .body
+
+ ld8 r4 = [in1], 8;;
+ tbit.nz p6, p0 = r4, 0;;
+(p6) ld8.s r4 = [r0]
+
+ CALL_NEXT(loc2)
+
+ getf.sig r4 = f2 // restore r4
+ .restore sp
+ add sp = 16, sp;;
+ ldf.fill f2 = [sp] // restore r2
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ br.ret.sptk.many rp
+ .endp save_static_to_fr
+
+ /* If r4 is not a NaT, save b3 to a stacked register and
+ then save r4 in b3. The non-NaTness of r4 is saved in
+ p1. */
+
+ .global save_static_to_br
+ .proc save_static_to_br
+save_static_to_br:
+ .prologue
+ .regstk 2, 6, 2, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 6, 2, 0
+ .save rp, loc1
+ mov loc1 = rp
+
+ .save pr, loc2
+ mov loc2 = pr // save predicates
+
+ .spillreg b3, loc3
+ mov loc3 = b3
+
+ tnat.z p1, p2 = r4;;
+ .spillreg.p p1, r4, b3
+(p1) mov b3 = r4
+ .spillreg.p p2, r4, loc4
+(p2) mov loc4 = r4
+
+ .body
+
+ LOAD_VAL(r4)
+ CALL_NEXT(loc5)
+
+ .pred.rel.mutex p1, p2
+(p1) mov r4 = b3 // restore r4
+(p2) mov r4 = loc4
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ mov pr = loc2, -1
+ mov b3 = loc3 // restore b3
+ br.ret.sptk.many rp
+ .endp save_static_to_br
+
+ /* Spill r4 into memory and then save r5 in r4. */
+
+ .global save_static_to_mem
+ .proc save_static_to_mem
+save_static_to_mem:
+ .prologue
+ .regstk 2, 4, 2, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 4, 2, 0
+ .save rp, loc1
+ mov loc1 = rp
+ .save ar.unat, loc2
+ mov loc2 = ar.unat
+
+ .fframe 16
+ .spillpsp r4, 0
+ st8.spill [sp] = r4, -16
+
+ .spillreg r5, r4
+ mov r4 = r5
+
+ .body
+
+ LOAD_VAL(r5)
+ CALL_NEXT(loc3)
+
+ mov r5 = r4 // restore r5
+ .restore sp
+ add sp = 16, sp;;
+ ld8.fill r4 = [sp] // restore r4
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ mov ar.unat = loc2 // restore ar.unat
+ br.ret.sptk.many rp
+ .endp save_static_to_mem
+
+ /* Spill r6 into memory and save primary ar.unat in a register. */
+
+ .global save_static_to_mem2
+ .proc save_static_to_mem2
+save_static_to_mem2:
+ .prologue
+ .regstk 2, 5, 2, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 5, 2, 0
+ .save rp, loc1
+ mov loc1 = rp
+ .save ar.unat, loc2
+ mov loc2 = ar.unat
+
+ .fframe 16
+ .spillpsp r6, 0
+ st8.spill [sp] = r6, -16;;
+ .save @priunat, loc3
+ mov loc3 = ar.unat
+ mov ar.unat = 0 // trash ar.unat
+
+ .body
+
+ LOAD_VAL(r6)
+ CALL_NEXT(loc4)
+
+ mov ar.unat = loc3 // restore primary UNaT
+ .restore sp
+ add sp = 16, sp;;
+ ld8.fill r6 = [sp] // restore r6
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ mov ar.unat = loc2 // restore ar.unat
+ br.ret.sptk.many rp
+ .endp save_static_to_mem2
+
+ /* Spill r6 into memory and save primary ar.unat in memory. */
+
+ .global save_static_to_mem3
+ .proc save_static_to_mem3
+save_static_to_mem3:
+ .prologue
+ .regstk 2, 5, 2, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 5, 2, 0
+ .save rp, loc1
+ mov loc1 = rp
+ .save ar.unat, loc2
+ mov loc2 = ar.unat
+
+ add r2 = 8, sp
+ .fframe 16
+ .spillpsp r6, 0
+ st8.spill [sp] = r6, -16;;
+ mov r3 = ar.unat;;
+ .savepsp @priunat, -8
+ st8 [r2] = r3
+ mov ar.unat = 0 // trash ar.unat
+
+ .body
+
+ LOAD_VAL(r6)
+ CALL_NEXT(loc4)
+
+ add r2 = 24, sp;;
+ ld8 r3 = [r2];;
+ mov ar.unat = r3 // restore primary UNaT
+ .restore sp
+ add sp = 16, sp;;
+ ld8.fill r6 = [sp] // restore r6
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ mov ar.unat = loc2 // restore ar.unat
+ br.ret.sptk.many rp
+ .endp save_static_to_mem3
+
+ /* Spill r6 into memory and save primary ar.unat in register,
+ then in memory. */
+
+ .global save_static_to_mem4
+ .proc save_static_to_mem4
+save_static_to_mem4:
+ .prologue
+ .regstk 2, 5, 2, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 5, 2, 0
+ .save rp, loc1
+ mov loc1 = rp
+ .save ar.unat, loc2
+ mov loc2 = ar.unat
+
+ add r2 = 8, sp
+ .fframe 16
+ .spillpsp r6, 0
+ st8.spill [sp] = r6, -16;;
+ .save @priunat, r3
+ mov r3 = ar.unat;;
+ mov ar.unat = 0 // trash ar.unat
+ .savepsp @priunat, -8
+ st8 [r2] = r3
+ mov r3 = r0 // trash register pri UNaT location
+ .body
+
+ LOAD_VAL(r6)
+ CALL_NEXT(loc4)
+
+ add r2 = 24, sp;;
+ ld8 r3 = [r2];;
+ mov ar.unat = r3 // restore primary UNaT
+ .restore sp
+ add sp = 16, sp;;
+ ld8.fill r6 = [sp] // restore r6
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ mov ar.unat = loc2 // restore ar.unat
+ br.ret.sptk.many rp
+ .endp save_static_to_mem4
+
+ /* Spill r6 into memory and save primary ar.unat in register,
+ then in memory. */
+
+ .global save_static_to_mem5
+ .proc save_static_to_mem5
+save_static_to_mem5:
+ .prologue
+ .regstk 2, 5, 2, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 5, 2, 0
+ .save rp, loc1
+ mov loc1 = rp
+ .save ar.unat, loc2
+ mov loc2 = ar.unat
+
+ add r2 = 8, sp
+ .fframe 16
+ .spillpsp r6, 0
+ st8.spill [sp] = r6, -16;;
+ mov r3 = ar.unat;;
+ mov ar.unat = 0 // trash ar.unat
+ .savepsp @priunat, -8
+ st8 [r2] = r3
+ .save @priunat, loc3
+ mov loc3 = r3
+ st8 [r2] = r0 // trash memory pri UNaT location
+ .body
+
+ LOAD_VAL(r6)
+ CALL_NEXT(loc4)
+
+ add r2 = 24, sp;;
+ ld8 r3 = [r2];;
+ mov ar.unat = loc3 // restore primary UNaT
+ .restore sp
+ add sp = 16, sp;;
+ ld8.fill r6 = [sp] // restore r6
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ mov ar.unat = loc2 // restore ar.unat
+ br.ret.sptk.many rp
+ .endp save_static_to_mem5
+
+ /* Save r4-r7 to various scratch registers, then trigger
+ a segfault. */
+
+ .global save_static_to_scratch
+ .proc save_static_to_scratch
+save_static_to_scratch:
+ .prologue
+
+ .spillreg r4, r16
+ mov r16 = r4 // save r4 in r16
+ tnat.nz p6, p7 = r5;;
+ .spillreg.p p6, r5, f31
+(p6) setf.sig f31 = r5 // save r5 in f31 if it's a NaT
+ .spillreg.p p7, r5, b6
+(p7) mov b6 = r5 // in b6 if it not
+ .spillreg r6, f32
+ setf.sig f32 = r6 // save r6 in f32 (fph partition)
+ .spillsp r7, 0
+ st8.spill [sp] = r7 // save r7 in the scratch stack space
+ .spillreg f4, f6
+ mov f6 = f4;;
+ .body
+
+ ld8 r2 = [in1]
+ ;;
+ mov ar.ec = r2
+
+ LOAD_VAL(r4)
+ LOAD_VAL(r5)
+ LOAD_VAL(r6)
+ LOAD_VAL(r7)
+ setf.sig f4 = r4
+
+ /* Now force a SIGSEGV. Make sure the ld8 is at the beginning of a
+ bundle, so the signal-handler can skip over it simply by
+ incrementing the IP. */
+ {
+ .mmi
+ ld8 r2 = [r0]
+ nop.m 0
+ nop.i 0 ;;
+ }
+
+ mov f4 = f6
+ mov r4 = r16
+ .pred.rel.mutex p6, p7
+(p6) getf.sig r5 = f31
+(p7) mov r5 = b6
+ getf.sig r6 = f32
+ ld8.fill r7 = [sp]
+
+ br.ret.sptk.many rp
+ .endp save_static_to_scratch
+
+ /* Rotate registers a bit in a vain attempt to sow some confusion.
+ Care must be taken not to write any rotating general register
+ after rotation, because we keep the preserved state
+ there... */
+
+ .global rotate_regs
+ .proc rotate_regs
+rotate_regs:
+ .prologue
+ .regstk 2, 14, 2, 16
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 14, 2, 16
+ .save rp, loc1
+ mov loc1 = rp
+ .save pr, loc2
+ mov loc2 = pr
+ .save ar.lc, loc3
+ mov loc3 = ar.lc
+ .spillreg r4, loc4
+ mov loc4 = r4
+
+ ld8 r2 = [in1], 8;;
+ mov pr = r2, -1
+
+ ld8 r2 = [in1], 8;;
+ mov r8 = in0
+ mov r9 = in1
+ and r2 = 127, r2;;
+ mov ar.ec = 0
+ mov ar.lc = r2;;
+
+ // use p6 to preserve p63 as it gets rotated into p16:
+(p16) cmp.eq.unc p6,p0 = r0,r0;;
+1:
+(p6) cmp.eq.unc p16,p0 = r0,r0
+(p63) cmp.eq.unc p6,p0 = r0,r0
+ br.ctop.dptk.few 1b;;
+
+(p6) cmp.eq.unc p63,p0 = r0,r0
+
+ CALL_NEXT_PTR(r4, r8, r9)
+
+ clrrrb
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ mov pr = loc2, -1
+ mov ar.lc = loc3
+ mov r4 = loc4
+ br.ret.sptk.many rp
+
+ .endp rotate_regs
+
+ .global save_pr
+ .proc save_pr
+save_pr:
+ .prologue
+ .regstk 2, 4, 2, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 4, 2, 0
+ .save rp, loc1
+ mov loc1 = rp
+ .save pr, loc2
+ mov loc2 = pr
+
+ ld8 r2 = [in1], 8;;
+ mov pr = r2, -1
+
+ CALL_NEXT(loc3)
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ mov pr = loc2, -1
+ br.ret.sptk.many rp
+
+ .endp save_pr
+
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/tests/ia64-test-rbs-asm.S b/src/pal/src/libunwind/tests/ia64-test-rbs-asm.S
new file mode 100644
index 0000000000..9a6d33fb1d
--- /dev/null
+++ b/src/pal/src/libunwind/tests/ia64-test-rbs-asm.S
@@ -0,0 +1,275 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "ia64-test-rbs.h"
+
+ .common stackmem, NSTACKS*STACK_SIZE, 16
+
+ .text
+
+#define SAVED_SP_OFF 0
+#define SAVED_RP_OFF 8
+#define SAVED_PFS_OFF 16
+#define SAVED_RNAT_OFF 24
+#define SAVED_BSP_OFF 32
+#define SAVED_BSPSTORE_OFF 40
+#define FRAME_SIZE 48
+
+#define SPILL(n) \
+ /* int rbs_spill_#n(long iteration, int (*next_func[])()) */ \
+ .globl rbs_spill_##n; \
+ .proc rbs_spill_##n; \
+rbs_spill_##n: \
+ .prologue; \
+ alloc r18 = ar.pfs, 2, (n)-2, 2, 0;/* read ar.pfs */ \
+ /* first, calculate address of new stack: */ \
+ addl r2 = @ltoff(stackmem), gp; \
+ add r8 = 1, in0; \
+ ;; \
+ ld8 r2 = [r2]; /* r2 = &stackmem */ \
+ shl r3 = in0, STACK_SIZE_SHIFT; \
+ shladd r8 = r8, 3, in1; /* r8 = &next_func[iteration+1] */ \
+ ;; \
+ ld8 r8 = [r8]; /* r8 = next_func[iteration+1] */ \
+ add r2 = r2, r3; /* r2 = stackmem[iteration] */ \
+ ;; \
+ ld8 r9 = [r8], 8;; /* r9 = target's entry-point */ \
+ ld8 gp = [r8]; /* r22 = target's gp */ \
+ addl r3 = STACK_SIZE-FRAME_SIZE, r2; /* r3 = &stackframe */ \
+ ;; \
+ mov b6 = r9; \
+ st8 [r3] = sp; \
+ .vframesp SAVED_SP_OFF+16; \
+ adds sp = -16, r3; /* switch the memory stack */ \
+ ;; \
+ adds r3 = (SAVED_RP_OFF - SAVED_SP_OFF), r3; \
+ mov r16 = rp; \
+ ;; \
+ .savesp rp, SAVED_RP_OFF+16; \
+ st8 [r3] = r16, (SAVED_PFS_OFF - SAVED_RP_OFF); \
+ ;; \
+ .savesp ar.pfs, SAVED_PFS_OFF+16; \
+ st8 [r3] = r18, (SAVED_BSP_OFF - SAVED_PFS_OFF); \
+ mov r16 = ar.bsp; \
+ mov r17 = ar.bspstore; \
+ mov r18 = ar.rnat; \
+ ;; \
+ .savesp ar.bsp, SAVED_BSP_OFF+16; \
+ st8 [r3] = r16, (SAVED_BSPSTORE_OFF - SAVED_BSP_OFF); \
+ ;; \
+ .savesp ar.bspstore, SAVED_BSPSTORE_OFF+16; \
+ st8 [r3] = r17, (SAVED_RNAT_OFF - SAVED_BSPSTORE_OFF); \
+ mov out1 = in1; \
+ ;; \
+ .savesp ar.rnat, SAVED_RNAT_OFF+16; \
+ st8 [r3] = r18; \
+ .body; \
+ mov ar.bspstore = r2; /* switch the backing store */ \
+ adds out0 = 1, in0; \
+ ;; \
+ br.call.sptk.many rp = b6; \
+1: /* switch back to stack: */ \
+ adds r3 = SAVED_SP_OFF+16, sp; \
+ cmp.ge p8, p0 = r8, r0; \
+ ;; \
+(p8) add r8 = 1, r8; \
+ ld8 r16 = [r3], (SAVED_RP_OFF-SAVED_SP_OFF);; /* saved sp */ \
+ ld8 r17 = [r3], (SAVED_PFS_OFF-SAVED_RP_OFF);; /* saved rp */ \
+ ld8 r18 = [r3], (SAVED_RNAT_OFF-SAVED_PFS_OFF);;/* saved pfs */ \
+ ld8 r19 = [r3], (SAVED_BSP_OFF-SAVED_RNAT_OFF);;/* saved rnat */ \
+ ld8 r20 = [r3], (SAVED_BSPSTORE_OFF-SAVED_BSP_OFF);;/* saved bsp */ \
+ ld8 r21 = [r3];; /* saved bspstore */ \
+ mov rp = r17; \
+ mov ar.pfs = r18; \
+ shl r3 = in0, STACK_SIZE_SHIFT; \
+ addl r2 = @ltoff(stackmem), gp;; \
+ ld8 r2 = [r2];; /* r2 = &stackmem */ \
+ add r2 = r2, r3; /* r2 = stackmem[iteration] */ \
+ mov r3 = ar.bsp;; \
+ sub r2 = r3, r2;; /* r2 = dirty_size */ \
+ shl r2 = r2, 16;; \
+ mov ar.rsc = r2;; \
+ alloc r3 = ar.pfs, 0, 0, 0, 0;; \
+ loadrs;; \
+ mov ar.bspstore = r21;; /* this also restores ar.bsp */ \
+ mov ar.rnat = r19; \
+ .restore sp; \
+ mov sp = r16; \
+ br.ret.sptk.many rp; \
+ .endp rbs_spill_##n
+
+ SPILL(2); SPILL(3)
+ SPILL(4); SPILL(5); SPILL(6); SPILL(7)
+ SPILL(8); SPILL(9); SPILL(10); SPILL(11)
+ SPILL(12); SPILL(13); SPILL(14); SPILL(15)
+ SPILL(16); SPILL(17); SPILL(18); SPILL(19)
+ SPILL(20); SPILL(21); SPILL(22); SPILL(23)
+ SPILL(24); SPILL(25); SPILL(26); SPILL(27)
+ SPILL(28); SPILL(29); SPILL(30); SPILL(31)
+ SPILL(32); SPILL(33); SPILL(34); SPILL(35)
+ SPILL(36); SPILL(37); SPILL(38); SPILL(39)
+ SPILL(40); SPILL(41); SPILL(42); SPILL(43)
+ SPILL(44); SPILL(45); SPILL(46); SPILL(47)
+ SPILL(48); SPILL(49); SPILL(50); SPILL(51)
+ SPILL(52); SPILL(53); SPILL(54); SPILL(55)
+ SPILL(56); SPILL(57); SPILL(58); SPILL(59)
+ SPILL(60); SPILL(61); SPILL(62); SPILL(63)
+ SPILL(64); SPILL(65); SPILL(66); SPILL(67)
+ SPILL(68); SPILL(69); SPILL(70); SPILL(71)
+ SPILL(72); SPILL(73); SPILL(74); SPILL(75)
+ SPILL(76); SPILL(77); SPILL(78); SPILL(79)
+ SPILL(80); SPILL(81); SPILL(82); SPILL(83)
+ SPILL(84); SPILL(85); SPILL(86); SPILL(87)
+ SPILL(88); SPILL(89); SPILL(90); SPILL(91)
+ SPILL(92); SPILL(93); SPILL(94)
+
+#define LD_LOC(n) \
+ ld4 loc##n = [in1], 4;; \
+ cmp.eq p8, p9 = r0, loc##n;; \
+(p9) or loc##n = loc##n, r8; \
+(p8) ld4.s loc##n = [r0]
+
+#define CK_LOC(n) \
+ ld4 r16 = [in1], 4;; \
+ cmp.eq p8, p9 = r0, r16; \
+ or r16 = r16, r9;; \
+(p8) tnat.z p10, p0 = loc##n; \
+(p9) cmp.ne p10, p0 = r16, loc##n; \
+ ;; \
+(p10) mov r8 = -n; \
+(p10) br.cond.spnt.many .fail
+
+ /* int loadup(long iteration, int *values, next_func[]) */
+
+ .global loadup
+ .proc loadup
+loadup:
+ .prologue
+ .save ar.pfs, r36
+ alloc loc1 = ar.pfs, 3, 90, 3, 0
+ .save rp, loc0
+ mov loc0 = rp
+ .body
+ cmp.eq p6, p7 = 1, in0
+ ;;
+ mov ar.rsc = 0 // put RSE into enforced lazy mode
+(p6) mov out1 = in2
+(p7) mov out2 = in2
+
+(p6) ld8 r17 = [in2] // get address of function descriptor
+(p7) add out0 = -1, in0
+(p7) mov out1 = in1
+
+ ;;
+(p6) ld8 r16 = [r17], 8 // load entry point
+ shl r8 = in0, 32 // store iteration # in top 32 bits
+ mov r18 = in1
+ ;;
+(p6) ld8 r1 = [r17] // load gp
+(p6) mov b6 = r16
+
+(p6) mov out0 = 0
+ ;;
+ LD_LOC( 2); LD_LOC( 3)
+ LD_LOC( 4); LD_LOC( 5); LD_LOC( 6); LD_LOC( 7)
+ LD_LOC( 8); LD_LOC( 9); LD_LOC(10); LD_LOC(11)
+ LD_LOC(12); LD_LOC(13); LD_LOC(14); LD_LOC(15)
+ LD_LOC(16); LD_LOC(17); LD_LOC(18); LD_LOC(19)
+ LD_LOC(20); LD_LOC(21); LD_LOC(22); LD_LOC(23)
+ LD_LOC(24); LD_LOC(25); LD_LOC(26); LD_LOC(27)
+ LD_LOC(28); LD_LOC(29); LD_LOC(30); LD_LOC(31)
+ LD_LOC(32); LD_LOC(33); LD_LOC(34); LD_LOC(35)
+ LD_LOC(36); LD_LOC(37); LD_LOC(38); LD_LOC(39)
+ LD_LOC(40); LD_LOC(41); LD_LOC(42); LD_LOC(43)
+ LD_LOC(44); LD_LOC(45); LD_LOC(46); LD_LOC(47)
+ LD_LOC(48); LD_LOC(49); LD_LOC(50); LD_LOC(51)
+ LD_LOC(52); LD_LOC(53); LD_LOC(54); LD_LOC(55)
+ LD_LOC(56); LD_LOC(57); LD_LOC(58); LD_LOC(59)
+ LD_LOC(60); LD_LOC(61); LD_LOC(62); LD_LOC(63)
+ LD_LOC(64); LD_LOC(65); LD_LOC(66); LD_LOC(67)
+ LD_LOC(68); LD_LOC(69); LD_LOC(70); LD_LOC(71)
+ LD_LOC(72); LD_LOC(73); LD_LOC(74); LD_LOC(75)
+ LD_LOC(76); LD_LOC(77); LD_LOC(78); LD_LOC(79)
+ LD_LOC(80); LD_LOC(81); LD_LOC(82); LD_LOC(83)
+ LD_LOC(84); LD_LOC(85); LD_LOC(86); LD_LOC(87)
+ LD_LOC(88); LD_LOC(89)
+ ;;
+{ .mbb
+ mov in1 = r18
+(p6) br.call.sptk.many rp = b6
+(p7) br.call.sptk.many rp = loadup
+}
+ cmp.lt p8, p9 = r8, r0
+ shl r9 = in0, 32 // store iteration # in top 32 bits
+(p8) br.cond.spnt.few .fail
+ ;;
+ add r8 = 1, r8
+ CK_LOC( 2); CK_LOC( 3)
+ CK_LOC( 4); CK_LOC( 5); CK_LOC( 6); CK_LOC( 7)
+ CK_LOC( 8); CK_LOC( 9); CK_LOC(10); CK_LOC(11)
+ CK_LOC(12); CK_LOC(13); CK_LOC(14); CK_LOC(15)
+ CK_LOC(16); CK_LOC(17); CK_LOC(18); CK_LOC(19)
+ CK_LOC(20); CK_LOC(21); CK_LOC(22); CK_LOC(23)
+ CK_LOC(24); CK_LOC(25); CK_LOC(26); CK_LOC(27)
+ CK_LOC(28); CK_LOC(29); CK_LOC(30); CK_LOC(31)
+ CK_LOC(32); CK_LOC(33); CK_LOC(34); CK_LOC(35)
+ CK_LOC(36); CK_LOC(37); CK_LOC(38); CK_LOC(39)
+ CK_LOC(40); CK_LOC(41); CK_LOC(42); CK_LOC(43)
+ CK_LOC(44); CK_LOC(45); CK_LOC(46); CK_LOC(47)
+ CK_LOC(48); CK_LOC(49); CK_LOC(50); CK_LOC(51)
+ CK_LOC(52); CK_LOC(53); CK_LOC(54); CK_LOC(55)
+ CK_LOC(56); CK_LOC(57); CK_LOC(58); CK_LOC(59)
+ CK_LOC(60); CK_LOC(61); CK_LOC(62); CK_LOC(63)
+ CK_LOC(64); CK_LOC(65); CK_LOC(66); CK_LOC(67)
+ CK_LOC(68); CK_LOC(69); CK_LOC(70); CK_LOC(71)
+ CK_LOC(72); CK_LOC(73); CK_LOC(74); CK_LOC(75)
+ CK_LOC(76); CK_LOC(77); CK_LOC(78); CK_LOC(79)
+ CK_LOC(80); CK_LOC(81); CK_LOC(82); CK_LOC(83)
+ CK_LOC(84); CK_LOC(85); CK_LOC(86); CK_LOC(87)
+ CK_LOC(88); CK_LOC(89)
+.fail:
+ mov rp = loc0
+ mov ar.pfs = loc1
+ br.ret.sptk.many rp
+ .endp loadup
+
+ .global resumption_point_label
+ .proc resumption_point
+resumption_point:
+resumption_point_label:
+ .prologue
+ .save rp, r16
+ .save ar.pfs, r0
+ .body
+ mov r8 = r15
+ mov b6 = r16
+ ;;
+ br.cond.sptk.many b6
+ .endp resumption_point
+
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/tests/ia64-test-rbs.h b/src/pal/src/libunwind/tests/ia64-test-rbs.h
new file mode 100644
index 0000000000..3315ad6380
--- /dev/null
+++ b/src/pal/src/libunwind/tests/ia64-test-rbs.h
@@ -0,0 +1,3 @@
+#define NSTACKS 128
+#define STACK_SIZE_SHIFT 17
+#define STACK_SIZE (1 << STACK_SIZE_SHIFT)
diff --git a/src/pal/src/libunwind/tests/ia64-test-readonly-asm.S b/src/pal/src/libunwind/tests/ia64-test-readonly-asm.S
new file mode 100644
index 0000000000..acd3ada2c6
--- /dev/null
+++ b/src/pal/src/libunwind/tests/ia64-test-readonly-asm.S
@@ -0,0 +1,55 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+ .text
+
+ .global test_func
+ .proc test_func
+test_func:
+ .prologue
+ .regstk 1, 3, 0, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 1, 3, 0, 0
+ mov loc1 = rp
+ .save rp, r0
+ .save ar.lc, r0
+ .body
+ mov loc2 = gp
+ ld8 r2 = [in0], 8;;
+ ld8 r1 = [in0];;
+ mov b6 = r2
+ br.call.sptk.many rp = b6
+
+ mov gp = loc2
+ mov rp = loc1
+ mov ar.pfs = loc0
+ br.ret.sptk.many rp
+
+ .endp test_func
+
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/tests/ia64-test-setjmp.c b/src/pal/src/libunwind/tests/ia64-test-setjmp.c
new file mode 100644
index 0000000000..50eaa01bc3
--- /dev/null
+++ b/src/pal/src/libunwind/tests/ia64-test-setjmp.c
@@ -0,0 +1,155 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Test to verify that we can siglongjmp() into a frame whose register
+ window is not backed by valid memory. */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+
+#ifdef HAVE_IA64INTRIN_H
+# include <ia64intrin.h>
+#endif
+
+static sigjmp_buf env;
+static int return_level;
+static uintptr_t return_bsp;
+static int verbose;
+
+uintptr_t
+get_bsp (void)
+{
+#ifdef __INTEL_COMPILER
+ return __getReg (_IA64_REG_AR_BSP);
+#else
+ return (uintptr_t) __builtin_ia64_bsp ();
+#endif
+}
+
+static void
+sighandler (int signal, void *siginfo, void *sigcontext)
+{
+ ucontext_t *uc = sigcontext;
+ int local = 0;
+
+ if (verbose)
+ printf ("got signal, stack at %p, saved bsp=0x%lx\n",
+ &local, uc->uc_mcontext.sc_ar_bsp);
+ siglongjmp (env, 1);
+}
+
+/* Direct call of doit () at the end of doit () would get optimized by GCC to
+ a branch. */
+static void doit (int n);
+typedef void (*doit_type) (int);
+static volatile doit_type doit_pointer = doit;
+
+static void
+doit (int n)
+{
+ uintptr_t guard_page_addr, bsp = get_bsp ();
+ void *ret;
+
+ if (n == 0)
+ {
+ size_t page_size = getpagesize ();
+
+ guard_page_addr = (bsp + page_size - 1) & -page_size;
+ if (verbose)
+ printf ("guard_page_addr = 0x%lx\n", (unsigned long) guard_page_addr);
+ ret = mmap ((void *) guard_page_addr, page_size, PROT_NONE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (ret != (void *) guard_page_addr)
+ {
+ if (ret == MAP_FAILED)
+ perror ("mmap");
+ else
+ fprintf (stderr, "mmap() returned %p, expected 0x%lx\n",
+ ret, guard_page_addr);
+ exit (EXIT_FAILURE);
+ }
+ }
+
+ if (sigsetjmp (env, 1))
+ {
+ return_level = n;
+ return_bsp = bsp;
+ }
+ else
+ (*doit_pointer) (n + 1);
+}
+
+int
+main (int argc, char **argv)
+{
+ struct sigaction sa;
+ stack_t ss;
+
+ if (argc > 1)
+ verbose = 1;
+
+ ss.ss_sp = malloc (2 * SIGSTKSZ);
+ if (ss.ss_sp == NULL)
+ {
+ puts ("failed to allocate alternate stack");
+ return EXIT_FAILURE;
+ }
+ ss.ss_flags = 0;
+ ss.ss_size = 2 * SIGSTKSZ;
+ if (sigaltstack (&ss, NULL) < 0)
+ {
+ printf ("sigaltstack failed: %s\n", strerror (errno));
+ return EXIT_FAILURE;
+ }
+
+ sa.sa_handler = (void (*) (int)) sighandler;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
+ if (sigaction (SIGSEGV, &sa, NULL) < 0)
+ {
+ printf ("sigaction failed: %s\n", strerror (errno));
+ exit (1);
+ }
+
+ doit (0);
+
+ if (verbose)
+ {
+ printf ("sigsetjmp returned at level %d bsp=0x%lx\n",
+ return_level, return_bsp);
+ puts ("Test succeeded!");
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/src/pal/src/libunwind/tests/ia64-test-sig.c b/src/pal/src/libunwind/tests/ia64-test-sig.c
new file mode 100644
index 0000000000..473efe91d7
--- /dev/null
+++ b/src/pal/src/libunwind/tests/ia64-test-sig.c
@@ -0,0 +1,102 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* This test uses the unwind interface to modify the IP in an ancestor
+ frame while still returning to the parent frame. */
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <libunwind-ia64.h>
+
+#define panic(args...) \
+ { fprintf (stderr, args); exit (-1); }
+
+int verbose;
+
+static void
+sighandler (int signal)
+{
+ unw_cursor_t cursor, cursor2;
+ unw_word_t ip;
+ unw_context_t uc;
+
+ if (verbose)
+ printf ("caught signal %d\n", signal);
+
+ unw_getcontext (&uc);
+ if (unw_init_local (&cursor, &uc) < 0)
+ panic ("unw_init() failed!\n");
+
+ /* get cursor for caller of sighandler: */
+ if (unw_step (&cursor) < 0)
+ panic ("unw_step() failed!\n");
+
+ cursor2 = cursor;
+ while (!unw_is_signal_frame (&cursor2))
+ if (unw_step (&cursor2) < 0)
+ panic ("failed to find signal frame!\n");
+
+ if (unw_step (&cursor2) < 0)
+ panic ("unw_step() failed!\n");
+
+ if (unw_get_reg (&cursor2, UNW_REG_IP, &ip) < 0)
+ panic ("failed to get IP!\n");
+
+ /* skip faulting instruction (doesn't handle MLX template) */
+ ++ip;
+ if ((ip & 0x3) == 0x3)
+ ip += 13;
+
+ if (unw_set_reg (&cursor2, UNW_REG_IP, ip) < 0)
+ panic ("failed to set IP!\n");
+
+ unw_resume (&cursor); /* update context & return to caller of sighandler() */
+
+ panic ("unexpected return from unw_resume()!\n");
+}
+
+static void
+doit (volatile char *p)
+{
+ int ch;
+
+ ch = *p; /* trigger SIGSEGV */
+
+ if (verbose)
+ printf ("doit: finishing execution!\n");
+}
+
+int
+main (int argc, char **argv)
+{
+ if (argc > 1)
+ verbose = 1;
+
+ signal (SIGSEGV, sighandler);
+ doit (0);
+ if (verbose)
+ printf ("SUCCESS\n");
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/ia64-test-stack-asm.S b/src/pal/src/libunwind/tests/ia64-test-stack-asm.S
new file mode 100644
index 0000000000..0aea33a441
--- /dev/null
+++ b/src/pal/src/libunwind/tests/ia64-test-stack-asm.S
@@ -0,0 +1,183 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "ia64-test-stack.h"
+
+ .common stackmem, NSTACKS*STACK_SIZE, 16
+
+ .global do_unwind_tests
+
+ .text
+
+#define SAVED_SP_OFF 0
+#define SAVED_RP_OFF 8
+#define SAVED_PFS_OFF 16
+#define SAVED_RNAT_OFF 24
+#define SAVED_BSP_OFF 32
+#define SAVED_BSPSTORE_OFF 40
+#define FRAME_SIZE 48
+
+ .proc stack_it
+stack_it:
+ .prologue
+ alloc r18 = ar.pfs, 0, 0, 0, 0 // read ar.pfs
+ // first, calculate address of new stack:
+ addl r2 = @ltoff(stackmem), gp
+ shl r3 = r8, STACK_SIZE_SHIFT
+ ;;
+ ld8 r2 = [r2] // r2 = &stackmem
+ ;;
+ add r2 = r2, r3 // r2 = stackmem[iteration]
+ ;;
+ addl r3 = STACK_SIZE-FRAME_SIZE, r2 // r3 = &stackframe
+ ;;
+ st8 [r3] = sp
+ .vframesp SAVED_SP_OFF+16
+ adds sp = -16, r3 // switch the memory stack
+ ;;
+ adds r3 = (SAVED_RP_OFF - SAVED_SP_OFF), r3
+ mov r16 = rp
+ ;;
+ .savesp rp, SAVED_RP_OFF+16
+ st8 [r3] = r16, (SAVED_PFS_OFF - SAVED_RP_OFF)
+ ;;
+ .savesp ar.pfs, SAVED_PFS_OFF+16
+ st8 [r3] = r18, (SAVED_BSP_OFF - SAVED_PFS_OFF)
+
+ mov r16 = ar.bsp
+ mov r17 = ar.bspstore
+ mov r18 = ar.rnat
+ ;;
+ .savesp ar.bsp, SAVED_BSP_OFF+16
+ st8 [r3] = r16, (SAVED_BSPSTORE_OFF - SAVED_BSP_OFF)
+ ;;
+ .savesp ar.bspstore, SAVED_BSPSTORE_OFF+16
+ st8 [r3] = r17, (SAVED_RNAT_OFF - SAVED_BSPSTORE_OFF)
+ ;;
+ .savesp ar.rnat, SAVED_RNAT_OFF+16
+ st8 [r3] = r18
+ ;;
+ mov ar.bspstore = r2 // switch the backing store
+
+ .body
+
+ // for even iterations, allocate a local variable:
+ tbit.nz p6, p0 = r8, 0
+(p6) br.cond.sptk.few .skip
+ ;;
+ alloc r2 = ar.pfs, 0, 1, 0, 0
+ mov loc0 = r8
+ ;;
+.skip: cmp.ne p6, p7 = 0, r8
+ ;;
+{ .mbb
+(p6) adds r8 = -1, r8
+(p6) br.call.sptk.many rp = stack_it // next iteration
+(p7) br.call.sptk.many rp = do_unwind_tests // time for introspection...
+}
+ // switch back to stack:
+
+ adds r3 = SAVED_SP_OFF+16, sp
+ ;;
+ ld8 r16 = [r3], (SAVED_RP_OFF-SAVED_SP_OFF);; // saved sp
+ ld8 r17 = [r3], (SAVED_PFS_OFF-SAVED_RP_OFF);; // saved rp
+ ld8 r18 = [r3], (SAVED_RNAT_OFF-SAVED_PFS_OFF);; // saved pfs
+ ld8 r19 = [r3], (SAVED_BSP_OFF-SAVED_RNAT_OFF);; // saved rnat
+ ld8 r20 = [r3], (SAVED_BSPSTORE_OFF-SAVED_BSP_OFF);; // saved bsp
+ ld8 r21 = [r3];; // saved bspstore
+
+ mov rp = r17
+ mov ar.pfs = r18
+ mov ar.bspstore = r21 // this also restores ar.bsp
+ ;;
+ mov ar.rnat = r19
+
+ .restore sp
+ mov sp = r16
+ br.ret.sptk.many rp
+ .endp stack_it
+
+
+#define SET_LOC(n) add loc##n = n, r8
+#define SET_NAT(n) ld8.s loc##n = [r0]
+
+ .global touch_all
+ .proc touch_all
+touch_all:
+ .prologue
+ .save ar.pfs, r34
+ alloc loc1 = ar.pfs, 1, 94, 1, 0
+ .save rp, loc0
+ mov loc0 = rp
+ .body
+
+ mov ar.rsc = 0 // put RSE into enforced lazy mode
+ shl r8 = in0, 32 // store iteration # in top 32 bits
+ add out0 = -1, in0
+ cmp.eq p6, p7 = 1, in0
+ ;;
+ SET_LOC( 2); SET_LOC( 3)
+ SET_LOC( 4); SET_LOC( 5); SET_LOC( 6); SET_LOC( 7)
+ SET_LOC( 8); SET_LOC( 9); SET_LOC(10); SET_LOC(11)
+ SET_LOC(12); SET_LOC(13); SET_LOC(14); SET_LOC(15)
+ SET_LOC(16); SET_LOC(17); SET_LOC(18); SET_LOC(19)
+ SET_LOC(20); SET_LOC(21); SET_LOC(22); SET_LOC(23)
+ SET_LOC(24); SET_LOC(25); SET_LOC(26); SET_LOC(27)
+ SET_LOC(28); SET_LOC(29); SET_LOC(30); SET_LOC(31)
+ SET_LOC(32); SET_LOC(33); SET_LOC(34); SET_LOC(35)
+ SET_LOC(36); SET_LOC(37); SET_LOC(38); SET_LOC(39)
+ SET_LOC(40); SET_LOC(41); SET_LOC(42); SET_LOC(43)
+ SET_LOC(44); SET_LOC(45); SET_LOC(46); SET_LOC(47)
+ SET_LOC(48); SET_LOC(49); SET_LOC(50); SET_LOC(51)
+ SET_LOC(52); SET_LOC(53); SET_LOC(54); SET_LOC(55)
+ SET_LOC(56); SET_LOC(57); SET_LOC(58); SET_LOC(59)
+ SET_LOC(60); SET_LOC(61); SET_LOC(62); SET_LOC(63)
+ SET_LOC(64); SET_LOC(65); SET_LOC(66); SET_LOC(67)
+ SET_LOC(68); SET_LOC(69); SET_LOC(70); SET_LOC(71)
+ SET_LOC(72); SET_LOC(73); SET_LOC(74); SET_LOC(75)
+ SET_LOC(76); SET_LOC(77); SET_LOC(78); SET_LOC(79)
+ SET_LOC(80); SET_LOC(81); SET_LOC(82); SET_LOC(83)
+ SET_LOC(84); SET_LOC(85); SET_LOC(86); SET_LOC(87)
+ SET_LOC(88); SET_LOC(89); SET_LOC(90); SET_LOC(91)
+ SET_LOC(92); SET_LOC(93)
+ ;;
+ SET_NAT(2); SET_NAT(31); SET_NAT(73); SET_NAT(93)
+ ;;
+{ .mbb
+ mov r8=NSTACKS-1
+(p6) br.call.sptk.many rp = stack_it
+(p7) br.call.sptk.many rp = touch_all
+}
+ ;;
+
+ mov rp = loc0
+ mov ar.pfs = loc1
+ br.ret.sptk.many rp
+ .endp touch_all
+
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/pal/src/libunwind/tests/ia64-test-stack.h b/src/pal/src/libunwind/tests/ia64-test-stack.h
new file mode 100644
index 0000000000..5665a79d95
--- /dev/null
+++ b/src/pal/src/libunwind/tests/ia64-test-stack.h
@@ -0,0 +1,3 @@
+#define NSTACKS 1024
+#define STACK_SIZE_SHIFT 17
+#define STACK_SIZE (1 << STACK_SIZE_SHIFT)
diff --git a/src/pal/src/libunwind/tests/ident.c b/src/pal/src/libunwind/tests/ident.c
new file mode 100644
index 0000000000..9024e292f5
--- /dev/null
+++ b/src/pal/src/libunwind/tests/ident.c
@@ -0,0 +1,5 @@
+long
+f (long val)
+{
+ return val;
+}
diff --git a/src/pal/src/libunwind/tests/mapper.c b/src/pal/src/libunwind/tests/mapper.c
new file mode 100644
index 0000000000..b47ae780f8
--- /dev/null
+++ b/src/pal/src/libunwind/tests/mapper.c
@@ -0,0 +1,78 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* This program creates lots of mappings such that on Linux the
+ reading of /proc/PID/maps gets very slow. With proper caching,
+ test-ptrace should still run at acceptable speed once
+ /proc/PID/maps has been scanned. If the program dies with a
+ SIGALRM, it means it was running unexpectedly slow. */
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+
+#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
+# define MAP_ANONYMOUS MAP_ANON
+#endif
+#if !defined(MAP_NORESERVE)
+# define MAP_NORESERVE 0
+#endif
+
+int
+main (void)
+{
+ long n = 0;
+
+ signal (SIGUSR1, SIG_IGN);
+ signal (SIGUSR2, SIG_IGN);
+
+ printf ("Starting mmap test...\n");
+ for (n = 0; n < 30000; ++n)
+ {
+ if (mmap (NULL, 1, (n & 1) ? PROT_READ : PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS
+#ifdef MAP_NORESERVE
+ | MAP_NORESERVE
+#endif
+ ,
+ -1, 0) == MAP_FAILED)
+ {
+ printf ("Failed after %ld successful maps\n", n - 1);
+ exit (0);
+ }
+ }
+
+ alarm (80); /* die if we don't finish in 80 seconds */
+
+ printf ("Turning on single-stepping...\n");
+ kill (getpid (), SIGUSR1); /* tell test-ptrace to start single-stepping */
+ printf ("Va bene?\n");
+ kill (getpid (), SIGUSR2); /* tell test-ptrace to stop single-stepping */
+ printf ("Turned single-stepping off...\n");
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/perf-startup b/src/pal/src/libunwind/tests/perf-startup
new file mode 100755
index 0000000000..1c24e9a9bc
--- /dev/null
+++ b/src/pal/src/libunwind/tests/perf-startup
@@ -0,0 +1,19 @@
+#!/bin/sh
+platform=$1
+LIBUNWIND=../src/.libs/libunwind.so
+LIBUNWIND_PLAT=../src/.libs/libunwind-$platform.so
+warmup=$(./forker 2000 /bin/true | cut -f1 -d' ')
+
+nsec1=$(./forker 2000 /bin/true | cut -f1 -d' ')
+printf "\"/bin/true\"\t\t\t\t\t\t: $nsec1 nsec/execution\n"
+
+nsec2=$(LD_PRELOAD=$LIBUNWIND ./forker 2000 /bin/true | cut -f1 -d' ')
+printf "\"LD_PRELOAD=$LIBUNWIND /bin/true\"\t: $nsec2 nsec/execution\n"
+
+nsec3=$(LD_PRELOAD=$LIBUNWIND_PLAT ./forker 2000 /bin/true | cut -f1 -d' ')
+printf "\"LD_PRELOAD=$LIBUNWIND_PLAT /bin/true\"\t: $nsec3 nsec/execution\n"
+
+echo
+
+printf "Overhead of preloading $LIBUNWIND\t: $(($nsec2 - $nsec1)) nsec\n"
+printf "Overhead of preloading $LIBUNWIND_PLAT\t: $(($nsec3 - $nsec1)) nsec\n"
diff --git a/src/pal/src/libunwind/tests/ppc64-test-altivec-utils.c b/src/pal/src/libunwind/tests/ppc64-test-altivec-utils.c
new file mode 100644
index 0000000000..bd67ff7d6e
--- /dev/null
+++ b/src/pal/src/libunwind/tests/ppc64-test-altivec-utils.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+#include <altivec.h>
+
+union si_overlay
+{
+ vector signed int v;
+ int ints[4];
+};
+
+vector signed int
+vec_init ()
+{
+ vector signed int v;
+ static int count = 1;
+
+ ((union si_overlay *) &v)->ints[0] = count++;
+ ((union si_overlay *) &v)->ints[1] = count++;
+ ((union si_overlay *) &v)->ints[2] = count++;
+ ((union si_overlay *) &v)->ints[3] = count++;
+ return v;
+}
+
+void
+vec_print (vector signed int v)
+{
+ printf ("%08x %08x %08x %08x",
+ ((union si_overlay *) &v)->ints[0],
+ ((union si_overlay *) &v)->ints[1],
+ ((union si_overlay *) &v)->ints[2],
+ ((union si_overlay *) &v)->ints[3]);
+}
+
diff --git a/src/pal/src/libunwind/tests/ppc64-test-altivec.c b/src/pal/src/libunwind/tests/ppc64-test-altivec.c
new file mode 100644
index 0000000000..a3e95eefbb
--- /dev/null
+++ b/src/pal/src/libunwind/tests/ppc64-test-altivec.c
@@ -0,0 +1,177 @@
+
+
+#include <libunwind.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <altivec.h>
+
+#include <sys/resource.h>
+
+#define panic(args...) { fprintf (stderr, args); abort(); }
+
+extern vector signed int vec_init ();
+extern void vec_print (vector signed int v);
+
+vector signed int vec_stack (int count);
+
+int
+main ()
+{
+ printf ("&vec_stack = %016lx\n", (unsigned long) vec_stack);
+ vec_stack (3);
+ return 0;
+}
+
+
+vector signed int
+vec_stack (int count)
+{
+ register vector signed int v1;
+ register vector signed int v2;
+ register vector signed int v3;
+ register vector signed int v4;
+ register vector signed int v5;
+ register vector signed int v6;
+ register vector signed int v7;
+ register vector signed int v8;
+ register vector signed int v9;
+
+ unw_fpreg_t vr;
+
+ unw_cursor_t cursor;
+ unw_word_t ip, sp;
+ unw_context_t uc;
+ int ret;
+ int verbose = 1;
+
+ /* if (count == 0) return vec_init(); */
+
+ if (count == 0)
+ {
+ unw_getcontext (&uc);
+ if (unw_init_local (&cursor, &uc) < 0)
+ {
+ panic ("unw_init_local failed!\n");
+ }
+ else
+ {
+ do
+ {
+ if ((ret = unw_get_reg (&cursor, UNW_REG_IP, &ip)) < 0)
+ {
+ panic ("FAILURE: unw_get_reg returned %d for UNW_REG_IP\n",
+ ret);
+ }
+ if ((ret = unw_get_reg (&cursor, UNW_REG_SP, &sp)) < 0)
+ {
+ panic ("FAILURE: unw_get_reg returned %d for UNW_REG_SP\n",
+ ret);
+ }
+ if ((ret = unw_get_fpreg (&cursor, UNW_PPC64_V30, &vr)) < 0)
+ {
+ panic
+ ("FAILURE: unw_get_vreg returned %d for UNW_PPC64_V30\n",
+ ret);
+ }
+
+
+ if (verbose)
+ {
+ const char *regname = unw_regname (UNW_PPC64_V30);
+ char proc_name_buffer[256];
+ unw_word_t offset;
+ unsigned int * vec_half1, * vec_half2;
+ vec_half1 = (unsigned int *)&vr;
+ vec_half2 = vec_half1 + 1;
+ printf ("ip = %016lx, sp=%016lx\n", (long) ip, (long) sp);
+ printf ("vr30 = %08x %08x %08x %08x\n",
+ (unsigned int) (*vec_half1 >> 16),
+ (unsigned int) (*vec_half1 & 0xffffffff),
+ (unsigned int) (*vec_half2 >> 16),
+ (unsigned int) (*vec_half2 & 0xffffffff));
+ ret =
+ unw_get_proc_name (&cursor, proc_name_buffer,
+ sizeof (proc_name_buffer), &offset);
+ if (ret == 0)
+ {
+ printf ("proc name = %s, offset = %lx\n",
+ proc_name_buffer, offset);
+ }
+ else
+ {
+ panic ("unw_get_proc_name returned %d\n", ret);
+ }
+ printf ("unw_regname(UNW_PPC_V30) = %s\n\n", regname);
+ }
+
+ ret = unw_step (&cursor);
+ if (ret < 0)
+ {
+ unw_get_reg (&cursor, UNW_REG_IP, &ip);
+ panic ("FAILURE: unw_step() returned %d for ip=%lx\n", ret,
+ (long) ip);
+ }
+ }
+ while (ret > 0);
+ }
+ }
+
+ v1 = vec_init ();
+ v2 = vec_init ();
+ v3 = vec_init ();
+ v4 = vec_init ();
+ v5 = vec_init ();
+ v6 = vec_init ();
+
+ /* make use of all of the registers in some calculation */
+ v7 =
+ vec_nor (v1, vec_add (v2, vec_sub (v3, vec_and (v4, vec_or (v5, v6)))));
+
+ /*
+ * "force" the registers to be non-volatile by making a call and also
+ * using the registers after the call.
+ */
+ v8 = vec_stack (count - 1);
+
+ /*
+ * Use the result from the previous call, plus all of the non-volatile
+ * registers in another calculation.
+ */
+ v9 =
+ vec_nor (v1,
+ vec_add (v2,
+ vec_sub (v3,
+ vec_and (v4, vec_or (v5, vec_xor (v6, v8))))));
+
+ printf ("v1 - ");
+ vec_print (v1);
+ printf ("\n");
+ printf ("v2 - ");
+ vec_print (v2);
+ printf ("\n");
+ printf ("v3 - ");
+ vec_print (v3);
+ printf ("\n");
+ printf ("v4 - ");
+ vec_print (v4);
+ printf ("\n");
+ printf ("v5 - ");
+ vec_print (v5);
+ printf ("\n");
+ printf ("v6 - ");
+ vec_print (v6);
+ printf ("\n");
+ printf ("v7 - ");
+ vec_print (v7);
+ printf ("\n");
+ printf ("v8 - ");
+ vec_print (v8);
+ printf ("\n");
+ printf ("v9 - ");
+ vec_print (v9);
+ printf ("\n");
+
+ return v9;
+}
diff --git a/src/pal/src/libunwind/tests/run-check-namespace b/src/pal/src/libunwind/tests/run-check-namespace
new file mode 100755
index 0000000000..d57c8642a2
--- /dev/null
+++ b/src/pal/src/libunwind/tests/run-check-namespace
@@ -0,0 +1,3 @@
+#!/bin/sh
+chmod +x ./check-namespace.sh
+./check-namespace.sh $*
diff --git a/src/pal/src/libunwind/tests/run-coredump-unwind b/src/pal/src/libunwind/tests/run-coredump-unwind
new file mode 100755
index 0000000000..8d07742574
--- /dev/null
+++ b/src/pal/src/libunwind/tests/run-coredump-unwind
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+# this function is slight modification of the one used in RPM
+# found at https://bugzilla.redhat.com/show_bug.cgi?id=834073
+# written by Alexander Larsson <alexl@redhat.com>
+add_minidebug()
+{
+ debuginfo="$1" ## we don't have separate debuginfo file
+ binary="$1"
+
+ dynsyms=`mktemp`
+ funcsyms=`mktemp`
+ keep_symbols=`mktemp`
+ mini_debuginfo=`mktemp`
+
+ # Extract the dynamic symbols from the main binary, there is no need to also have these
+ # in the normal symbol table
+ nm -D "$binary" --format=posix --defined-only | awk '{ print $1 }' | sort > "$dynsyms"
+ # Extract all the text (i.e. function) symbols from the debuginfo
+ nm "$debuginfo" --format=posix --defined-only | awk '{ if ($2 == "T" || $2 == "t") print $1 }' | sort > "$funcsyms"
+ # Keep all the function symbols not already in the dynamic symbol table
+ comm -13 "$dynsyms" "$funcsyms" > "$keep_symbols"
+ # Copy the full debuginfo, keeping only a minumal set of symbols and removing some unnecessary sections
+ objcopy -S --remove-section .gdb_index --remove-section .comment --keep-symbols="$keep_symbols" "$debuginfo" "$mini_debuginfo" &> /dev/null
+ #Inject the compressed data into the .gnu_debugdata section of the original binary
+ xz "$mini_debuginfo"
+ mini_debuginfo="${mini_debuginfo}.xz"
+ objcopy --add-section .gnu_debugdata="$mini_debuginfo" "$binary"
+ rm -f "$dynsyms" "$funcsyms" "$keep_symbols" "$mini_debuginfo"
+
+ strip "$binary" ## throw away the symbol table
+}
+
+
+TESTDIR=`pwd`
+TEMPDIR=`mktemp --tmpdir -d libunwind-test-XXXXXXXXXX`
+trap "rm -r -- $TEMPDIR" EXIT
+
+cp crasher $TEMPDIR/crasher
+if [ "$1" = "-minidebuginfo" ]; then
+ add_minidebug $TEMPDIR/crasher
+fi
+
+# create core dump
+(
+ cd $TEMPDIR
+ ulimit -c 10000
+ ./crasher backing_files
+) 2>/dev/null
+COREFILE=$TEMPDIR/core*
+
+# magic option -testcase enables checking for the specific contents of the stack
+./test-coredump-unwind $COREFILE -testcase `cat $TEMPDIR/backing_files`
diff --git a/src/pal/src/libunwind/tests/run-coredump-unwind-mdi b/src/pal/src/libunwind/tests/run-coredump-unwind-mdi
new file mode 100755
index 0000000000..d0a315b8e3
--- /dev/null
+++ b/src/pal/src/libunwind/tests/run-coredump-unwind-mdi
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# This test intends to test the unw_get_proc_name function on binaries without
+# the symbol table but with so called MiniDebuginfo available. In particular,
+# it is tested using the coredump accessors. For more info about MiniDebugInfo
+# see e.g. http://fedoraproject.org/wiki/Features/MiniDebugInfo
+
+${0%/*}/run-coredump-unwind -minidebuginfo
diff --git a/src/pal/src/libunwind/tests/run-ia64-test-dyn1 b/src/pal/src/libunwind/tests/run-ia64-test-dyn1
new file mode 100755
index 0000000000..acce944ca1
--- /dev/null
+++ b/src/pal/src/libunwind/tests/run-ia64-test-dyn1
@@ -0,0 +1,2 @@
+#!/bin/sh
+./test-ptrace -t ./ia64-test-dyn1
diff --git a/src/pal/src/libunwind/tests/run-ptrace-mapper b/src/pal/src/libunwind/tests/run-ptrace-mapper
new file mode 100755
index 0000000000..dc3010d4b3
--- /dev/null
+++ b/src/pal/src/libunwind/tests/run-ptrace-mapper
@@ -0,0 +1,2 @@
+#!/bin/sh
+./test-ptrace -c -n -t ./mapper $*
diff --git a/src/pal/src/libunwind/tests/run-ptrace-misc b/src/pal/src/libunwind/tests/run-ptrace-misc
new file mode 100755
index 0000000000..c3a6552f1d
--- /dev/null
+++ b/src/pal/src/libunwind/tests/run-ptrace-misc
@@ -0,0 +1,2 @@
+#!/bin/sh
+./test-ptrace -c -t ./test-ptrace-misc
diff --git a/src/pal/src/libunwind/tests/test-async-sig.c b/src/pal/src/libunwind/tests/test-async-sig.c
new file mode 100644
index 0000000000..2ce8b4bb71
--- /dev/null
+++ b/src/pal/src/libunwind/tests/test-async-sig.c
@@ -0,0 +1,193 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* Check whether basic unwinding truly is async-signal safe. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "compiler.h"
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/time.h>
+
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+
+static const int nerrors_max = 100;
+
+struct itimerval interval =
+ {
+ .it_interval = { .tv_sec = 0, .tv_usec = 0 },
+ .it_value = { .tv_sec = 0, .tv_usec = 1000 }
+ };
+
+int verbose;
+int nerrors;
+int sigcount;
+
+#ifndef CONFIG_BLOCK_SIGNALS
+/* When libunwind is configured with --enable-block-signals=no, the caller
+ is responsible for preventing recursion via signal handlers.
+ We use a simple global here. In a multithreaded program, one would use
+ a thread-local variable. */
+int recurcount;
+#endif
+
+#define panic(args...) \
+ { ++nerrors; fprintf (stderr, args); return; }
+
+static void
+do_backtrace (int may_print, int get_proc_name)
+{
+ char buf[512], name[256];
+ unw_cursor_t cursor;
+ unw_word_t ip, sp, off;
+ unw_context_t uc;
+ int ret;
+ int depth = 0;
+
+#ifndef CONFIG_BLOCK_SIGNALS
+ if (recurcount > 0)
+ return;
+ recurcount += 1;
+#endif
+
+ unw_getcontext (&uc);
+ if (unw_init_local (&cursor, &uc) < 0)
+ panic ("unw_init_local failed!\n");
+
+ do
+ {
+ unw_get_reg (&cursor, UNW_REG_IP, &ip);
+ unw_get_reg (&cursor, UNW_REG_SP, &sp);
+
+ buf[0] = '\0';
+ if (get_proc_name || (may_print && verbose))
+ {
+ ret = unw_get_proc_name (&cursor, name, sizeof (name), &off);
+ if (ret == 0 && (may_print && verbose))
+ {
+ if (off)
+ snprintf (buf, sizeof (buf), "<%s+0x%lx>", name, (long) off);
+ else
+ {
+ size_t len = strlen (name);
+ buf[0] = '<';
+ memcpy (buf + 1, name, len);
+ buf[len + 1] = '>';
+ buf[len + 2] = '\0';
+ }
+ }
+ }
+
+ if (may_print && verbose)
+ printf ("%016lx %-32s (sp=%016lx)\n", (long) ip, buf, (long) sp);
+
+ ret = unw_step (&cursor);
+ if (ret < 0)
+ {
+ unw_get_reg (&cursor, UNW_REG_IP, &ip);
+ panic ("FAILURE: unw_step() returned %d for ip=%lx\n",
+ ret, (long) ip);
+ }
+ if (depth++ > 100)
+ {
+ panic ("FAILURE: unw_step() looping over %d iterations\n", depth);
+ break;
+ }
+ }
+ while (ret > 0);
+
+#ifndef CONFIG_BLOCK_SIGNALS
+ recurcount -= 1;
+#endif
+}
+
+void
+sighandler (int signal)
+{
+ if (verbose)
+ printf ("sighandler(signal=%d, count=%d)\n", signal, sigcount);
+
+ do_backtrace (1, 1);
+
+ ++sigcount;
+
+ if (sigcount == 100)
+ unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_GLOBAL);
+ else if (sigcount == 200)
+ unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_PER_THREAD);
+ else if (sigcount == 300 || nerrors > nerrors_max)
+ {
+ if (nerrors > nerrors_max)
+ panic ("Too many errors (%d)\n", nerrors);
+ if (nerrors)
+ {
+ fprintf (stderr, "FAILURE: detected %d errors\n", nerrors);
+ exit (-1);
+ }
+ if (verbose)
+ printf ("SUCCESS.\n");
+ exit (0);
+ }
+ setitimer (ITIMER_VIRTUAL, &interval, NULL);
+}
+
+int
+main (int argc, char **argv UNUSED)
+{
+ struct sigaction act;
+ long i = 0;
+
+ if (argc > 1)
+ verbose = 1;
+
+ unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_NONE);
+
+ memset (&act, 0, sizeof (act));
+ act.sa_handler = sighandler;
+ act.sa_flags = SA_SIGINFO;
+ sigaction (SIGVTALRM, &act, NULL);
+
+ setitimer (ITIMER_VIRTUAL, &interval, NULL);
+
+ while (1)
+ {
+ if (0 && verbose)
+ printf ("%s: starting backtrace\n", __FUNCTION__);
+ do_backtrace (0, (i++ % 100) == 0);
+ if (nerrors > nerrors_max)
+ {
+ fprintf (stderr, "Too many errors (%d)\n", nerrors);
+ exit (-1);
+ }
+ }
+ return (0);
+}
diff --git a/src/pal/src/libunwind/tests/test-coredump-unwind.c b/src/pal/src/libunwind/tests/test-coredump-unwind.c
new file mode 100644
index 0000000000..53498237c2
--- /dev/null
+++ b/src/pal/src/libunwind/tests/test-coredump-unwind.c
@@ -0,0 +1,395 @@
+/*
+ * Example program for unwinding core dumps.
+ *
+ * Compile a-la:
+ * gcc -Os -Wall \
+ * -Wl,--start-group \
+ * -lunwind -lunwind-x86 -lunwind-coredump \
+ * example-core-unwind.c \
+ * -Wl,--end-group \
+ * -oexample-core-unwind
+ *
+ * Run:
+ * eu-unstrip -n --core COREDUMP
+ * figure out which virtual addresses in COREDUMP correspond to which mapped executable files
+ * (binary and libraries), then supply them like this:
+ * ./example-core-unwind COREDUMP 0x400000:/bin/crashed_program 0x3458600000:/lib/libc.so.6 [...]
+ *
+ * Note: Program eu-unstrip is part of elfutils, virtual addresses of shared
+ * libraries can be determined by ldd (at least on linux).
+ */
+
+#include "compiler.h"
+
+#undef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#undef __USE_GNU
+#define __USE_GNU 1
+
+#include <assert.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <string.h>
+#include <syslog.h>
+#include <sys/poll.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/param.h>
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <limits.h>
+#include <pwd.h>
+#include <grp.h>
+
+/* For SIGSEGV handler code */
+#include <execinfo.h>
+#include <sys/ucontext.h>
+
+#include <libunwind-coredump.h>
+
+
+/* Utility logging functions */
+
+enum {
+ LOGMODE_NONE = 0,
+ LOGMODE_STDIO = (1 << 0),
+ LOGMODE_SYSLOG = (1 << 1),
+ LOGMODE_BOTH = LOGMODE_SYSLOG + LOGMODE_STDIO,
+};
+const char *msg_prefix = "";
+const char *msg_eol = "\n";
+int logmode = LOGMODE_STDIO;
+int xfunc_error_retval = EXIT_FAILURE;
+
+void xfunc_die(void)
+{
+ exit(xfunc_error_retval);
+}
+
+static void verror_msg_helper(const char *s,
+ va_list p,
+ const char* strerr,
+ int flags)
+{
+ char *msg;
+ int prefix_len, strerr_len, msgeol_len, used;
+
+ if (!logmode)
+ return;
+
+ used = vasprintf(&msg, s, p);
+ if (used < 0)
+ return;
+
+ /* This is ugly and costs +60 bytes compared to multiple
+ * fprintf's, but is guaranteed to do a single write.
+ * This is needed for e.g. when multiple children
+ * can produce log messages simultaneously. */
+
+ prefix_len = msg_prefix[0] ? strlen(msg_prefix) + 2 : 0;
+ strerr_len = strerr ? strlen(strerr) : 0;
+ msgeol_len = strlen(msg_eol);
+ /* +3 is for ": " before strerr and for terminating NUL */
+ char *msg1 = (char*) realloc(msg, prefix_len + used + strerr_len + msgeol_len + 3);
+ if (!msg1)
+ {
+ free(msg);
+ return;
+ }
+ msg = msg1;
+ /* TODO: maybe use writev instead of memmoving? Need full_writev? */
+ if (prefix_len)
+ {
+ char *p;
+ memmove(msg + prefix_len, msg, used);
+ used += prefix_len;
+ p = stpcpy(msg, msg_prefix);
+ p[0] = ':';
+ p[1] = ' ';
+ }
+ if (strerr)
+ {
+ if (s[0])
+ {
+ msg[used++] = ':';
+ msg[used++] = ' ';
+ }
+ strcpy(&msg[used], strerr);
+ used += strerr_len;
+ }
+ strcpy(&msg[used], msg_eol);
+
+ if (flags & LOGMODE_STDIO)
+ {
+ fflush(stdout);
+ write(STDERR_FILENO, msg, used + msgeol_len);
+ }
+ msg[used] = '\0'; /* remove msg_eol (usually "\n") */
+ if (flags & LOGMODE_SYSLOG)
+ {
+ syslog(LOG_ERR, "%s", msg + prefix_len);
+ }
+ free(msg);
+}
+
+void log_msg(const char *s, ...)
+{
+ va_list p;
+ va_start(p, s);
+ verror_msg_helper(s, p, NULL, logmode);
+ va_end(p);
+}
+/* It's a macro, not function, since it collides with log() from math.h */
+#undef log
+#define log(...) log_msg(__VA_ARGS__)
+
+void error_msg(const char *s, ...)
+{
+ va_list p;
+ va_start(p, s);
+ verror_msg_helper(s, p, NULL, logmode);
+ va_end(p);
+}
+
+void error_msg_and_die(const char *s, ...)
+{
+ va_list p;
+ va_start(p, s);
+ verror_msg_helper(s, p, NULL, logmode);
+ va_end(p);
+ xfunc_die();
+}
+
+void perror_msg(const char *s, ...)
+{
+ va_list p;
+ va_start(p, s);
+ /* Guard against "<error message>: Success" */
+ verror_msg_helper(s, p, errno ? strerror(errno) : NULL, logmode);
+ va_end(p);
+}
+
+void perror_msg_and_die(const char *s, ...)
+{
+ va_list p;
+ va_start(p, s);
+ /* Guard against "<error message>: Success" */
+ verror_msg_helper(s, p, errno ? strerror(errno) : NULL, logmode);
+ va_end(p);
+ xfunc_die();
+}
+
+void die_out_of_memory(void)
+{
+ error_msg_and_die("Out of memory, exiting");
+}
+
+/* End of utility logging functions */
+
+
+
+static
+void handle_sigsegv(int sig, siginfo_t *info, void *ucontext)
+{
+ long ip = 0;
+ ucontext_t *uc UNUSED;
+
+ uc = ucontext;
+#if defined(__linux__)
+#ifdef UNW_TARGET_X86
+ ip = uc->uc_mcontext.gregs[REG_EIP];
+#elif defined(UNW_TARGET_X86_64)
+ ip = uc->uc_mcontext.gregs[REG_RIP];
+#elif defined(UNW_TARGET_ARM)
+ ip = uc->uc_mcontext.arm_pc;
+#endif
+#elif defined(__FreeBSD__)
+#ifdef __i386__
+ ip = uc->uc_mcontext.mc_eip;
+#elif defined(__amd64__)
+ ip = uc->uc_mcontext.mc_rip;
+#else
+#error Port me
+#endif
+#else
+#error Port me
+#endif
+ dprintf(2, "signal:%d address:0x%lx ip:0x%lx\n",
+ sig,
+ /* this is void*, but using %p would print "(null)"
+ * even for ptrs which are not exactly 0, but, say, 0x123:
+ */
+ (long)info->si_addr,
+ ip);
+
+ {
+ /* glibc extension */
+ void *array[50];
+ int size;
+ size = backtrace(array, 50);
+#ifdef __linux__
+ backtrace_symbols_fd(array, size, 2);
+#endif
+ }
+
+ _exit(1);
+}
+
+static void install_sigsegv_handler(void)
+{
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_sigaction = handle_sigsegv;
+ sa.sa_flags = SA_SIGINFO;
+ sigaction(SIGSEGV, &sa, NULL);
+ sigaction(SIGILL, &sa, NULL);
+ sigaction(SIGFPE, &sa, NULL);
+ sigaction(SIGBUS, &sa, NULL);
+}
+
+int
+main(int argc UNUSED, char **argv)
+{
+ unw_addr_space_t as;
+ struct UCD_info *ui;
+ unw_cursor_t c;
+ int ret;
+
+#define TEST_FRAMES 4
+#define TEST_NAME_LEN 32
+ int testcase = 0;
+ int test_cur = 0;
+ long test_start_ips[TEST_FRAMES];
+ char test_names[TEST_FRAMES][TEST_NAME_LEN];
+
+ install_sigsegv_handler();
+
+ const char *progname = strrchr(argv[0], '/');
+ if (progname)
+ progname++;
+ else
+ progname = argv[0];
+
+ if (!argv[1])
+ error_msg_and_die("Usage: %s COREDUMP [VADDR:BINARY_FILE]...", progname);
+
+ msg_prefix = progname;
+
+ as = unw_create_addr_space(&_UCD_accessors, 0);
+ if (!as)
+ error_msg_and_die("unw_create_addr_space() failed");
+
+ ui = _UCD_create(argv[1]);
+ if (!ui)
+ error_msg_and_die("_UCD_create('%s') failed", argv[1]);
+ ret = unw_init_remote(&c, as, ui);
+ if (ret < 0)
+ error_msg_and_die("unw_init_remote() failed: ret=%d\n", ret);
+
+ argv += 2;
+
+ /* Enable checks for the crasher test program? */
+ if (*argv && !strcmp(*argv, "-testcase"))
+ {
+ testcase = 1;
+ logmode = LOGMODE_NONE;
+ argv++;
+ }
+
+ while (*argv)
+ {
+ char *colon;
+ unsigned long vaddr = strtoul(*argv, &colon, 16);
+ if (*colon != ':')
+ error_msg_and_die("Bad format: '%s'", *argv);
+ if (_UCD_add_backing_file_at_vaddr(ui, vaddr, colon + 1) < 0)
+ error_msg_and_die("Can't add backing file '%s'", colon + 1);
+ argv++;
+ }
+
+ for (;;)
+ {
+ unw_word_t ip;
+ ret = unw_get_reg(&c, UNW_REG_IP, &ip);
+ if (ret < 0)
+ error_msg_and_die("unw_get_reg(UNW_REG_IP) failed: ret=%d\n", ret);
+
+ unw_proc_info_t pi;
+ ret = unw_get_proc_info(&c, &pi);
+ if (ret < 0)
+ error_msg_and_die("unw_get_proc_info(ip=0x%lx) failed: ret=%d\n", (long) ip, ret);
+
+ if (!testcase)
+ printf("\tip=0x%08lx proc=%08lx-%08lx handler=0x%08lx lsda=0x%08lx\n",
+ (long) ip,
+ (long) pi.start_ip, (long) pi.end_ip,
+ (long) pi.handler, (long) pi.lsda);
+
+ if (testcase && test_cur < TEST_FRAMES)
+ {
+ unw_word_t off;
+
+ test_start_ips[test_cur] = (long) pi.start_ip;
+ if (unw_get_proc_name(&c, test_names[test_cur], sizeof(test_names[0]), &off) != 0)
+ {
+ test_names[test_cur][0] = '\0';
+ }
+ test_cur++;
+ }
+
+ log("step");
+ ret = unw_step(&c);
+ log("step done:%d", ret);
+ if (ret < 0)
+ error_msg_and_die("FAILURE: unw_step() returned %d", ret);
+ if (ret == 0)
+ break;
+ }
+ log("stepping ended");
+
+ /* Check that the second and third frames are equal, but distinct of the
+ * others */
+ if (testcase &&
+ (test_cur != 4
+ || test_start_ips[1] != test_start_ips[2]
+ || test_start_ips[0] == test_start_ips[1]
+ || test_start_ips[2] == test_start_ips[3]
+ )
+ )
+ {
+ fprintf(stderr, "FAILURE: start IPs incorrect\n");
+ return -1;
+ }
+
+ if (testcase &&
+ ( strcmp(test_names[0], "a")
+ || strcmp(test_names[1], "b")
+ || strcmp(test_names[2], "b")
+ || strcmp(test_names[3], "main")
+ )
+ )
+ {
+ fprintf(stderr, "FAILURE: procedure names are missing/incorrect\n");
+ return -1;
+ }
+
+ _UCD_destroy(ui);
+ unw_destroy_addr_space(as);
+
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/test-flush-cache.c b/src/pal/src/libunwind/tests/test-flush-cache.c
new file mode 100644
index 0000000000..1611cf48ef
--- /dev/null
+++ b/src/pal/src/libunwind/tests/test-flush-cache.c
@@ -0,0 +1,143 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Copyright (c) 2003 Hewlett-Packard Co.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdio.h>
+#include <string.h>
+
+#define UNW_LOCAL_ONLY /* must define this for consistency with backtrace() */
+#include <libunwind.h>
+
+int verbose;
+
+int
+f257 (void)
+{
+ void *buffer[300];
+ int i, n;
+
+ if (verbose)
+ printf ("First backtrace:\n");
+ n = unw_backtrace (buffer, 300);
+ if (verbose)
+ for (i = 0; i < n; ++i)
+ printf ("[%d] ip=%p\n", i, buffer[i]);
+
+ unw_set_cache_size (unw_local_addr_space, 1023, 0);
+ unw_flush_cache (unw_local_addr_space, 0, 0);
+
+ if (verbose)
+ printf ("\nSecond backtrace:\n");
+ n = unw_backtrace (buffer, 300);
+ if (verbose)
+ for (i = 0; i < n; ++i)
+ printf ("[%d] ip=%p\n", i, buffer[i]);
+ return 0;
+}
+
+#define F(n,m) \
+int \
+f##n (void) \
+{ \
+ return f##m (); \
+}
+
+/* Here, we rely on the fact that the script-cache's hash-table is 256
+ entries big. With 257 functions, we're guaranteed to get at least
+ one hash-collision. */
+F(256,257) F(255,256) F(254,255) F(253,254)
+F(252,253) F(251,252) F(250,251) F(249,250)
+F(248,249) F(247,248) F(246,247) F(245,246)
+F(244,245) F(243,244) F(242,243) F(241,242)
+F(240,241) F(239,240) F(238,239) F(237,238)
+F(236,237) F(235,236) F(234,235) F(233,234)
+F(232,233) F(231,232) F(230,231) F(229,230)
+F(228,229) F(227,228) F(226,227) F(225,226)
+F(224,225) F(223,224) F(222,223) F(221,222)
+F(220,221) F(219,220) F(218,219) F(217,218)
+F(216,217) F(215,216) F(214,215) F(213,214)
+F(212,213) F(211,212) F(210,211) F(209,210)
+F(208,209) F(207,208) F(206,207) F(205,206)
+F(204,205) F(203,204) F(202,203) F(201,202)
+F(200,201) F(199,200) F(198,199) F(197,198)
+F(196,197) F(195,196) F(194,195) F(193,194)
+F(192,193) F(191,192) F(190,191) F(189,190)
+F(188,189) F(187,188) F(186,187) F(185,186)
+F(184,185) F(183,184) F(182,183) F(181,182)
+F(180,181) F(179,180) F(178,179) F(177,178)
+F(176,177) F(175,176) F(174,175) F(173,174)
+F(172,173) F(171,172) F(170,171) F(169,170)
+F(168,169) F(167,168) F(166,167) F(165,166)
+F(164,165) F(163,164) F(162,163) F(161,162)
+F(160,161) F(159,160) F(158,159) F(157,158)
+F(156,157) F(155,156) F(154,155) F(153,154)
+F(152,153) F(151,152) F(150,151) F(149,150)
+F(148,149) F(147,148) F(146,147) F(145,146)
+F(144,145) F(143,144) F(142,143) F(141,142)
+F(140,141) F(139,140) F(138,139) F(137,138)
+F(136,137) F(135,136) F(134,135) F(133,134)
+F(132,133) F(131,132) F(130,131) F(129,130)
+F(128,129) F(127,128) F(126,127) F(125,126)
+F(124,125) F(123,124) F(122,123) F(121,122)
+F(120,121) F(119,120) F(118,119) F(117,118)
+F(116,117) F(115,116) F(114,115) F(113,114)
+F(112,113) F(111,112) F(110,111) F(109,110)
+F(108,109) F(107,108) F(106,107) F(105,106)
+F(104,105) F(103,104) F(102,103) F(101,102)
+F(100,101) F(99,100) F(98,99) F(97,98)
+F(96,97) F(95,96) F(94,95) F(93,94)
+F(92,93) F(91,92) F(90,91) F(89,90)
+F(88,89) F(87,88) F(86,87) F(85,86)
+F(84,85) F(83,84) F(82,83) F(81,82)
+F(80,81) F(79,80) F(78,79) F(77,78)
+F(76,77) F(75,76) F(74,75) F(73,74)
+F(72,73) F(71,72) F(70,71) F(69,70)
+F(68,69) F(67,68) F(66,67) F(65,66)
+F(64,65) F(63,64) F(62,63) F(61,62)
+F(60,61) F(59,60) F(58,59) F(57,58)
+F(56,57) F(55,56) F(54,55) F(53,54)
+F(52,53) F(51,52) F(50,51) F(49,50)
+F(48,49) F(47,48) F(46,47) F(45,46)
+F(44,45) F(43,44) F(42,43) F(41,42)
+F(40,41) F(39,40) F(38,39) F(37,38)
+F(36,37) F(35,36) F(34,35) F(33,34)
+F(32,33) F(31,32) F(30,31) F(29,30)
+F(28,29) F(27,28) F(26,27) F(25,26)
+F(24,25) F(23,24) F(22,23) F(21,22)
+F(20,21) F(19,20) F(18,19) F(17,18)
+F(16,17) F(15,16) F(14,15) F(13,14)
+F(12,13) F(11,12) F(10,11) F(9,10)
+F(8,9) F(7,8) F(6,7) F(5,6)
+F(4,5) F(3,4) F(2,3) F(1,2)
+
+int
+main (int argc, char **argv)
+{
+ if (argc > 1 && strcmp (argv[1], "-v") == 0)
+ verbose = 1;
+
+ return f1 ();
+}
diff --git a/src/pal/src/libunwind/tests/test-init-remote.c b/src/pal/src/libunwind/tests/test-init-remote.c
new file mode 100644
index 0000000000..66f2d6a1e0
--- /dev/null
+++ b/src/pal/src/libunwind/tests/test-init-remote.c
@@ -0,0 +1,103 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Copyright (c) 2002 Hewlett-Packard Co.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* This test simply verifies that unw_init_remote() can be used in
+ lieu of unw_init_local(). This was broken for a while on ia64. */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "compiler.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libunwind.h>
+
+#define panic(args...) \
+ { fprintf (stderr, args); exit (-1); }
+
+int verbose;
+
+static int
+do_backtrace (void)
+{
+ char buf[512], name[256];
+ unw_word_t ip, sp, off;
+ unw_cursor_t cursor;
+ unw_context_t uc;
+ int ret;
+
+ unw_getcontext (&uc);
+ if (unw_init_remote (&cursor, unw_local_addr_space, &uc) < 0)
+ panic ("unw_init_remote failed!\n");
+
+ do
+ {
+ unw_get_reg (&cursor, UNW_REG_IP, &ip);
+ unw_get_reg (&cursor, UNW_REG_SP, &sp);
+ buf[0] = '\0';
+ if (unw_get_proc_name (&cursor, name, sizeof (name), &off) == 0)
+ {
+ if (off)
+ snprintf (buf, sizeof (buf), "<%s+0x%lx>", name, (long) off);
+ else
+ snprintf (buf, sizeof (buf), "<%s>", name);
+ }
+ if (verbose)
+ printf ("%016lx %-32s (sp=%016lx)\n", (long) ip, buf, (long) sp);
+
+ ret = unw_step (&cursor);
+ if (ret < 0)
+ {
+ unw_get_reg (&cursor, UNW_REG_IP, &ip);
+ printf ("FAILURE: unw_step() returned %d for ip=%lx\n",
+ ret, (long) ip);
+ return -1;
+ }
+ }
+ while (ret > 0);
+
+ return 0;
+}
+
+static int
+foo (void)
+{
+ return do_backtrace ();
+}
+
+int
+main (int argc, char **argv UNUSED)
+{
+ verbose = (argc > 1);
+
+ if (verbose)
+ printf ("Normal backtrace:\n");
+ return foo ();
+}
diff --git a/src/pal/src/libunwind/tests/test-mem.c b/src/pal/src/libunwind/tests/test-mem.c
new file mode 100644
index 0000000000..52c977488a
--- /dev/null
+++ b/src/pal/src/libunwind/tests/test-mem.c
@@ -0,0 +1,103 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Copyright (c) 2003 Hewlett-Packard Co.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "compiler.h"
+
+#include <libunwind.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/resource.h>
+
+#define panic(args...) \
+ { fprintf (stderr, args); exit (-1); }
+
+int verbose;
+
+static void
+do_backtrace (void)
+{
+ unw_cursor_t cursor;
+ unw_word_t ip, sp;
+ unw_context_t uc;
+ int ret;
+
+ unw_getcontext (&uc);
+ if (unw_init_local (&cursor, &uc) < 0)
+ panic ("unw_init_local failed!\n");
+
+ do
+ {
+ unw_get_reg (&cursor, UNW_REG_IP, &ip);
+ unw_get_reg (&cursor, UNW_REG_SP, &sp);
+
+ if (verbose)
+ printf ("%016lx (sp=%016lx)\n", (long) ip, (long) sp);
+
+ ret = unw_step (&cursor);
+ if (ret < 0)
+ {
+ unw_get_reg (&cursor, UNW_REG_IP, &ip);
+ panic ("FAILURE: unw_step() returned %d for ip=%lx\n",
+ ret, (long) ip);
+ }
+ }
+ while (ret > 0);
+}
+
+int
+consume_some_stack_space (void)
+{
+ unw_cursor_t cursor;
+ unw_context_t uc;
+ char string[1024];
+
+ memset (&cursor, 0, sizeof (cursor));
+ memset (&uc, 0, sizeof (uc));
+ return sprintf (string, "hello %p %p\n", &cursor, &uc);
+}
+
+int
+main (int argc, char **argv UNUSED)
+{
+ struct rlimit rlim;
+
+ verbose = argc > 1;
+
+ if (consume_some_stack_space () > 9999)
+ exit (-1); /* can't happen, but don't let the compiler know... */
+
+ rlim.rlim_cur = 0;
+ rlim.rlim_max = RLIM_INFINITY;
+ setrlimit (RLIMIT_DATA, &rlim);
+ setrlimit (RLIMIT_AS, &rlim);
+
+ do_backtrace ();
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/test-proc-info.c b/src/pal/src/libunwind/tests/test-proc-info.c
new file mode 100644
index 0000000000..c4145bc374
--- /dev/null
+++ b/src/pal/src/libunwind/tests/test-proc-info.c
@@ -0,0 +1,171 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Copyright (c) 2003 Hewlett-Packard Co.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* This test program checks whether proc_info lookup failures are
+ cached. They must NOT be cached because it could otherwise turn
+ temporary failures into permanent ones. Furthermore, we allow apps
+ to return -UNW_ESTOPUNWIND to terminate unwinding (though this
+ feature is deprecated and dynamic unwind info should be used
+ instead). */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <libunwind.h>
+#include "compiler.h"
+
+int errors;
+
+#define panic(args...) \
+ { ++errors; fprintf (stderr, args); return -1; }
+
+static int
+find_proc_info (unw_addr_space_t as UNUSED,
+ unw_word_t ip UNUSED,
+ unw_proc_info_t *pip UNUSED,
+ int need_unwind_info UNUSED,
+ void *arg UNUSED)
+{
+ return -UNW_ESTOPUNWIND;
+}
+
+static int
+access_mem (unw_addr_space_t as UNUSED,
+ unw_word_t addr UNUSED,
+ unw_word_t *valp, int write,
+ void *arg UNUSED)
+{
+ if (!write)
+ *valp = 0;
+ return 0;
+}
+
+static int
+access_reg (unw_addr_space_t as UNUSED,
+ unw_regnum_t regnum UNUSED,
+ unw_word_t *valp, int write,
+ void *arg UNUSED)
+{
+ if (!write)
+ *valp = 32;
+ return 0;
+}
+
+static int
+access_fpreg (unw_addr_space_t as UNUSED,
+ unw_regnum_t regnum UNUSED,
+ unw_fpreg_t *valp, int write,
+ void *arg UNUSED)
+{
+ if (!write)
+ memset (valp, 0, sizeof (*valp));
+ return 0;
+}
+
+static int
+get_dyn_info_list_addr (unw_addr_space_t as UNUSED,
+ unw_word_t *dilap UNUSED,
+ void *arg UNUSED)
+{
+ return -UNW_ENOINFO;
+}
+
+static void
+put_unwind_info (unw_addr_space_t as UNUSED,
+ unw_proc_info_t *pi UNUSED,
+ void *arg UNUSED)
+{
+ ++errors;
+ fprintf (stderr, "%s() got called!\n", __FUNCTION__);
+}
+
+static int
+resume (unw_addr_space_t as UNUSED,
+ unw_cursor_t *reg UNUSED,
+ void *arg UNUSED)
+{
+ panic ("%s() got called!\n", __FUNCTION__);
+}
+
+static int
+get_proc_name (unw_addr_space_t as UNUSED,
+ unw_word_t ip UNUSED,
+ char *buf UNUSED,
+ size_t buf_len UNUSED,
+ unw_word_t *offp UNUSED,
+ void *arg UNUSED)
+{
+ panic ("%s() got called!\n", __FUNCTION__);
+}
+
+int
+main (int argc, char **argv)
+{
+ unw_accessors_t acc;
+ unw_addr_space_t as;
+ int ret, verbose = 0;
+ unw_cursor_t c;
+
+ if (argc > 1 && strcmp (argv[1], "-v") == 0)
+ verbose = 1;
+
+ memset (&acc, 0, sizeof (acc));
+ acc.find_proc_info = find_proc_info;
+ acc.put_unwind_info = put_unwind_info;
+ acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
+ acc.access_mem = access_mem;
+ acc.access_reg = access_reg;
+ acc.access_fpreg = access_fpreg;
+ acc.resume = resume;
+ acc.get_proc_name = get_proc_name;
+
+ as = unw_create_addr_space (&acc, 0);
+ if (!as)
+ panic ("unw_create_addr_space() failed\n");
+
+ unw_set_caching_policy (as, UNW_CACHE_GLOBAL);
+
+ ret = unw_init_remote (&c, as, NULL);
+ if (ret < 0)
+ panic ("unw_init_remote() returned %d instead of 0\n", ret);
+
+ ret = unw_step (&c);
+ if (ret != -UNW_ESTOPUNWIND)
+ panic ("First call to unw_step() returned %d instead of %d\n",
+ ret, -UNW_ESTOPUNWIND);
+
+ ret = unw_step (&c);
+ if (ret != -UNW_ESTOPUNWIND)
+ panic ("Second call to unw_step() returned %d instead of %d\n",
+ ret, -UNW_ESTOPUNWIND);
+
+ unw_destroy_addr_space (as);
+
+ if (verbose)
+ printf ("SUCCESS\n");
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/test-ptrace-misc.c b/src/pal/src/libunwind/tests/test-ptrace-misc.c
new file mode 100644
index 0000000000..374059dc44
--- /dev/null
+++ b/src/pal/src/libunwind/tests/test-ptrace-misc.c
@@ -0,0 +1,120 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "compiler.h"
+
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+
+pid_t self;
+int global[64];
+
+int
+func (int arg)
+{
+ int sum = 0, i, max, arr[1024];
+
+ if (arg == 0)
+ {
+ sum = global[2];
+ sum += sum + sum * getppid ();
+ return sum;
+ }
+ else
+ {
+ max = arg;
+ if (max >= 64)
+ max = 64;
+
+ for (i = 0; i < max; ++i)
+ arr[i] = func (arg - 1);
+
+ for (i = 0; i < max; ++i)
+ if (arr[i] > 16)
+ sum += arr[i];
+ else
+ sum -= arr[i];
+ }
+ return sum;
+}
+
+int
+bar (int v)
+{
+ extern long f (long);
+ int arr[1] = { v };
+ uintptr_t r;
+
+ /* This is a vain attempt to use up lots of registers to force
+ the frame-chain info to be saved on the memory stack on ia64.
+ It happens to work with gcc v3.3.4 and gcc v3.4.1 but perhaps
+ not with any other compiler. */
+ r = (uintptr_t) malloc(f (arr[0])
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
+ + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + f (v))
+ ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+ )))))))))))))))))))))))))))))))))))))))))))))))))))))));
+ if (r < 2)
+ v = r;
+
+ kill (self, SIGUSR1); /* tell test-ptrace to start single-stepping */
+ v = func (v);
+ kill (self, SIGUSR2); /* tell test-ptrace to stop single-stepping */
+ return v;
+}
+
+int
+main (int argc, char **argv UNUSED)
+{
+ int val = argc;
+
+ signal (SIGUSR1, SIG_IGN);
+ signal (SIGUSR2, SIG_IGN);
+
+ self = getpid ();
+
+ printf ("sum = %d\n", bar (val));
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/test-ptrace.c b/src/pal/src/libunwind/tests/test-ptrace.c
new file mode 100644
index 0000000000..e7c7883f38
--- /dev/null
+++ b/src/pal/src/libunwind/tests/test-ptrace.c
@@ -0,0 +1,370 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <config.h>
+
+#ifdef HAVE_TTRACE
+
+int
+main (void)
+{
+ printf ("FAILURE: ttrace() not supported yet\n");
+ return -1;
+}
+
+#else /* !HAVE_TTRACE */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <libunwind-ptrace.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+
+extern char **environ;
+
+static const int nerrors_max = 100;
+
+int nerrors;
+int verbose;
+int print_names = 1;
+
+enum
+ {
+ INSTRUCTION,
+ SYSCALL,
+ TRIGGER
+ }
+trace_mode = SYSCALL;
+
+#define panic(args...) \
+ do { fprintf (stderr, args); ++nerrors; } while (0)
+
+static unw_addr_space_t as;
+static struct UPT_info *ui;
+
+static int killed;
+
+void
+do_backtrace (void)
+{
+ unw_word_t ip, sp, start_ip = 0, off;
+ int n = 0, ret;
+ unw_proc_info_t pi;
+ unw_cursor_t c;
+ char buf[512];
+ size_t len;
+
+ ret = unw_init_remote (&c, as, ui);
+ if (ret < 0)
+ panic ("unw_init_remote() failed: ret=%d\n", ret);
+
+ do
+ {
+ if ((ret = unw_get_reg (&c, UNW_REG_IP, &ip)) < 0
+ || (ret = unw_get_reg (&c, UNW_REG_SP, &sp)) < 0)
+ panic ("unw_get_reg/unw_get_proc_name() failed: ret=%d\n", ret);
+
+ if (n == 0)
+ start_ip = ip;
+
+ buf[0] = '\0';
+ if (print_names)
+ unw_get_proc_name (&c, buf, sizeof (buf), &off);
+
+ if (verbose)
+ {
+ if (off)
+ {
+ len = strlen (buf);
+ if (len >= sizeof (buf) - 32)
+ len = sizeof (buf) - 32;
+ sprintf (buf + len, "+0x%lx", (unsigned long) off);
+ }
+ printf ("%016lx %-32s (sp=%016lx)\n", (long) ip, buf, (long) sp);
+ }
+
+ if ((ret = unw_get_proc_info (&c, &pi)) < 0)
+ panic ("unw_get_proc_info(ip=0x%lx) failed: ret=%d\n", (long) ip, ret);
+ else if (verbose)
+ printf ("\tproc=%016lx-%016lx\n\thandler=%lx lsda=%lx",
+ (long) pi.start_ip, (long) pi.end_ip,
+ (long) pi.handler, (long) pi.lsda);
+
+#if UNW_TARGET_IA64
+ {
+ unw_word_t bsp;
+
+ if ((ret = unw_get_reg (&c, UNW_IA64_BSP, &bsp)) < 0)
+ panic ("unw_get_reg() failed: ret=%d\n", ret);
+ else if (verbose)
+ printf (" bsp=%lx", bsp);
+ }
+#endif
+ if (verbose)
+ printf ("\n");
+
+ ret = unw_step (&c);
+ if (ret < 0)
+ {
+ unw_get_reg (&c, UNW_REG_IP, &ip);
+ panic ("FAILURE: unw_step() returned %d for ip=%lx (start ip=%lx)\n",
+ ret, (long) ip, (long) start_ip);
+ }
+
+ if (++n > 64)
+ {
+ /* guard against bad unwind info in old libraries... */
+ panic ("too deeply nested---assuming bogus unwind (start ip=%lx)\n",
+ (long) start_ip);
+ break;
+ }
+ if (nerrors > nerrors_max)
+ {
+ panic ("Too many errors (%d)!\n", nerrors);
+ break;
+ }
+ }
+ while (ret > 0);
+
+ if (ret < 0)
+ panic ("unwind failed with ret=%d\n", ret);
+
+ if (verbose)
+ printf ("================\n\n");
+}
+
+static pid_t target_pid;
+static void target_pid_kill (void)
+{
+ kill (target_pid, SIGKILL);
+}
+
+int
+main (int argc, char **argv)
+{
+ int status, pid, pending_sig, optind = 1, state = 1;
+
+ as = unw_create_addr_space (&_UPT_accessors, 0);
+ if (!as)
+ panic ("unw_create_addr_space() failed");
+
+ if (argc == 1)
+ {
+ static char *args[] = { "self", "/bin/ls", "/usr", NULL };
+
+ /* automated test case */
+ argv = args;
+
+ /* Unless the args array is 'walked' the child
+ process is unable to access it and dies with a segfault */
+ fprintf(stderr, "Automated test (%s,%s,%s,%s)\n",
+ args[0],args[1],args[2],args[3]);
+ }
+ else if (argc > 1)
+ while (argv[optind][0] == '-')
+ {
+ if (strcmp (argv[optind], "-v") == 0)
+ ++optind, verbose = 1;
+ else if (strcmp (argv[optind], "-i") == 0)
+ ++optind, trace_mode = INSTRUCTION; /* backtrace at each insn */
+ else if (strcmp (argv[optind], "-s") == 0)
+ ++optind, trace_mode = SYSCALL; /* backtrace at each syscall */
+ else if (strcmp (argv[optind], "-t") == 0)
+ /* Execute until raise(SIGUSR1), then backtrace at each insn
+ until raise(SIGUSR2). */
+ ++optind, trace_mode = TRIGGER;
+ else if (strcmp (argv[optind], "-c") == 0)
+ /* Enable caching of unwind-info. */
+ ++optind, unw_set_caching_policy (as, UNW_CACHE_GLOBAL);
+ else if (strcmp (argv[optind], "-n") == 0)
+ /* Don't look-up and print symbol names. */
+ ++optind, print_names = 0;
+ else
+ fprintf(stderr, "unrecognized option: %s\n", argv[optind++]);
+ if (optind >= argc)
+ break;
+ }
+
+ target_pid = fork ();
+ if (!target_pid)
+ {
+ /* child */
+
+ if (!verbose)
+ dup2 (open ("/dev/null", O_WRONLY), 1);
+
+#if HAVE_DECL_PTRACE_TRACEME
+ ptrace (PTRACE_TRACEME, 0, 0, 0);
+#elif HAVE_DECL_PT_TRACE_ME
+ ptrace (PT_TRACE_ME, 0, 0, 0);
+#else
+#error Trace me
+#endif
+
+ if ((argc > 1) && (optind == argc)) {
+ fprintf(stderr, "Need to specify a command line for the child\n");
+ exit (-1);
+ }
+ execve (argv[optind], argv + optind, environ);
+ _exit (-1);
+ }
+ atexit (target_pid_kill);
+
+ ui = _UPT_create (target_pid);
+
+ while (nerrors <= nerrors_max)
+ {
+ pid = wait4 (-1, &status, 0, NULL);
+ if (pid == -1)
+ {
+ if (errno == EINTR)
+ continue;
+
+ panic ("wait4() failed (errno=%d)\n", errno);
+ }
+ pending_sig = 0;
+ if (WIFSIGNALED (status) || WIFEXITED (status)
+ || (WIFSTOPPED (status) && WSTOPSIG (status) != SIGTRAP))
+ {
+ if (WIFEXITED (status))
+ {
+ if (WEXITSTATUS (status) != 0)
+ panic ("child's exit status %d\n", WEXITSTATUS (status));
+ break;
+ }
+ else if (WIFSIGNALED (status))
+ {
+ if (!killed)
+ panic ("child terminated by signal %d\n", WTERMSIG (status));
+ break;
+ }
+ else
+ {
+ pending_sig = WSTOPSIG (status);
+ /* Avoid deadlock: */
+ if (WSTOPSIG (status) == SIGKILL)
+ break;
+ if (trace_mode == TRIGGER)
+ {
+ if (WSTOPSIG (status) == SIGUSR1)
+ state = 0;
+ else if (WSTOPSIG (status) == SIGUSR2)
+ state = 1;
+ }
+ if (WSTOPSIG (status) != SIGUSR1 && WSTOPSIG (status) != SIGUSR2)
+ {
+ static int count = 0;
+
+ if (count++ > 100)
+ {
+ panic ("Too many child unexpected signals (now %d)\n",
+ WSTOPSIG (status));
+ killed = 1;
+ }
+ }
+ }
+ }
+
+ switch (trace_mode)
+ {
+ case TRIGGER:
+ if (state)
+#if HAVE_DECL_PTRACE_CONT
+ ptrace (PTRACE_CONT, target_pid, 0, 0);
+#elif HAVE_DECL_PT_CONTINUE
+ ptrace (PT_CONTINUE, target_pid, (caddr_t)1, 0);
+#else
+#error Port me
+#endif
+ else
+ {
+ do_backtrace ();
+#if HAVE_DECL_PTRACE_SINGLESTEP
+ if (ptrace (PTRACE_SINGLESTEP, target_pid, 0, pending_sig) < 0)
+ {
+ panic ("ptrace(PTRACE_SINGLESTEP) failed (errno=%d)\n", errno);
+ killed = 1;
+ }
+#elif HAVE_DECL_PT_STEP
+ if (ptrace (PT_STEP, target_pid, (caddr_t)1, pending_sig) < 0)
+ {
+ panic ("ptrace(PT_STEP) failed (errno=%d)\n", errno);
+ killed = 1;
+ }
+#else
+#error Singlestep me
+#endif
+ }
+ break;
+
+ case SYSCALL:
+ if (!state)
+ do_backtrace ();
+ state ^= 1;
+#if HAVE_DECL_PTRACE_SYSCALL
+ ptrace (PTRACE_SYSCALL, target_pid, 0, pending_sig);
+#elif HAVE_DECL_PT_SYSCALL
+ ptrace (PT_SYSCALL, target_pid, (caddr_t)1, pending_sig);
+#else
+#error Syscall me
+#endif
+ break;
+
+ case INSTRUCTION:
+ do_backtrace ();
+#if HAVE_DECL_PTRACE_SINGLESTEP
+ ptrace (PTRACE_SINGLESTEP, target_pid, 0, pending_sig);
+#elif HAVE_DECL_PT_STEP
+ ptrace (PT_STEP, target_pid, (caddr_t)1, pending_sig);
+#else
+#error Singlestep me
+#endif
+ break;
+ }
+ if (killed)
+ kill (target_pid, SIGKILL);
+ }
+
+ _UPT_destroy (ui);
+ unw_destroy_addr_space (as);
+
+ if (nerrors)
+ {
+ printf ("FAILURE: detected %d errors\n", nerrors);
+ exit (-1);
+ }
+ if (verbose)
+ printf ("SUCCESS\n");
+
+ return 0;
+}
+
+#endif /* !HAVE_TTRACE */
diff --git a/src/pal/src/libunwind/tests/test-reg-state.c b/src/pal/src/libunwind/tests/test-reg-state.c
new file mode 100644
index 0000000000..ac713ea68a
--- /dev/null
+++ b/src/pal/src/libunwind/tests/test-reg-state.c
@@ -0,0 +1,133 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Copyright (c) 2003 Hewlett-Packard Co.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "compiler.h"
+
+#include <libunwind.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+#include <sys/resource.h>
+
+#define panic(args...) \
+ { fprintf (stderr, args); exit (-1); }
+
+int verbose;
+
+struct cb_data
+{
+ unw_word_t ip;
+ void* reg_state;
+ size_t len;
+};
+
+static int
+dwarf_reg_states_callback(void *token,
+ void *rs,
+ size_t size,
+ unw_word_t start_ip, unw_word_t end_ip)
+{
+ struct cb_data *data = token;
+ if (start_ip <= data->ip && data->ip < end_ip)
+ {
+ data->reg_state = mmap(NULL, size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ memcpy(data->reg_state, rs, size);
+ data->len = size;
+ }
+ return 0;
+}
+
+static void
+do_backtrace (void)
+{
+ unw_cursor_t cursor;
+ unw_word_t ip, sp;
+ unw_context_t uc;
+ int ret;
+
+ unw_getcontext (&uc);
+ if (unw_init_local (&cursor, &uc) < 0)
+ panic ("unw_init_local failed!\n");
+
+ do
+ {
+ unw_get_reg (&cursor, UNW_REG_IP, &ip);
+ unw_get_reg (&cursor, UNW_REG_SP, &sp);
+
+ if (verbose)
+ printf ("%016lx (sp=%016lx)\n", (long) ip, (long) sp);
+
+ struct cb_data data = {.ip = ip, .reg_state = NULL};
+ ret = unw_reg_states_iterate(&cursor, dwarf_reg_states_callback, &data);
+ if (ret > 0)
+ {
+ ret = unw_apply_reg_state (&cursor, data.reg_state);
+ munmap(data.reg_state, data.len);
+ }
+ if (ret < 0)
+ {
+ unw_get_reg (&cursor, UNW_REG_IP, &ip);
+ panic ("FAILURE: unw_step() returned %d for ip=%lx\n",
+ ret, (long) ip);
+ }
+ }
+ while (ret > 0);
+}
+
+int
+consume_some_stack_space (void)
+{
+ unw_cursor_t cursor;
+ unw_context_t uc;
+ char string[1024];
+
+ memset (&cursor, 0, sizeof (cursor));
+ memset (&uc, 0, sizeof (uc));
+ return sprintf (string, "hello %p %p\n", &cursor, &uc);
+}
+
+int
+main (int argc, char **argv UNUSED)
+{
+ struct rlimit rlim;
+
+ verbose = argc > 1;
+
+ if (consume_some_stack_space () > 9999)
+ exit (-1); /* can't happen, but don't let the compiler know... */
+
+ rlim.rlim_cur = 0;
+ rlim.rlim_max = RLIM_INFINITY;
+ setrlimit (RLIMIT_DATA, &rlim);
+
+ do_backtrace ();
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/test-setjmp.c b/src/pal/src/libunwind/tests/test-setjmp.c
new file mode 100644
index 0000000000..769b71b222
--- /dev/null
+++ b/src/pal/src/libunwind/tests/test-setjmp.c
@@ -0,0 +1,285 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* The setjmp()/longjmp(), sigsetjmp()/siglongjmp(). */
+
+#include "compiler.h"
+
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int nerrors;
+int verbose;
+
+static jmp_buf jbuf;
+static sigjmp_buf sigjbuf;
+static sigset_t sigset4;
+
+void
+raise_longjmp (jmp_buf jbuf, int i, int n)
+{
+ while (i < n)
+ raise_longjmp (jbuf, i + 1, n);
+
+ longjmp (jbuf, n);
+}
+
+void
+test_setjmp (void)
+{
+ volatile int i;
+ jmp_buf jbuf;
+ int ret;
+
+ for (i = 0; i < 10; ++i)
+ {
+ if ((ret = setjmp (jbuf)))
+ {
+ if (verbose)
+ printf ("%s: secondary setjmp () return, ret=%d\n",
+ __FUNCTION__, ret);
+ if (ret != i + 1)
+ {
+ fprintf (stderr, "%s: setjmp() returned %d, expected %d\n",
+ __FUNCTION__, ret, i + 1);
+ ++nerrors;
+ }
+ continue;
+ }
+ if (verbose)
+ printf ("%s.%d: done with setjmp(); calling children\n",
+ __FUNCTION__, i + 1);
+
+ raise_longjmp (jbuf, 0, i + 1);
+
+ fprintf (stderr, "%s: raise_longjmp() returned unexpectedly\n",
+ __FUNCTION__);
+ ++nerrors;
+ }
+}
+
+
+void
+raise_siglongjmp (sigjmp_buf jbuf, int i, int n)
+{
+ while (i < n)
+ raise_siglongjmp (jbuf, i + 1, n);
+
+ siglongjmp (jbuf, n);
+}
+
+void
+test_sigsetjmp (void)
+{
+ sigjmp_buf jbuf;
+ volatile int i;
+ int ret;
+
+ for (i = 0; i < 10; ++i)
+ {
+ if ((ret = sigsetjmp (jbuf, 1)))
+ {
+ if (verbose)
+ printf ("%s: secondary sigsetjmp () return, ret=%d\n",
+ __FUNCTION__, ret);
+ if (ret != i + 1)
+ {
+ fprintf (stderr, "%s: sigsetjmp() returned %d, expected %d\n",
+ __FUNCTION__, ret, i + 1);
+ ++nerrors;
+ }
+ continue;
+ }
+ if (verbose)
+ printf ("%s.%d: done with sigsetjmp(); calling children\n",
+ __FUNCTION__, i + 1);
+
+ raise_siglongjmp (jbuf, 0, i + 1);
+
+ fprintf (stderr, "%s: raise_siglongjmp() returned unexpectedly\n",
+ __FUNCTION__);
+ ++nerrors;
+ }
+}
+
+void
+sighandler (int signal)
+{
+ if (verbose)
+ printf ("%s: got signal %d\n", __FUNCTION__, signal);
+
+ sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset4);
+ if (verbose)
+ printf ("%s: back from sigprocmask\n", __FUNCTION__);
+
+ siglongjmp (sigjbuf, 1);
+ printf ("%s: siglongjmp() returned unexpectedly!\n", __FUNCTION__);
+}
+
+int
+main (int argc, char **argv UNUSED)
+{
+ volatile sigset_t sigset1, sigset2, sigset3;
+ volatile struct sigaction act;
+
+ if (argc > 1)
+ verbose = 1;
+
+ sigemptyset ((sigset_t *) &sigset1);
+ sigaddset ((sigset_t *) &sigset1, SIGUSR1);
+ sigemptyset ((sigset_t *) &sigset2);
+ sigaddset ((sigset_t *) &sigset2, SIGUSR2);
+
+ memset ((void *) &act, 0, sizeof (act));
+ act.sa_handler = sighandler;
+ sigaction (SIGTERM, (struct sigaction *) &act, NULL);
+
+ test_setjmp ();
+ test_sigsetjmp ();
+
+ /* _setjmp() MUST NOT change signal mask: */
+ sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
+ if (_setjmp (jbuf))
+ {
+ sigemptyset ((sigset_t *) &sigset3);
+ sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
+ if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset2,
+ sizeof (sigset_t)) != 0)
+ {
+ fprintf (stderr, "FAILURE: _longjmp() manipulated signal mask!\n");
+ ++nerrors;
+ }
+ else if (verbose)
+ printf ("OK: _longjmp() seems not to change signal mask\n");
+ }
+ else
+ {
+ sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
+ _longjmp (jbuf, 1);
+ }
+
+ /* sigsetjmp(jbuf, 1) MUST preserve signal mask: */
+ sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
+ if (sigsetjmp (sigjbuf, 1))
+ {
+ sigemptyset ((sigset_t *) &sigset3);
+ sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
+ if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset1,
+ sizeof (sigset_t)) != 0)
+ {
+ fprintf (stderr,
+ "FAILURE: siglongjmp() didn't restore signal mask!\n");
+ ++nerrors;
+ }
+ else if (verbose)
+ printf ("OK: siglongjmp() restores signal mask when asked to\n");
+ }
+ else
+ {
+ sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
+ siglongjmp (sigjbuf, 1);
+ }
+
+ /* sigsetjmp(jbuf, 0) MUST NOT preserve signal mask: */
+ sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
+ if (sigsetjmp (sigjbuf, 0))
+ {
+ sigemptyset ((sigset_t *) &sigset3);
+ sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
+ if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset2,
+ sizeof (sigset_t)) != 0)
+ {
+ fprintf (stderr,
+ "FAILURE: siglongjmp() changed signal mask!\n");
+ ++nerrors;
+ }
+ else if (verbose)
+ printf ("OK: siglongjmp() leaves signal mask alone when asked to\n");
+ }
+ else
+ {
+ sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
+ siglongjmp (sigjbuf, 1);
+ }
+
+ /* sigsetjmp(jbuf, 1) MUST preserve signal mask: */
+ sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
+ if (sigsetjmp (sigjbuf, 1))
+ {
+ sigemptyset ((sigset_t *) &sigset3);
+ sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
+ if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset1,
+ sizeof (sigset_t)) != 0)
+ {
+ fprintf (stderr,
+ "FAILURE: siglongjmp() didn't restore signal mask!\n");
+ ++nerrors;
+ }
+ else if (verbose)
+ printf ("OK: siglongjmp() restores signal mask when asked to\n");
+ }
+ else
+ {
+ sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
+ kill (getpid (), SIGTERM);
+ fprintf (stderr, "FAILURE: unexpected return from kill()\n");
+ ++nerrors;
+ }
+
+ /* sigsetjmp(jbuf, 0) MUST NOT preserve signal mask: */
+ sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
+ if (sigsetjmp (sigjbuf, 0))
+ {
+ sigemptyset ((sigset_t *) &sigset3);
+ sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
+ if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset4,
+ sizeof (sigset_t)) != 0)
+ {
+ fprintf (stderr,
+ "FAILURE: siglongjmp() changed signal mask!\n");
+ ++nerrors;
+ }
+ else if (verbose)
+ printf ("OK: siglongjmp() leaves signal mask alone when asked to\n");
+ }
+ else
+ {
+ sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
+ kill (getpid (), SIGTERM);
+ fprintf (stderr, "FAILURE: unexpected return from kill()\n");
+ ++nerrors;
+ }
+
+ if (nerrors > 0)
+ {
+ fprintf (stderr, "FAILURE: detected %d failures\n", nerrors);
+ exit (-1);
+ }
+ if (verbose)
+ printf ("SUCCESS\n");
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/test-static-link-gen.c b/src/pal/src/libunwind/tests/test-static-link-gen.c
new file mode 100644
index 0000000000..d61e7a51c6
--- /dev/null
+++ b/src/pal/src/libunwind/tests/test-static-link-gen.c
@@ -0,0 +1,74 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Copyright (c) 2003 Hewlett-Packard Co.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <stdio.h>
+
+#include <libunwind.h>
+
+extern int verbose;
+
+static void *funcs[] =
+ {
+ (void *) &unw_get_reg,
+ (void *) &unw_get_fpreg,
+ (void *) &unw_set_reg,
+ (void *) &unw_set_fpreg,
+ (void *) &unw_resume,
+ (void *) &unw_create_addr_space,
+ (void *) &unw_destroy_addr_space,
+ (void *) &unw_get_accessors,
+ (void *) &unw_flush_cache,
+ (void *) &unw_set_caching_policy,
+ (void *) &unw_set_cache_size,
+ (void *) &unw_regname,
+ (void *) &unw_get_proc_info,
+ (void *) &unw_get_save_loc,
+ (void *) &unw_is_signal_frame,
+ (void *) &unw_get_proc_name
+ };
+
+int
+test_generic (void)
+{
+ if (verbose)
+ printf (__FILE__": funcs[0]=%p\n", funcs[0]);
+
+#ifndef UNW_REMOTE_ONLY
+ {
+ unw_context_t uc;
+ unw_cursor_t c;
+
+ unw_getcontext (&uc);
+ unw_init_local (&c, &uc);
+ unw_init_remote (&c, unw_local_addr_space, &uc);
+
+ return unw_step (&c);
+ }
+#else
+ return 0;
+#endif
+}
diff --git a/src/pal/src/libunwind/tests/test-static-link-loc.c b/src/pal/src/libunwind/tests/test-static-link-loc.c
new file mode 100644
index 0000000000..1c7aa0378c
--- /dev/null
+++ b/src/pal/src/libunwind/tests/test-static-link-loc.c
@@ -0,0 +1,102 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Copyright (c) 2003 Hewlett-Packard Co.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* The purpose of this program is simply to link in all libunwind-API
+ functions both in their local-only and generic variants and to make
+ sure that the final result can be linked statically. */
+
+#include <stdio.h>
+
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#include "compiler.h"
+
+extern int test_generic (void);
+
+int verbose;
+
+#ifdef UNW_REMOTE_ONLY
+
+int
+test_local (void)
+{
+ return 0;
+}
+
+#else /* !UNW_REMOTE_ONLY */
+
+static void *funcs[] =
+ {
+ (void *) &unw_get_reg,
+ (void *) &unw_get_fpreg,
+ (void *) &unw_set_reg,
+ (void *) &unw_set_fpreg,
+ (void *) &unw_resume,
+ (void *) &unw_create_addr_space,
+ (void *) &unw_destroy_addr_space,
+ (void *) &unw_get_accessors,
+ (void *) &unw_flush_cache,
+ (void *) &unw_set_caching_policy,
+ (void *) &unw_set_cache_size,
+ (void *) &unw_regname,
+ (void *) &unw_get_proc_info,
+ (void *) &unw_get_save_loc,
+ (void *) &unw_is_signal_frame,
+ (void *) &unw_get_proc_name,
+ (void *) &_U_dyn_register,
+ (void *) &_U_dyn_cancel
+ };
+
+int
+test_local (void)
+{
+ unw_context_t uc;
+ unw_cursor_t c;
+
+ if (verbose)
+ printf (__FILE__": funcs[0]=%p\n", funcs[0]);
+
+ unw_getcontext (&uc);
+ unw_init_local (&c, &uc);
+ unw_init_remote (&c, unw_local_addr_space, &uc);
+ return unw_step (&c);
+}
+
+#endif /* !UNW_REMOTE_ONLY */
+
+int
+main (int argc, char **argv UNUSED)
+{
+ if (argc > 1)
+ verbose = 1;
+
+ if (test_local () < 0)
+ return -1;
+ if (test_generic () < 0)
+ return -1;
+ return 0;
+}
diff --git a/src/pal/src/libunwind/tests/test-strerror.c b/src/pal/src/libunwind/tests/test-strerror.c
new file mode 100644
index 0000000000..f7ae61ed17
--- /dev/null
+++ b/src/pal/src/libunwind/tests/test-strerror.c
@@ -0,0 +1,18 @@
+#include "compiler.h"
+#include <libunwind.h>
+#include <stdio.h>
+
+int
+main (int argc, char **argv UNUSED)
+{
+ int i, verbose = argc > 1;
+ const char *msg;
+
+ for (i = 0; i < 16; ++i)
+ {
+ msg = unw_strerror (-i);
+ if (verbose)
+ printf ("%6d -> %s\n", -i, msg);
+ }
+ return 0;
+}