mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-25 16:47:38 +01:00
Add initial ARM and MIPS support. To support this, also enable the
reading of .debug_frame sections (used in lieu of .eh_frame sections when they're not available).
This commit is contained in:
parent
5ed2da2a40
commit
3842dac733
100 changed files with 6270 additions and 920 deletions
|
@ -1,9 +1,15 @@
|
|||
if ARCH_ARM
|
||||
include_HEADERS_tdep = include/libunwind-arm.h
|
||||
else
|
||||
if ARCH_IA64
|
||||
include_HEADERS_tdep = include/libunwind-ia64.h
|
||||
else
|
||||
if ARCH_HPPA
|
||||
include_HEADERS_tdep = include/libunwind-hppa.h
|
||||
else
|
||||
if ARCH_MIPS
|
||||
include_HEADERS_tdep = include/libunwind-mips.h
|
||||
else
|
||||
if ARCH_X86
|
||||
include_HEADERS_tdep = include/libunwind-x86.h
|
||||
else
|
||||
|
@ -19,8 +25,10 @@ endif # ARCH_PPC64
|
|||
endif # ARCH_PPC32
|
||||
endif # ARCH_X86_64
|
||||
endif # ARCH_X86
|
||||
endif # ARCH_MIPS
|
||||
endif # ARCH_HPPA
|
||||
endif # ARCH_IA64
|
||||
endif # ARCH_ARM
|
||||
|
||||
include_HEADERS_common = $(include_HEADERS_tdep) \
|
||||
include/libunwind-dynamic.h include/libunwind-ptrace.h
|
||||
|
|
24
Makefile.in
24
Makefile.in
|
@ -66,8 +66,9 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
|
|||
uninstall-recursive
|
||||
am__include_HEADERS_DIST = include/libunwind-ppc64.h \
|
||||
include/libunwind-ppc32.h include/libunwind-x86_64.h \
|
||||
include/libunwind-x86.h include/libunwind-hppa.h \
|
||||
include/libunwind-ia64.h include/libunwind-dynamic.h \
|
||||
include/libunwind-x86.h include/libunwind-mips.h \
|
||||
include/libunwind-hppa.h include/libunwind-ia64.h \
|
||||
include/libunwind-arm.h include/libunwind-dynamic.h \
|
||||
include/libunwind-ptrace.h include/libunwind.h \
|
||||
include/unwind.h
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
|
@ -100,10 +101,14 @@ AMDEP_TRUE = @AMDEP_TRUE@
|
|||
AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
ARCH = @ARCH@
|
||||
ARCH_ARM_FALSE = @ARCH_ARM_FALSE@
|
||||
ARCH_ARM_TRUE = @ARCH_ARM_TRUE@
|
||||
ARCH_HPPA_FALSE = @ARCH_HPPA_FALSE@
|
||||
ARCH_HPPA_TRUE = @ARCH_HPPA_TRUE@
|
||||
ARCH_IA64_FALSE = @ARCH_IA64_FALSE@
|
||||
ARCH_IA64_TRUE = @ARCH_IA64_TRUE@
|
||||
ARCH_MIPS_FALSE = @ARCH_MIPS_FALSE@
|
||||
ARCH_MIPS_TRUE = @ARCH_MIPS_TRUE@
|
||||
ARCH_PPC32_FALSE = @ARCH_PPC32_FALSE@
|
||||
ARCH_PPC32_TRUE = @ARCH_PPC32_TRUE@
|
||||
ARCH_PPC64_FALSE = @ARCH_PPC64_FALSE@
|
||||
|
@ -174,6 +179,7 @@ PKG_MINOR = @PKG_MINOR@
|
|||
RANLIB = @RANLIB@
|
||||
REMOTE_ONLY_FALSE = @REMOTE_ONLY_FALSE@
|
||||
REMOTE_ONLY_TRUE = @REMOTE_ONLY_TRUE@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
|
@ -233,12 +239,14 @@ target_alias = @target_alias@
|
|||
target_cpu = @target_cpu@
|
||||
target_os = @target_os@
|
||||
target_vendor = @target_vendor@
|
||||
@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_PPC32_FALSE@@ARCH_PPC64_TRUE@@ARCH_X86_64_FALSE@@ARCH_X86_FALSE@include_HEADERS_tdep = include/libunwind-ppc64.h
|
||||
@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_PPC32_TRUE@@ARCH_X86_64_FALSE@@ARCH_X86_FALSE@include_HEADERS_tdep = include/libunwind-ppc32.h
|
||||
@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_X86_64_TRUE@@ARCH_X86_FALSE@include_HEADERS_tdep = include/libunwind-x86_64.h
|
||||
@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_X86_TRUE@include_HEADERS_tdep = include/libunwind-x86.h
|
||||
@ARCH_HPPA_TRUE@@ARCH_IA64_FALSE@include_HEADERS_tdep = include/libunwind-hppa.h
|
||||
@ARCH_IA64_TRUE@include_HEADERS_tdep = include/libunwind-ia64.h
|
||||
@ARCH_ARM_FALSE@@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_MIPS_FALSE@@ARCH_PPC32_FALSE@@ARCH_PPC64_TRUE@@ARCH_X86_64_FALSE@@ARCH_X86_FALSE@include_HEADERS_tdep = include/libunwind-ppc64.h
|
||||
@ARCH_ARM_FALSE@@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_MIPS_FALSE@@ARCH_PPC32_TRUE@@ARCH_X86_64_FALSE@@ARCH_X86_FALSE@include_HEADERS_tdep = include/libunwind-ppc32.h
|
||||
@ARCH_ARM_FALSE@@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_MIPS_FALSE@@ARCH_X86_64_TRUE@@ARCH_X86_FALSE@include_HEADERS_tdep = include/libunwind-x86_64.h
|
||||
@ARCH_ARM_FALSE@@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_MIPS_FALSE@@ARCH_X86_TRUE@include_HEADERS_tdep = include/libunwind-x86.h
|
||||
@ARCH_ARM_FALSE@@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_MIPS_TRUE@include_HEADERS_tdep = include/libunwind-mips.h
|
||||
@ARCH_ARM_FALSE@@ARCH_HPPA_TRUE@@ARCH_IA64_FALSE@include_HEADERS_tdep = include/libunwind-hppa.h
|
||||
@ARCH_ARM_FALSE@@ARCH_IA64_TRUE@include_HEADERS_tdep = include/libunwind-ia64.h
|
||||
@ARCH_ARM_TRUE@include_HEADERS_tdep = include/libunwind-arm.h
|
||||
include_HEADERS_common = $(include_HEADERS_tdep) \
|
||||
include/libunwind-dynamic.h include/libunwind-ptrace.h
|
||||
|
||||
|
|
412
aclocal.m4
vendored
412
aclocal.m4
vendored
|
@ -13,7 +13,7 @@
|
|||
|
||||
# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
|
||||
|
||||
# serial 48 Debian 1.5.22-4 AC_PROG_LIBTOOL
|
||||
# serial 51 Debian 1.5.24-2 AC_PROG_LIBTOOL
|
||||
|
||||
|
||||
# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED)
|
||||
|
@ -176,7 +176,7 @@ test -z "$STRIP" && STRIP=:
|
|||
test -z "$ac_objext" && ac_objext=o
|
||||
|
||||
# Determine commands to create old-style static archives.
|
||||
old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
|
||||
old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
|
||||
old_postinstall_cmds='chmod 644 $oldlib'
|
||||
old_postuninstall_cmds=
|
||||
|
||||
|
@ -263,8 +263,9 @@ cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
|
|||
# Check for compiler boilerplate output or warnings with
|
||||
# the simple compiler test code.
|
||||
AC_DEFUN([_LT_COMPILER_BOILERPLATE],
|
||||
[ac_outfile=conftest.$ac_objext
|
||||
printf "$lt_simple_compile_test_code" >conftest.$ac_ext
|
||||
[AC_REQUIRE([LT_AC_PROG_SED])dnl
|
||||
ac_outfile=conftest.$ac_objext
|
||||
echo "$lt_simple_compile_test_code" >conftest.$ac_ext
|
||||
eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
|
||||
_lt_compiler_boilerplate=`cat conftest.err`
|
||||
$rm conftest*
|
||||
|
@ -276,8 +277,9 @@ $rm conftest*
|
|||
# Check for linker boilerplate output or warnings with
|
||||
# the simple link test code.
|
||||
AC_DEFUN([_LT_LINKER_BOILERPLATE],
|
||||
[ac_outfile=conftest.$ac_objext
|
||||
printf "$lt_simple_link_test_code" >conftest.$ac_ext
|
||||
[AC_REQUIRE([LT_AC_PROG_SED])dnl
|
||||
ac_outfile=conftest.$ac_objext
|
||||
echo "$lt_simple_link_test_code" >conftest.$ac_ext
|
||||
eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
|
||||
_lt_linker_boilerplate=`cat conftest.err`
|
||||
$rm conftest*
|
||||
|
@ -293,12 +295,20 @@ $rm conftest*
|
|||
# If we don't find anything, use the default library path according
|
||||
# to the aix ld manual.
|
||||
AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX],
|
||||
[AC_LINK_IFELSE(AC_LANG_PROGRAM,[
|
||||
aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
|
||||
}'`
|
||||
[AC_REQUIRE([LT_AC_PROG_SED])dnl
|
||||
AC_LINK_IFELSE(AC_LANG_PROGRAM,[
|
||||
lt_aix_libpath_sed='
|
||||
/Import File Strings/,/^$/ {
|
||||
/^0/ {
|
||||
s/^0 *\(.*\)$/\1/
|
||||
p
|
||||
}
|
||||
}'
|
||||
aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
|
||||
# Check for a 64-bit object if we didn't find anything.
|
||||
if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
|
||||
}'`; fi],[])
|
||||
if test -z "$aix_libpath"; then
|
||||
aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
|
||||
fi],[])
|
||||
if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
|
||||
])# _LT_AC_SYS_LIBPATH_AIX
|
||||
|
||||
|
@ -529,13 +539,17 @@ ia64-*-hpux*)
|
|||
rm -rf conftest*
|
||||
;;
|
||||
|
||||
x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
|
||||
x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
|
||||
s390*-*linux*|sparc*-*linux*)
|
||||
# Find out which ABI we are using.
|
||||
echo 'int i;' > conftest.$ac_ext
|
||||
if AC_TRY_EVAL(ac_compile); then
|
||||
case `/usr/bin/file conftest.o` in
|
||||
*32-bit*)
|
||||
case $host in
|
||||
x86_64-*kfreebsd*-gnu)
|
||||
LD="${LD-ld} -m elf_i386_fbsd"
|
||||
;;
|
||||
x86_64-*linux*)
|
||||
LD="${LD-ld} -m elf_i386"
|
||||
;;
|
||||
|
@ -552,6 +566,9 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
|
|||
;;
|
||||
*64-bit*)
|
||||
case $host in
|
||||
x86_64-*kfreebsd*-gnu)
|
||||
LD="${LD-ld} -m elf_x86_64_fbsd"
|
||||
;;
|
||||
x86_64-*linux*)
|
||||
LD="${LD-ld} -m elf_x86_64"
|
||||
;;
|
||||
|
@ -623,7 +640,7 @@ AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION],
|
|||
AC_CACHE_CHECK([$1], [$2],
|
||||
[$2=no
|
||||
ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
|
||||
printf "$lt_simple_compile_test_code" > conftest.$ac_ext
|
||||
echo "$lt_simple_compile_test_code" > conftest.$ac_ext
|
||||
lt_compiler_flag="$3"
|
||||
# Insert the option either (1) after the last *FLAGS variable, or
|
||||
# (2) before a word containing "conftest.", or (3) at the end.
|
||||
|
@ -664,11 +681,12 @@ fi
|
|||
# ------------------------------------------------------------
|
||||
# Check whether the given compiler option works
|
||||
AC_DEFUN([AC_LIBTOOL_LINKER_OPTION],
|
||||
[AC_CACHE_CHECK([$1], [$2],
|
||||
[AC_REQUIRE([LT_AC_PROG_SED])dnl
|
||||
AC_CACHE_CHECK([$1], [$2],
|
||||
[$2=no
|
||||
save_LDFLAGS="$LDFLAGS"
|
||||
LDFLAGS="$LDFLAGS $3"
|
||||
printf "$lt_simple_link_test_code" > conftest.$ac_ext
|
||||
echo "$lt_simple_link_test_code" > conftest.$ac_ext
|
||||
if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
|
||||
# The linker can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings
|
||||
|
@ -782,9 +800,11 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
|
|||
fi
|
||||
;;
|
||||
*)
|
||||
# If test is not a shell built-in, we'll probably end up computing a
|
||||
# maximum length that is only half of the actual maximum length, but
|
||||
# we can't tell.
|
||||
lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
|
||||
if test -n "$lt_cv_sys_max_cmd_len"; then
|
||||
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
|
||||
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
|
||||
else
|
||||
SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
|
||||
while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \
|
||||
= "XX$teststring") >/dev/null 2>&1 &&
|
||||
|
@ -800,6 +820,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
|
|||
# amounts of additional arguments before passing them to the linker.
|
||||
# It appears as though 1/2 is a usable value.
|
||||
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
])
|
||||
|
@ -1026,7 +1047,8 @@ fi
|
|||
# ---------------------------------
|
||||
# Check to see if options -c and -o are simultaneously supported by compiler
|
||||
AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O],
|
||||
[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
|
||||
[AC_REQUIRE([LT_AC_PROG_SED])dnl
|
||||
AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
|
||||
AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
|
||||
[_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
|
||||
[_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
|
||||
|
@ -1034,7 +1056,7 @@ AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
|
|||
mkdir conftest
|
||||
cd conftest
|
||||
mkdir out
|
||||
printf "$lt_simple_compile_test_code" > conftest.$ac_ext
|
||||
echo "$lt_simple_compile_test_code" > conftest.$ac_ext
|
||||
|
||||
lt_compiler_flag="-o out/conftest2.$ac_objext"
|
||||
# Insert the option either (1) after the last *FLAGS variable, or
|
||||
|
@ -1174,6 +1196,7 @@ else
|
|||
darwin*)
|
||||
if test -n "$STRIP" ; then
|
||||
striplib="$STRIP -x"
|
||||
old_striplib="$STRIP -S"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
|
@ -1191,7 +1214,8 @@ fi
|
|||
# -----------------------------
|
||||
# PORTME Fill in your ld.so characteristics
|
||||
AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER],
|
||||
[AC_MSG_CHECKING([dynamic linker characteristics])
|
||||
[AC_REQUIRE([LT_AC_PROG_SED])dnl
|
||||
AC_MSG_CHECKING([dynamic linker characteristics])
|
||||
library_names_spec=
|
||||
libname_spec='lib$name'
|
||||
soname_spec=
|
||||
|
@ -1205,20 +1229,58 @@ shlibpath_overrides_runpath=unknown
|
|||
version_type=none
|
||||
dynamic_linker="$host_os ld.so"
|
||||
sys_lib_dlsearch_path_spec="/lib /usr/lib"
|
||||
m4_if($1,[],[
|
||||
if test "$GCC" = yes; then
|
||||
sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
|
||||
if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
|
||||
case $host_os in
|
||||
darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
|
||||
*) lt_awk_arg="/^libraries:/" ;;
|
||||
esac
|
||||
lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
|
||||
if echo "$lt_search_path_spec" | grep ';' >/dev/null ; then
|
||||
# if the path contains ";" then we assume it to be the separator
|
||||
# otherwise default to the standard path separator (i.e. ":") - it is
|
||||
# assumed that no part of a normal pathname contains ";" but that should
|
||||
# okay in the real world where ";" in dirpaths is itself problematic.
|
||||
sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
|
||||
lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e 's/;/ /g'`
|
||||
else
|
||||
sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
|
||||
lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
|
||||
fi
|
||||
# Ok, now we have the path, separated by spaces, we can step through it
|
||||
# and add multilib dir if necessary.
|
||||
lt_tmp_lt_search_path_spec=
|
||||
lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
|
||||
for lt_sys_path in $lt_search_path_spec; do
|
||||
if test -d "$lt_sys_path/$lt_multi_os_dir"; then
|
||||
lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
|
||||
else
|
||||
test -d "$lt_sys_path" && \
|
||||
lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
|
||||
fi
|
||||
done
|
||||
lt_search_path_spec=`echo $lt_tmp_lt_search_path_spec | awk '
|
||||
BEGIN {RS=" "; FS="/|\n";} {
|
||||
lt_foo="";
|
||||
lt_count=0;
|
||||
for (lt_i = NF; lt_i > 0; lt_i--) {
|
||||
if ($lt_i != "" && $lt_i != ".") {
|
||||
if ($lt_i == "..") {
|
||||
lt_count++;
|
||||
} else {
|
||||
if (lt_count == 0) {
|
||||
lt_foo="/" $lt_i lt_foo;
|
||||
} else {
|
||||
lt_count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lt_foo != "") { lt_freq[[lt_foo]]++; }
|
||||
if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
|
||||
}'`
|
||||
sys_lib_search_path_spec=`echo $lt_search_path_spec`
|
||||
else
|
||||
sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
|
||||
fi
|
||||
fi])
|
||||
need_lib_prefix=unknown
|
||||
hardcode_into_libs=no
|
||||
|
||||
|
@ -1375,12 +1437,8 @@ darwin* | rhapsody*)
|
|||
shlibpath_overrides_runpath=yes
|
||||
shlibpath_var=DYLD_LIBRARY_PATH
|
||||
shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
|
||||
# Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
|
||||
if test "$GCC" = yes; then
|
||||
sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
|
||||
else
|
||||
sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
|
||||
fi
|
||||
m4_if([$1], [],[
|
||||
sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
|
||||
sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
|
||||
;;
|
||||
|
||||
|
@ -1434,7 +1492,7 @@ freebsd* | dragonfly*)
|
|||
shlibpath_overrides_runpath=no
|
||||
hardcode_into_libs=yes
|
||||
;;
|
||||
freebsd*) # from 4.6 on
|
||||
*) # from 4.6 on, and DragonFly
|
||||
shlibpath_overrides_runpath=yes
|
||||
hardcode_into_libs=yes
|
||||
;;
|
||||
|
@ -1497,7 +1555,7 @@ hpux9* | hpux10* | hpux11*)
|
|||
postinstall_cmds='chmod 555 $lib'
|
||||
;;
|
||||
|
||||
interix3*)
|
||||
interix[[3-9]]*)
|
||||
version_type=linux
|
||||
need_lib_prefix=no
|
||||
need_version=no
|
||||
|
@ -1568,7 +1626,7 @@ linux* | k*bsd*-gnu)
|
|||
|
||||
# Append ld.so.conf contents to the search path
|
||||
if test -f /etc/ld.so.conf; then
|
||||
lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
|
||||
lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
|
||||
sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
|
||||
fi
|
||||
|
||||
|
@ -1674,6 +1732,10 @@ osf3* | osf4* | osf5*)
|
|||
sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
|
||||
;;
|
||||
|
||||
rdos*)
|
||||
dynamic_linker=no
|
||||
;;
|
||||
|
||||
solaris*)
|
||||
version_type=linux
|
||||
need_lib_prefix=no
|
||||
|
@ -1779,7 +1841,8 @@ fi
|
|||
# _LT_AC_TAGCONFIG
|
||||
# ----------------
|
||||
AC_DEFUN([_LT_AC_TAGCONFIG],
|
||||
[AC_ARG_WITH([tags],
|
||||
[AC_REQUIRE([LT_AC_PROG_SED])dnl
|
||||
AC_ARG_WITH([tags],
|
||||
[AC_HELP_STRING([--with-tags@<:@=TAGS@:>@],
|
||||
[include additional configurations @<:@automatic@:>@])],
|
||||
[tagnames="$withval"])
|
||||
|
@ -2040,7 +2103,7 @@ m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP],
|
|||
|
||||
# AC_PATH_TOOL_PREFIX
|
||||
# -------------------
|
||||
# find a file program which can recognise shared library
|
||||
# find a file program which can recognize shared library
|
||||
AC_DEFUN([AC_PATH_TOOL_PREFIX],
|
||||
[AC_REQUIRE([AC_PROG_EGREP])dnl
|
||||
AC_MSG_CHECKING([for $1])
|
||||
|
@ -2103,7 +2166,7 @@ fi
|
|||
|
||||
# AC_PATH_MAGIC
|
||||
# -------------
|
||||
# find a file program which can recognise a shared library
|
||||
# find a file program which can recognize a shared library
|
||||
AC_DEFUN([AC_PATH_MAGIC],
|
||||
[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
|
||||
if test -z "$lt_cv_path_MAGIC_CMD"; then
|
||||
|
@ -2250,7 +2313,7 @@ esac
|
|||
# how to check for library dependencies
|
||||
# -- PORTME fill in with the dynamic library characteristics
|
||||
AC_DEFUN([AC_DEPLIBS_CHECK_METHOD],
|
||||
[AC_CACHE_CHECK([how to recognise dependent libraries],
|
||||
[AC_CACHE_CHECK([how to recognize dependent libraries],
|
||||
lt_cv_deplibs_check_method,
|
||||
[lt_cv_file_magic_cmd='$MAGIC_CMD'
|
||||
lt_cv_file_magic_test_file=
|
||||
|
@ -2289,9 +2352,15 @@ cygwin*)
|
|||
|
||||
mingw* | pw32*)
|
||||
# Base MSYS/MinGW do not provide the 'file' command needed by
|
||||
# func_win32_libid shell function, so use a weaker test based on 'objdump'.
|
||||
# func_win32_libid shell function, so use a weaker test based on 'objdump',
|
||||
# unless we find 'file', for example because we are cross-compiling.
|
||||
if ( file / ) >/dev/null 2>&1; then
|
||||
lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
|
||||
lt_cv_file_magic_cmd='func_win32_libid'
|
||||
else
|
||||
lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
|
||||
lt_cv_file_magic_cmd='$OBJDUMP -f'
|
||||
fi
|
||||
;;
|
||||
|
||||
darwin* | rhapsody*)
|
||||
|
@ -2336,7 +2405,7 @@ hpux10.20* | hpux11*)
|
|||
esac
|
||||
;;
|
||||
|
||||
interix3*)
|
||||
interix[[3-9]]*)
|
||||
# PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
|
||||
lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
|
||||
;;
|
||||
|
@ -2386,6 +2455,10 @@ osf3* | osf4* | osf5*)
|
|||
lt_cv_deplibs_check_method=pass_all
|
||||
;;
|
||||
|
||||
rdos*)
|
||||
lt_cv_deplibs_check_method=pass_all
|
||||
;;
|
||||
|
||||
solaris*)
|
||||
lt_cv_deplibs_check_method=pass_all
|
||||
;;
|
||||
|
@ -2654,10 +2727,10 @@ objext=o
|
|||
_LT_AC_TAGVAR(objext, $1)=$objext
|
||||
|
||||
# Code to be used in simple compile tests
|
||||
lt_simple_compile_test_code="int some_variable = 0;\n"
|
||||
lt_simple_compile_test_code="int some_variable = 0;"
|
||||
|
||||
# Code to be used in simple link tests
|
||||
lt_simple_link_test_code='int main(){return(0);}\n'
|
||||
lt_simple_link_test_code='int main(){return(0);}'
|
||||
|
||||
_LT_AC_SYS_COMPILER
|
||||
|
||||
|
@ -2759,10 +2832,10 @@ objext=o
|
|||
_LT_AC_TAGVAR(objext, $1)=$objext
|
||||
|
||||
# Code to be used in simple compile tests
|
||||
lt_simple_compile_test_code="int some_variable = 0;\n"
|
||||
lt_simple_compile_test_code="int some_variable = 0;"
|
||||
|
||||
# Code to be used in simple link tests
|
||||
lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }\n'
|
||||
lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
|
||||
|
||||
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
|
||||
_LT_AC_SYS_COMPILER
|
||||
|
@ -2908,7 +2981,7 @@ case $host_os in
|
|||
strings "$collect2name" | grep resolve_lib_name >/dev/null
|
||||
then
|
||||
# We have reworked collect2
|
||||
_LT_AC_TAGVAR(hardcode_direct, $1)=yes
|
||||
:
|
||||
else
|
||||
# We have old collect2
|
||||
_LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
|
||||
|
@ -3067,10 +3140,10 @@ case $host_os in
|
|||
case $cc_basename in
|
||||
xlc*)
|
||||
output_verbose_link_cmd='echo'
|
||||
_LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
|
||||
_LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring'
|
||||
_LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
|
||||
# Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
|
||||
_LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
|
||||
_LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
|
||||
_LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
|
||||
;;
|
||||
*)
|
||||
|
@ -3153,9 +3226,7 @@ case $host_os in
|
|||
_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
|
||||
|
||||
case $host_cpu in
|
||||
hppa*64*|ia64*)
|
||||
_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
|
||||
;;
|
||||
hppa*64*|ia64*) ;;
|
||||
*)
|
||||
_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
|
||||
;;
|
||||
|
@ -3223,7 +3294,7 @@ case $host_os in
|
|||
;;
|
||||
esac
|
||||
;;
|
||||
interix3*)
|
||||
interix[[3-9]]*)
|
||||
_LT_AC_TAGVAR(hardcode_direct, $1)=no
|
||||
_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
|
||||
_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
|
||||
|
@ -3343,6 +3414,29 @@ case $host_os in
|
|||
# dependencies.
|
||||
output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
|
||||
;;
|
||||
*)
|
||||
case `$CC -V 2>&1 | sed 5q` in
|
||||
*Sun\ C*)
|
||||
# Sun C++ 5.9
|
||||
_LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs'
|
||||
_LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
|
||||
_LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
|
||||
_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
|
||||
_LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
|
||||
|
||||
# Not sure whether something based on
|
||||
# $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
|
||||
# would be better.
|
||||
output_verbose_link_cmd='echo'
|
||||
|
||||
# Archives containing C++ object files must be created using
|
||||
# "CC -xar", where "CC" is the Sun C++ compiler. This is
|
||||
# necessary to make sure instantiated templates are included
|
||||
# in the archive.
|
||||
_LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
lynxos*)
|
||||
|
@ -3381,6 +3475,7 @@ case $host_os in
|
|||
_LT_AC_TAGVAR(ld_shlibs, $1)=no
|
||||
;;
|
||||
openbsd*)
|
||||
if test -f /usr/libexec/ld.so; then
|
||||
_LT_AC_TAGVAR(hardcode_direct, $1)=yes
|
||||
_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
|
||||
_LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
|
||||
|
@ -3391,6 +3486,9 @@ case $host_os in
|
|||
_LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
|
||||
fi
|
||||
output_verbose_link_cmd='echo'
|
||||
else
|
||||
_LT_AC_TAGVAR(ld_shlibs, $1)=no
|
||||
fi
|
||||
;;
|
||||
osf3*)
|
||||
case $cc_basename in
|
||||
|
@ -3552,15 +3650,10 @@ case $host_os in
|
|||
case $host_os in
|
||||
solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
|
||||
*)
|
||||
# The C++ compiler is used as linker so we must use $wl
|
||||
# flag to pass the commands to the underlying system
|
||||
# linker. We must also pass each convience library through
|
||||
# to the system linker between allextract/defaultextract.
|
||||
# The C++ compiler will combine linker options so we
|
||||
# cannot just pass the convience library names through
|
||||
# without $wl.
|
||||
# The compiler driver will combine and reorder linker options,
|
||||
# but understands `-z linker_flag'.
|
||||
# Supported since Solaris 2.6 (maybe 2.5.1?)
|
||||
_LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract'
|
||||
_LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
|
||||
;;
|
||||
esac
|
||||
_LT_AC_TAGVAR(link_all_deplibs, $1)=yes
|
||||
|
@ -3607,6 +3700,12 @@ case $host_os in
|
|||
fi
|
||||
|
||||
_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
|
||||
case $host_os in
|
||||
solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
|
||||
*)
|
||||
_LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
@ -3850,7 +3949,7 @@ $rm -f confest.$objext
|
|||
# PORTME: override above test on systems where it is broken
|
||||
ifelse([$1],[CXX],
|
||||
[case $host_os in
|
||||
interix3*)
|
||||
interix[[3-9]]*)
|
||||
# Interix 3.5 installs completely hosed .la files for C++, so rather than
|
||||
# hack all around it, let's just trust "g++" to DTRT.
|
||||
_LT_AC_TAGVAR(predep_objects,$1)=
|
||||
|
@ -3858,13 +3957,46 @@ interix3*)
|
|||
_LT_AC_TAGVAR(postdeps,$1)=
|
||||
;;
|
||||
|
||||
linux*)
|
||||
case `$CC -V 2>&1 | sed 5q` in
|
||||
*Sun\ C*)
|
||||
# Sun C++ 5.9
|
||||
#
|
||||
# The more standards-conforming stlport4 library is
|
||||
# incompatible with the Cstd library. Avoid specifying
|
||||
# it if it's in CXXFLAGS. Ignore libCrun as
|
||||
# -library=stlport4 depends on it.
|
||||
case " $CXX $CXXFLAGS " in
|
||||
*" -library=stlport4 "*)
|
||||
solaris_use_stlport4=yes
|
||||
;;
|
||||
esac
|
||||
if test "$solaris_use_stlport4" != yes; then
|
||||
_LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
solaris*)
|
||||
case $cc_basename in
|
||||
CC*)
|
||||
# The more standards-conforming stlport4 library is
|
||||
# incompatible with the Cstd library. Avoid specifying
|
||||
# it if it's in CXXFLAGS. Ignore libCrun as
|
||||
# -library=stlport4 depends on it.
|
||||
case " $CXX $CXXFLAGS " in
|
||||
*" -library=stlport4 "*)
|
||||
solaris_use_stlport4=yes
|
||||
;;
|
||||
esac
|
||||
|
||||
# Adding this requires a known-good setup of shared libraries for
|
||||
# Sun compiler versions before 5.6, else PIC objects from an old
|
||||
# archive will be linked into the output, leading to subtle bugs.
|
||||
_LT_AC_TAGVAR(postdeps,$1)='-lCstd -lCrun'
|
||||
if test "$solaris_use_stlport4" != yes; then
|
||||
_LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
@ -3913,10 +4045,17 @@ objext=o
|
|||
_LT_AC_TAGVAR(objext, $1)=$objext
|
||||
|
||||
# Code to be used in simple compile tests
|
||||
lt_simple_compile_test_code=" subroutine t\n return\n end\n"
|
||||
lt_simple_compile_test_code="\
|
||||
subroutine t
|
||||
return
|
||||
end
|
||||
"
|
||||
|
||||
# Code to be used in simple link tests
|
||||
lt_simple_link_test_code=" program t\n end\n"
|
||||
lt_simple_link_test_code="\
|
||||
program t
|
||||
end
|
||||
"
|
||||
|
||||
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
|
||||
_LT_AC_SYS_COMPILER
|
||||
|
@ -3995,10 +4134,10 @@ objext=o
|
|||
_LT_AC_TAGVAR(objext, $1)=$objext
|
||||
|
||||
# Code to be used in simple compile tests
|
||||
lt_simple_compile_test_code="class foo {}\n"
|
||||
lt_simple_compile_test_code="class foo {}"
|
||||
|
||||
# Code to be used in simple link tests
|
||||
lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }\n'
|
||||
lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
|
||||
|
||||
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
|
||||
_LT_AC_SYS_COMPILER
|
||||
|
@ -4051,7 +4190,7 @@ objext=o
|
|||
_LT_AC_TAGVAR(objext, $1)=$objext
|
||||
|
||||
# Code to be used in simple compile tests
|
||||
lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n'
|
||||
lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
|
||||
|
||||
# Code to be used in simple link tests
|
||||
lt_simple_link_test_code="$lt_simple_compile_test_code"
|
||||
|
@ -4140,6 +4279,7 @@ if test -f "$ltmain"; then
|
|||
_LT_AC_TAGVAR(module_cmds, $1) \
|
||||
_LT_AC_TAGVAR(module_expsym_cmds, $1) \
|
||||
_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \
|
||||
_LT_AC_TAGVAR(fix_srcfile_path, $1) \
|
||||
_LT_AC_TAGVAR(exclude_expsyms, $1) \
|
||||
_LT_AC_TAGVAR(include_expsyms, $1); do
|
||||
|
||||
|
@ -4186,7 +4326,7 @@ ifelse([$1], [],
|
|||
# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
|
||||
# NOTE: Changes made to this file will be lost: look at ltmain.sh.
|
||||
#
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GNU Libtool:
|
||||
|
@ -4511,7 +4651,7 @@ sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
|
|||
sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
|
||||
|
||||
# Fix the shell variable \$srcfile for the compiler.
|
||||
fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)"
|
||||
fix_srcfile_path=$lt_fix_srcfile_path
|
||||
|
||||
# Set to yes if exported symbols are required.
|
||||
always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1)
|
||||
|
@ -4594,6 +4734,7 @@ fi
|
|||
# ---------------------------------
|
||||
AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE],
|
||||
[AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
AC_REQUIRE([LT_AC_PROG_SED])
|
||||
AC_REQUIRE([AC_PROG_NM])
|
||||
AC_REQUIRE([AC_OBJEXT])
|
||||
# Check for command to grab the raw symbol name followed by C symbol from nm.
|
||||
|
@ -4820,12 +4961,14 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
|
|||
# like `-m68040'.
|
||||
_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
|
||||
;;
|
||||
beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
|
||||
beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
|
||||
# PIC is the default for these OSes.
|
||||
;;
|
||||
mingw* | os2* | pw32*)
|
||||
mingw* | cygwin* | os2* | pw32*)
|
||||
# This hack is so that the source file can tell whether it is being
|
||||
# built for inclusion in a dll (and should export symbols for example).
|
||||
# Although the cygwin gcc ignores -fPIC, still need this for old-style
|
||||
# (--disable-auto-import) libraries
|
||||
_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
|
||||
;;
|
||||
darwin* | rhapsody*)
|
||||
|
@ -4837,7 +4980,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
|
|||
# DJGPP does not support shared libraries at all
|
||||
_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
|
||||
;;
|
||||
interix3*)
|
||||
interix[[3-9]]*)
|
||||
# Interix 3.x gcc -fpic/-fPIC options generate broken code.
|
||||
# Instead, we relocate shared libraries at runtime.
|
||||
;;
|
||||
|
@ -4973,6 +5116,14 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
|
|||
_LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
|
||||
;;
|
||||
*)
|
||||
case `$CC -V 2>&1 | sed 5q` in
|
||||
*Sun\ C*)
|
||||
# Sun C++ 5.9
|
||||
_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
|
||||
_LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
|
||||
_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
@ -5093,13 +5244,15 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
|
|||
_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
|
||||
;;
|
||||
|
||||
beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
|
||||
beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
|
||||
# PIC is the default for these OSes.
|
||||
;;
|
||||
|
||||
mingw* | pw32* | os2*)
|
||||
mingw* | cygwin* | pw32* | os2*)
|
||||
# This hack is so that the source file can tell whether it is being
|
||||
# built for inclusion in a dll (and should export symbols for example).
|
||||
# Although the cygwin gcc ignores -fPIC, still need this for old-style
|
||||
# (--disable-auto-import) libraries
|
||||
_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
|
||||
;;
|
||||
|
||||
|
@ -5109,7 +5262,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
|
|||
_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
|
||||
;;
|
||||
|
||||
interix3*)
|
||||
interix[[3-9]]*)
|
||||
# Interix 3.x gcc -fpic/-fPIC options generate broken code.
|
||||
# Instead, we relocate shared libraries at runtime.
|
||||
;;
|
||||
|
@ -5167,7 +5320,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
|
|||
esac
|
||||
;;
|
||||
|
||||
mingw* | pw32* | os2*)
|
||||
mingw* | cygwin* | pw32* | os2*)
|
||||
# This hack is so that the source file can tell whether it is being
|
||||
# built for inclusion in a dll (and should export symbols for example).
|
||||
_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
|
||||
|
@ -5219,6 +5372,22 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
|
|||
# All Alpha code is PIC.
|
||||
_LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
|
||||
;;
|
||||
*)
|
||||
case `$CC -V 2>&1 | sed 5q` in
|
||||
*Sun\ C*)
|
||||
# Sun C 5.9
|
||||
_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
|
||||
_LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
|
||||
_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
|
||||
;;
|
||||
*Sun\ F*)
|
||||
# Sun Fortran 8.3 passes all unrecognized flags to the linker
|
||||
_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
|
||||
_LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
|
||||
_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)=''
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
|
@ -5228,6 +5397,10 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
|
|||
_LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
|
||||
;;
|
||||
|
||||
rdos*)
|
||||
_LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
|
||||
;;
|
||||
|
||||
solaris*)
|
||||
_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
|
||||
_LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
|
||||
|
@ -5322,7 +5495,8 @@ AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
|
|||
# ------------------------------------
|
||||
# See if the linker supports building shared libraries.
|
||||
AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS],
|
||||
[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
|
||||
[AC_REQUIRE([LT_AC_PROG_SED])dnl
|
||||
AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
|
||||
ifelse([$1],[CXX],[
|
||||
_LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
|
||||
case $host_os in
|
||||
|
@ -5339,7 +5513,7 @@ ifelse([$1],[CXX],[
|
|||
_LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
|
||||
;;
|
||||
cygwin* | mingw*)
|
||||
_LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([[^ ]]*\) [[^ ]]*/\1 DATA/;/^I /d;/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols'
|
||||
_LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
|
||||
;;
|
||||
linux* | k*bsd*-gnu)
|
||||
_LT_AC_TAGVAR(link_all_deplibs, $1)=no
|
||||
|
@ -5481,7 +5655,7 @@ EOF
|
|||
_LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
|
||||
_LT_AC_TAGVAR(always_export_symbols, $1)=no
|
||||
_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
|
||||
_LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols'
|
||||
_LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
|
||||
|
||||
if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
|
||||
_LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
|
||||
|
@ -5499,7 +5673,7 @@ EOF
|
|||
fi
|
||||
;;
|
||||
|
||||
interix3*)
|
||||
interix[[3-9]]*)
|
||||
_LT_AC_TAGVAR(hardcode_direct, $1)=no
|
||||
_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
|
||||
_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
|
||||
|
@ -5514,7 +5688,7 @@ EOF
|
|||
_LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
|
||||
;;
|
||||
|
||||
linux* | k*bsd*-gnu)
|
||||
gnu* | linux* | k*bsd*-gnu)
|
||||
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||
tmp_addflag=
|
||||
case $cc_basename,$host_cpu in
|
||||
|
@ -5532,13 +5706,22 @@ EOF
|
|||
ifc* | ifort*) # Intel Fortran compiler
|
||||
tmp_addflag=' -nofor_main' ;;
|
||||
esac
|
||||
_LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
|
||||
case `$CC -V 2>&1 | sed 5q` in
|
||||
*Sun\ C*) # Sun C 5.9
|
||||
_LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
|
||||
tmp_sharedflag='-G' ;;
|
||||
*Sun\ F*) # Sun Fortran 8.3
|
||||
tmp_sharedflag='-G' ;;
|
||||
*)
|
||||
tmp_sharedflag='-shared' ;;
|
||||
esac
|
||||
_LT_AC_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
|
||||
|
||||
if test $supports_anon_versioning = yes; then
|
||||
_LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~
|
||||
cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
|
||||
$echo "local: *; };" >> $output_objdir/$libname.ver~
|
||||
$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
|
||||
$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
|
||||
fi
|
||||
_LT_AC_TAGVAR(link_all_deplibs, $1)=no
|
||||
else
|
||||
|
@ -5698,7 +5881,7 @@ _LT_EOF
|
|||
strings "$collect2name" | grep resolve_lib_name >/dev/null
|
||||
then
|
||||
# We have reworked collect2
|
||||
_LT_AC_TAGVAR(hardcode_direct, $1)=yes
|
||||
:
|
||||
else
|
||||
# We have old collect2
|
||||
_LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
|
||||
|
@ -5791,7 +5974,7 @@ _LT_EOF
|
|||
# The linker will automatically build a .lib file if we build a DLL.
|
||||
_LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true'
|
||||
# FIXME: Should let the user specify the lib program.
|
||||
_LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs'
|
||||
_LT_AC_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
|
||||
_LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`'
|
||||
_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
|
||||
;;
|
||||
|
@ -5833,10 +6016,10 @@ _LT_EOF
|
|||
case $cc_basename in
|
||||
xlc*)
|
||||
output_verbose_link_cmd='echo'
|
||||
_LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
|
||||
_LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring'
|
||||
_LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
|
||||
# Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
|
||||
_LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
|
||||
_LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
|
||||
_LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
|
||||
;;
|
||||
*)
|
||||
|
@ -5998,6 +6181,7 @@ _LT_EOF
|
|||
;;
|
||||
|
||||
openbsd*)
|
||||
if test -f /usr/libexec/ld.so; then
|
||||
_LT_AC_TAGVAR(hardcode_direct, $1)=yes
|
||||
_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
|
||||
if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
|
||||
|
@ -6017,6 +6201,9 @@ _LT_EOF
|
|||
;;
|
||||
esac
|
||||
fi
|
||||
else
|
||||
_LT_AC_TAGVAR(ld_shlibs, $1)=no
|
||||
fi
|
||||
;;
|
||||
|
||||
os2*)
|
||||
|
@ -6074,17 +6261,16 @@ _LT_EOF
|
|||
case $host_os in
|
||||
solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
|
||||
*)
|
||||
# The compiler driver will combine linker options so we
|
||||
# cannot just pass the convience library names through
|
||||
# without $wl, iff we do not link with $LD.
|
||||
# Luckily, gcc supports the same syntax we need for Sun Studio.
|
||||
# The compiler driver will combine and reorder linker options,
|
||||
# but understands `-z linker_flag'. GCC discards it without `$wl',
|
||||
# but is careful enough not to reorder.
|
||||
# Supported since Solaris 2.6 (maybe 2.5.1?)
|
||||
case $wlarc in
|
||||
'')
|
||||
_LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;;
|
||||
*)
|
||||
_LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
|
||||
esac ;;
|
||||
if test "$GCC" = yes; then
|
||||
_LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
|
||||
else
|
||||
_LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
_LT_AC_TAGVAR(link_all_deplibs, $1)=yes
|
||||
;;
|
||||
|
@ -6141,7 +6327,7 @@ _LT_EOF
|
|||
fi
|
||||
;;
|
||||
|
||||
sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7*)
|
||||
sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
|
||||
_LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
|
||||
_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
|
||||
_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
|
||||
|
@ -6216,7 +6402,7 @@ x|xyes)
|
|||
# to ld, don't add -lc before -lgcc.
|
||||
AC_MSG_CHECKING([whether -lc should be explicitly linked in])
|
||||
$rm conftest*
|
||||
printf "$lt_simple_compile_test_code" > conftest.$ac_ext
|
||||
echo "$lt_simple_compile_test_code" > conftest.$ac_ext
|
||||
|
||||
if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
|
||||
soname=conftest
|
||||
|
@ -6319,6 +6505,30 @@ AC_DEFUN([LT_AC_PROG_RC],
|
|||
[AC_CHECK_TOOL(RC, windres, no)
|
||||
])
|
||||
|
||||
|
||||
# Cheap backport of AS_EXECUTABLE_P and required macros
|
||||
# from Autoconf 2.59; we should not use $as_executable_p directly.
|
||||
|
||||
# _AS_TEST_PREPARE
|
||||
# ----------------
|
||||
m4_ifndef([_AS_TEST_PREPARE],
|
||||
[m4_defun([_AS_TEST_PREPARE],
|
||||
[if test -x / >/dev/null 2>&1; then
|
||||
as_executable_p='test -x'
|
||||
else
|
||||
as_executable_p='test -f'
|
||||
fi
|
||||
])])# _AS_TEST_PREPARE
|
||||
|
||||
# AS_EXECUTABLE_P
|
||||
# ---------------
|
||||
# Check whether a file is executable.
|
||||
m4_ifndef([AS_EXECUTABLE_P],
|
||||
[m4_defun([AS_EXECUTABLE_P],
|
||||
[AS_REQUIRE([_AS_TEST_PREPARE])dnl
|
||||
$as_executable_p $1[]dnl
|
||||
])])# AS_EXECUTABLE_P
|
||||
|
||||
# NOTE: This macro has been submitted for inclusion into #
|
||||
# GNU Autoconf as AC_PROG_SED. When it is available in #
|
||||
# a released version of Autoconf we should remove this #
|
||||
|
@ -6339,12 +6549,13 @@ do
|
|||
test -z "$as_dir" && as_dir=.
|
||||
for lt_ac_prog in sed gsed; do
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
|
||||
if AS_EXECUTABLE_P(["$as_dir/$lt_ac_prog$ac_exec_ext"]); then
|
||||
lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
|
||||
fi
|
||||
done
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
lt_ac_max=0
|
||||
lt_ac_count=0
|
||||
# Add /usr/xpg4/bin/sed as it is typically found on Solaris
|
||||
|
@ -6377,6 +6588,7 @@ for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
|
|||
done
|
||||
])
|
||||
SED=$lt_cv_path_SED
|
||||
AC_SUBST([SED])
|
||||
AC_MSG_RESULT([$SED])
|
||||
])
|
||||
|
||||
|
|
|
@ -75,19 +75,24 @@ AM_CONDITIONAL(USE_ALTIVEC, test x$use_altivec = xhas_altivec)
|
|||
|
||||
get_arch() {
|
||||
case "$1" in
|
||||
arm*) echo arm;;
|
||||
i?86) echo x86;;
|
||||
hppa*) echo hppa;;
|
||||
mips*) echo mips;;
|
||||
powerpc64) is_gcc_m64;;
|
||||
*) echo $1;;
|
||||
esac
|
||||
}
|
||||
|
||||
build_arch=`get_arch $build_cpu`
|
||||
host_arch=`get_arch $host_cpu`
|
||||
target_arch=`get_arch $target_cpu`
|
||||
|
||||
AM_CONDITIONAL(REMOTE_ONLY, test x$target_arch != x$build_arch)
|
||||
AM_CONDITIONAL(REMOTE_ONLY, test x$target_arch != x$host_arch)
|
||||
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)
|
||||
|
@ -101,7 +106,7 @@ if test x$target_arch = xppc64; then
|
|||
AC_SUBST([libdir])
|
||||
fi
|
||||
|
||||
if test x$target_arch != x$build_arch; then
|
||||
if test x$target_arch != x$host_arch; then
|
||||
CPPFLAGS="${CPPFLAGS} -DUNW_REMOTE_ONLY"
|
||||
fi
|
||||
AC_CONFIG_LINKS(include/libunwind.h:include/libunwind-$target_arch.h
|
||||
|
|
|
@ -60,10 +60,14 @@ AMDEP_TRUE = @AMDEP_TRUE@
|
|||
AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
ARCH = @ARCH@
|
||||
ARCH_ARM_FALSE = @ARCH_ARM_FALSE@
|
||||
ARCH_ARM_TRUE = @ARCH_ARM_TRUE@
|
||||
ARCH_HPPA_FALSE = @ARCH_HPPA_FALSE@
|
||||
ARCH_HPPA_TRUE = @ARCH_HPPA_TRUE@
|
||||
ARCH_IA64_FALSE = @ARCH_IA64_FALSE@
|
||||
ARCH_IA64_TRUE = @ARCH_IA64_TRUE@
|
||||
ARCH_MIPS_FALSE = @ARCH_MIPS_FALSE@
|
||||
ARCH_MIPS_TRUE = @ARCH_MIPS_TRUE@
|
||||
ARCH_PPC32_FALSE = @ARCH_PPC32_FALSE@
|
||||
ARCH_PPC32_TRUE = @ARCH_PPC32_TRUE@
|
||||
ARCH_PPC64_FALSE = @ARCH_PPC64_FALSE@
|
||||
|
@ -134,6 +138,7 @@ PKG_MINOR = @PKG_MINOR@
|
|||
RANLIB = @RANLIB@
|
||||
REMOTE_ONLY_FALSE = @REMOTE_ONLY_FALSE@
|
||||
REMOTE_ONLY_TRUE = @REMOTE_ONLY_TRUE@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
|
|
|
@ -329,6 +329,23 @@ struct dwarf_rs_cache
|
|||
dwarf_reg_state_t buckets[DWARF_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_find_proc_info UNW_OBJ (dwarf_find_proc_info)
|
||||
|
@ -363,6 +380,7 @@ extern int dwarf_extract_proc_info_from_fde (unw_addr_space_t as,
|
|||
unw_word_t *fde_addr,
|
||||
unw_proc_info_t *pi,
|
||||
int need_unwind_info,
|
||||
unw_word_t base,
|
||||
void *arg);
|
||||
extern int dwarf_find_save_locs (struct dwarf_cursor *c);
|
||||
extern int dwarf_create_state_record (struct dwarf_cursor *c,
|
||||
|
|
|
@ -9,6 +9,12 @@
|
|||
#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
|
||||
|
||||
#define dwarf_to_unw_regnum_map UNW_OBJ (dwarf_to_unw_regnum_map)
|
||||
|
||||
extern uint8_t dwarf_to_unw_regnum_map[DWARF_REGNUM_MAP_LENGTH];
|
||||
|
@ -22,7 +28,7 @@ extern uint8_t dwarf_to_unw_regnum_map[DWARF_REGNUM_MAP_LENGTH];
|
|||
/* 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
|
||||
typedef union __attribute__ ((packed))
|
||||
{
|
||||
int8_t s8;
|
||||
int16_t s16;
|
||||
|
@ -32,16 +38,15 @@ typedef union
|
|||
uint16_t u16;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
unw_word_t w;
|
||||
void *ptr;
|
||||
}
|
||||
dwarf_misaligned_value_t __attribute__ ((packed));
|
||||
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 *) *addr;
|
||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||
|
||||
*val = mvp->s8;
|
||||
*addr += sizeof (mvp->s8);
|
||||
|
@ -52,7 +57,7 @@ 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 *) *addr;
|
||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||
|
||||
*val = mvp->s16;
|
||||
*addr += sizeof (mvp->s16);
|
||||
|
@ -63,7 +68,7 @@ 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 *) *addr;
|
||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||
|
||||
*val = mvp->s32;
|
||||
*addr += sizeof (mvp->s32);
|
||||
|
@ -74,7 +79,7 @@ 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 *) *addr;
|
||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||
|
||||
*val = mvp->s64;
|
||||
*addr += sizeof (mvp->s64);
|
||||
|
@ -85,7 +90,7 @@ 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 *) *addr;
|
||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||
|
||||
*val = mvp->u8;
|
||||
*addr += sizeof (mvp->u8);
|
||||
|
@ -96,7 +101,7 @@ 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 *) *addr;
|
||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||
|
||||
*val = mvp->u16;
|
||||
*addr += sizeof (mvp->u16);
|
||||
|
@ -107,7 +112,7 @@ 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 *) *addr;
|
||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||
|
||||
*val = mvp->u32;
|
||||
*addr += sizeof (mvp->u32);
|
||||
|
@ -118,24 +123,13 @@ 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 *) *addr;
|
||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||
|
||||
*val = mvp->u64;
|
||||
*addr += sizeof (mvp->u64);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_readw (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
unw_word_t *val, void *arg)
|
||||
{
|
||||
dwarf_misaligned_value_t *mvp = (void *) *addr;
|
||||
|
||||
*val = mvp->w;
|
||||
*addr += sizeof (mvp->w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !UNW_LOCAL_ONLY */
|
||||
|
||||
static inline int
|
||||
|
@ -263,25 +257,37 @@ dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
|||
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)
|
||||
{
|
||||
switch (sizeof (unw_word_t))
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
int ret;
|
||||
|
||||
switch (dwarf_addr_size (as))
|
||||
{
|
||||
case 4:
|
||||
return dwarf_readu32 (as, a, addr, (uint32_t *) val, arg);
|
||||
ret = dwarf_readu32 (as, a, addr, &u32, arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = u32;
|
||||
return ret;
|
||||
|
||||
case 8:
|
||||
return dwarf_readu64 (as, a, addr, (uint64_t *) val, arg);
|
||||
ret = dwarf_readu64 (as, a, addr, &u64, arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = u64;
|
||||
return ret;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
|
||||
/* Read an unsigned "little-endian base 128" value. See Chapter 7.6
|
||||
of DWARF spec v3. */
|
||||
|
||||
|
@ -360,7 +366,8 @@ dwarf_read_encoded_pointer_inlined (unw_addr_space_t as, unw_accessors_t *a,
|
|||
}
|
||||
else if (encoding == DW_EH_PE_aligned)
|
||||
{
|
||||
*addr = (initial_addr + sizeof (unw_word_t) - 1) & -sizeof (unw_word_t);
|
||||
int size = dwarf_addr_size (as);
|
||||
*addr = (initial_addr + size - 1) & -size;
|
||||
return dwarf_readw (as, a, addr, valp, arg);
|
||||
}
|
||||
|
||||
|
@ -459,6 +466,15 @@ dwarf_read_encoded_pointer_inlined (unw_addr_space_t as, unw_accessors_t *a,
|
|||
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;
|
||||
|
|
298
include/libunwind-arm.h
Normal file
298
include/libunwind-arm.h
Normal file
|
@ -0,0 +1,298 @@
|
|||
/* 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 <ucontext.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 can directly use ucontext_t as the unwind context. */
|
||||
typedef ucontext_t 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 int unw_base asm ("r0") \
|
||||
= (int) (&unw_ctx->uc_mcontext.arm_r0); \
|
||||
__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 int unw_base asm ("r0") \
|
||||
= (int) (&unw_ctx->uc_mcontext.arm_r0); \
|
||||
__asm__ __volatile__ ( \
|
||||
".align 2\nbx pc\nnop\n.code 32\n" \
|
||||
"stmia %[base], {r0-r15}\n" \
|
||||
"orr %[base], pc, #1\nbx %[base]" \
|
||||
: [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 */
|
155
include/libunwind-mips.h
Normal file
155
include/libunwind-mips.h
Normal file
|
@ -0,0 +1,155 @@
|
|||
/* 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 <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. To allow a single library to support
|
||||
multiple ABIs, and to support N32 at all, we must use a 64-bit type
|
||||
even when addresses are only 32 bits. */
|
||||
typedef uint64_t unw_word_t;
|
||||
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,
|
||||
|
||||
/* 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_R31,
|
||||
|
||||
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 */
|
|
@ -11,7 +11,7 @@ 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 *) *addr;
|
||||
*valp = *(int8_t *) (uintptr_t) *addr;
|
||||
*addr += 1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ 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 *) *addr;
|
||||
*valp = *(int16_t *) (uintptr_t) *addr;
|
||||
*addr += 2;
|
||||
return 0;
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ 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 *) *addr;
|
||||
*valp = *(int32_t *) (uintptr_t) *addr;
|
||||
*addr += 4;
|
||||
return 0;
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ 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 *) *addr;
|
||||
*valp = *(unw_word_t *) (uintptr_t) *addr;
|
||||
*addr += sizeof (unw_word_t);
|
||||
return 0;
|
||||
}
|
||||
|
|
51
include/tdep-arm/dwarf-config.h
Normal file
51
include/tdep-arm/dwarf-config.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/* 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 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
|
||||
|
||||
/* FIXME: Probably unnecessary on ARM. See arm/Gglobal.c. */
|
||||
#define DWARF_REGNUM_MAP_LENGTH 16
|
||||
|
||||
/* 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 */
|
32
include/tdep-arm/jmpbuf.h
Normal file
32
include/tdep-arm/jmpbuf.h
Normal file
|
@ -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
|
254
include/tdep-arm/libunwind_i.h
Normal file
254
include/tdep-arm/libunwind_i.h
Normal file
|
@ -0,0 +1,254 @@
|
|||
/* 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"
|
||||
|
||||
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_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_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_uc_addr UNW_ARCH_OBJ(uc_addr)
|
||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||
|
||||
#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_needs_initialization;
|
||||
|
||||
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);
|
||||
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 /* ARM_LIBUNWIND_I_H */
|
|
@ -46,6 +46,7 @@ struct unw_addr_space
|
|||
#endif
|
||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||
struct unw_debug_frame_list *debug_frames;
|
||||
};
|
||||
|
||||
struct cursor
|
||||
|
|
54
include/tdep-mips/dwarf-config.h
Normal file
54
include/tdep-mips/dwarf-config.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/* 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 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
|
||||
|
||||
/* FIXME: Probably unnecessary on MIPS. See mips/Gglobal.c. */
|
||||
#define DWARF_REGNUM_MAP_LENGTH 32
|
||||
|
||||
/* 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 */
|
32
include/tdep-mips/jmpbuf.h
Normal file
32
include/tdep-mips/jmpbuf.h
Normal file
|
@ -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
|
315
include/tdep-mips/libunwind_i.h
Normal file
315
include/tdep-mips/libunwind_i.h
Normal file
|
@ -0,0 +1,315 @@
|
|||
/* 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"
|
||||
|
||||
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_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_uc_addr UNW_ARCH_OBJ(uc_addr)
|
||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||
|
||||
#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_needs_initialization;
|
||||
|
||||
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);
|
||||
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 */
|
|
@ -54,6 +54,7 @@ struct unw_addr_space
|
|||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ struct unw_addr_space
|
|||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ struct unw_addr_space
|
|||
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
|
||||
|
|
|
@ -50,6 +50,7 @@ struct unw_addr_space
|
|||
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;
|
||||
};
|
||||
|
||||
|
|
118
src/Makefile.am
118
src/Makefile.am
|
@ -33,9 +33,11 @@ libunwind_setjmp_la_LIBADD = libunwind-$(arch).la -lc
|
|||
libunwind_setjmp_la_SOURCES_common = setjmp/setjmp_i.h \
|
||||
setjmp/longjmp.c \
|
||||
setjmp/siglongjmp.c
|
||||
libunwind_setjmp_la_SOURCES_arm = arm/siglongjmp.S
|
||||
libunwind_setjmp_la_SOURCES_ia64 = ia64/setjmp.S ia64/sigsetjmp.S \
|
||||
ia64/longjmp.S ia64/siglongjmp.S
|
||||
libunwind_setjmp_la_SOURCES_hppa = hppa/siglongjmp.S
|
||||
libunwind_setjmp_la_SOURCES_mips = mips/siglongjmp.S
|
||||
libunwind_setjmp_la_SOURCES_x86 = x86/longjmp.S x86/siglongjmp.S
|
||||
libunwind_setjmp_la_SOURCES_x86_64 = x86_64/longjmp.S x86_64/siglongjmp.S
|
||||
libunwind_setjmp_la_SOURCES_ppc64 = ppc/longjmp.S ppc/siglongjmp.S
|
||||
|
@ -59,8 +61,17 @@ libunwind_la_SOURCES_generic = \
|
|||
mi/Gget_fpreg.c mi/Gset_fpreg.c \
|
||||
mi/Gset_caching_policy.c
|
||||
|
||||
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
|
||||
|
||||
# List of arch-independent files needed by local-only library (libunwind):
|
||||
libunwind_la_SOURCES_local = \
|
||||
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 \
|
||||
|
@ -70,14 +81,23 @@ libunwind_la_SOURCES_local = \
|
|||
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 \
|
||||
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
|
||||
mi/Lset_caching_policy.c
|
||||
|
||||
# On some platforms, defining _Unwind replacements really upsets
|
||||
# exception-handling. Turn off those functions for those platforms.
|
||||
if ARCH_ARM
|
||||
libunwind_la_SOURCES_local = \
|
||||
$(libunwind_la_SOURCES_local_nounwind)
|
||||
else
|
||||
if ARCH_MIPS
|
||||
libunwind_la_SOURCES_local = \
|
||||
$(libunwind_la_SOURCES_local_nounwind)
|
||||
else
|
||||
libunwind_la_SOURCES_local = \
|
||||
$(libunwind_la_SOURCES_local_nounwind) \
|
||||
$(libunwind_la_SOURCES_local_unwind)
|
||||
endif # ARCH_MIPS
|
||||
endif # ARCH_ARM
|
||||
|
||||
libunwind_la_SOURCES_os_linux = os-linux.h os-linux.c
|
||||
|
||||
|
@ -94,6 +114,31 @@ dwarf_SOURCES_local = \
|
|||
dwarf_SOURCES_generic = \
|
||||
dwarf/Gexpr.c dwarf/Gfde.c dwarf/Gparser.c dwarf/Gpe.c dwarf/Gstep.c
|
||||
|
||||
# The list of files that go info libunwind and libunwind-arm:
|
||||
libunwind_la_SOURCES_arm_common = $(libunwind_la_SOURCES_common) \
|
||||
$(dwarf_SOURCES_common) \
|
||||
elf32.c elf32.h \
|
||||
arm/init.h arm/offsets.h arm/regs.h \
|
||||
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_local) \
|
||||
arm/getcontext.S \
|
||||
$(dwarf_SOURCES_local) \
|
||||
dwarf/Lfind_proc_info-lsb.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/Lis_signal_frame.c arm/Lregs.c arm/Lresume.c arm/Lstep.c
|
||||
|
||||
libunwind_arm_la_SOURCES_arm = $(libunwind_la_SOURCES_arm_common) \
|
||||
$(libunwind_la_SOURCES_generic) \
|
||||
$(dwarf_SOURCES_generic) \
|
||||
dwarf/Gfind_proc_info-lsb.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/Gis_signal_frame.c arm/Gregs.c arm/Gresume.c arm/Gstep.c
|
||||
|
||||
# The list of files that go both into libunwind and libunwind-ia64:
|
||||
libunwind_la_SOURCES_ia64_common = $(libunwind_la_SOURCES_common) \
|
||||
elf64.c elf64.h \
|
||||
|
@ -150,6 +195,31 @@ libunwind_hppa_la_SOURCES_hppa = $(libunwind_la_SOURCES_hppa_common) \
|
|||
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:
|
||||
libunwind_la_SOURCES_mips_common = $(libunwind_la_SOURCES_common) \
|
||||
$(dwarf_SOURCES_common) \
|
||||
elfxx.c \
|
||||
mips/init.h mips/offsets.h mips/regs.h \
|
||||
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 \
|
||||
$(dwarf_SOURCES_local) \
|
||||
dwarf/Lfind_proc_info-lsb.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) \
|
||||
$(dwarf_SOURCES_generic) \
|
||||
dwarf/Gfind_proc_info-lsb.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 both into libunwind and libunwind-x86:
|
||||
libunwind_la_SOURCES_x86_common = $(libunwind_la_SOURCES_common) \
|
||||
$(dwarf_SOURCES_common) \
|
||||
|
@ -289,6 +359,17 @@ if OS_HPUX
|
|||
libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_hpux_local)
|
||||
endif
|
||||
|
||||
if ARCH_ARM
|
||||
lib_LTLIBRARIES_arch = 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)
|
||||
if !REMOTE_ONLY
|
||||
libunwind_arm_la_LIBADD = libunwind.la -lc
|
||||
endif
|
||||
libunwind_setjmp_la_SOURCES = $(libunwind_setjmp_la_SOURCES_common) \
|
||||
$(libunwind_setjmp_la_SOURCES_arm)
|
||||
else
|
||||
if ARCH_IA64
|
||||
ia64_mk_Gcursor_i_SOURCES = ia64/mk_Gcursor_i.c
|
||||
ia64_mk_Lcursor_i_SOURCES = ia64/mk_Lcursor_i.c
|
||||
|
@ -319,6 +400,17 @@ endif
|
|||
libunwind_setjmp_la_SOURCES = $(libunwind_setjmp_la_SOURCES_common) \
|
||||
$(libunwind_setjmp_la_SOURCES_hppa)
|
||||
else
|
||||
if ARCH_MIPS
|
||||
lib_LTLIBRARIES_arch = 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)
|
||||
if !REMOTE_ONLY
|
||||
libunwind_mips_la_LIBADD = libunwind.la -lc
|
||||
endif
|
||||
libunwind_setjmp_la_SOURCES = $(libunwind_setjmp_la_SOURCES_common) \
|
||||
$(libunwind_setjmp_la_SOURCES_mips)
|
||||
else
|
||||
if ARCH_X86
|
||||
lib_LTLIBRARIES_arch = libunwind-x86.la
|
||||
libunwind_la_SOURCES = $(libunwind_la_SOURCES_x86)
|
||||
|
@ -367,8 +459,10 @@ endif # ARCH_PPC64
|
|||
endif # ARCH_PPC32
|
||||
endif # ARCH_X86_64
|
||||
endif # ARCH_X86
|
||||
endif # ARCH_MIPS
|
||||
endif # ARCH_HPPA
|
||||
endif # ARCH_IA64
|
||||
endif # ARCH_ARM
|
||||
|
||||
#
|
||||
# Don't link with standard libraries, because those may mention
|
||||
|
@ -386,22 +480,28 @@ AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/tdep-$(arch) -I.
|
|||
AM_CCASFLAGS = $(AM_CPPFLAGS)
|
||||
|
||||
EXTRA_DIST = elfxx.h elfxx.c unwind/unwind-internal.h \
|
||||
$(libunwind_la_SOURCES_arm) \
|
||||
$(libunwind_la_SOURCES_hppa) \
|
||||
$(libunwind_la_SOURCES_ia64) \
|
||||
$(libunwind_la_SOURCES_mips) \
|
||||
$(libunwind_la_SOURCES_x86) \
|
||||
$(libunwind_la_SOURCES_os_linux) \
|
||||
$(libunwind_la_SOURCES_os_hpux) \
|
||||
$(libunwind_la_SOURCES_common) \
|
||||
$(libunwind_la_SOURCES_local) \
|
||||
$(libunwind_la_SOURCES_generic) \
|
||||
$(libunwind_arm_la_SOURCES_arm) \
|
||||
$(libunwind_hppa_la_SOURCES_hppa) \
|
||||
$(libunwind_ia64_la_SOURCES_ia64) \
|
||||
$(libunwind_mips_la_SOURCES_mips) \
|
||||
$(libunwind_x86_la_SOURCES_x86) \
|
||||
$(libunwind_x86_64_la_SOURCES_x86_64) \
|
||||
$(libunwind_ptrace_a_SOURCES) \
|
||||
$(libunwind_setjmp_la_SOURCES_common) \
|
||||
$(libunwind_setjmp_la_SOURCES_arm) \
|
||||
$(libunwind_setjmp_la_SOURCES_hppa) \
|
||||
$(libunwind_setjmp_la_SOURCES_ia64) \
|
||||
$(libunwind_setjmp_la_SOURCES_mips) \
|
||||
$(libunwind_setjmp_la_SOURCES_x86) \
|
||||
$(libunwind_setjmp_la_SOURCES_x86_64) \
|
||||
$(libunwind_setjmp_la_SOURCES_ppc32) \
|
||||
|
|
828
src/Makefile.in
828
src/Makefile.in
File diff suppressed because it is too large
Load diff
59
src/arm/Gcreate_addr_space.c
Normal file
59
src/arm/Gcreate_addr_space.c
Normal file
|
@ -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 <stdlib.h>
|
||||
|
||||
#include "unwind_i.h"
|
||||
|
||||
PROTECTED 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;
|
||||
|
||||
/*
|
||||
* ARM supports little-endian and big-endian.
|
||||
*/
|
||||
if (byte_order != 0 && byte_order != __LITTLE_ENDIAN
|
||||
&& byte_order != __BIG_ENDIAN)
|
||||
return NULL;
|
||||
|
||||
/* 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
|
||||
}
|
41
src/arm/Gget_proc_info.c
Normal file
41
src/arm/Gget_proc_info.c
Normal file
|
@ -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"
|
||||
|
||||
PROTECTED 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;
|
||||
}
|
81
src/arm/Gget_save_loc.c
Normal file
81
src/arm/Gget_save_loc.c
Normal file
|
@ -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"
|
||||
|
||||
PROTECTED 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;
|
||||
}
|
66
src/arm/Gglobal.c
Normal file
66
src/arm/Gglobal.c
Normal file
|
@ -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 <ucontext.h>
|
||||
#include "unwind_i.h"
|
||||
#include "dwarf_i.h"
|
||||
|
||||
HIDDEN pthread_mutex_t arm_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
HIDDEN int tdep_needs_initialization = 1;
|
||||
|
||||
/* FIXME: I'm pretty sure we don't need this at all for ARM, but "generic"
|
||||
code (include/dwarf_i.h) seems to expect it to be here at present. */
|
||||
|
||||
HIDDEN uint8_t dwarf_to_unw_regnum_map[16] =
|
||||
{
|
||||
R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15
|
||||
};
|
||||
|
||||
HIDDEN void
|
||||
tdep_init (void)
|
||||
{
|
||||
intrmask_t saved_mask;
|
||||
|
||||
sigfillset (&unwi_full_mask);
|
||||
|
||||
sigprocmask (SIG_SETMASK, &unwi_full_mask, &saved_mask);
|
||||
mutex_lock (&arm_lock);
|
||||
{
|
||||
if (!tdep_needs_initialization)
|
||||
/* another thread else beat us to it... */
|
||||
goto out;
|
||||
|
||||
mi_init ();
|
||||
|
||||
dwarf_init ();
|
||||
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
arm_local_addr_space_init ();
|
||||
#endif
|
||||
tdep_needs_initialization = 0; /* signal that we're initialized... */
|
||||
}
|
||||
out:
|
||||
mutex_unlock (&arm_lock);
|
||||
sigprocmask (SIG_SETMASK, &saved_mask, NULL);
|
||||
}
|
207
src/arm/Ginit.c
Normal file
207
src/arm/Ginit.c
Normal file
|
@ -0,0 +1,207 @@
|
|||
/* 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. */
|
||||
PROTECTED unw_addr_space_t unw_local_addr_space;
|
||||
|
||||
#else /* !UNW_REMOTE_ONLY */
|
||||
|
||||
static struct unw_addr_space local_addr_space;
|
||||
|
||||
PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space;
|
||||
|
||||
static inline void *
|
||||
uc_addr (ucontext_t *uc, int reg)
|
||||
{
|
||||
void *addr;
|
||||
|
||||
switch (reg)
|
||||
{
|
||||
case UNW_ARM_R0: addr = &uc->uc_mcontext.arm_r0; break;
|
||||
case UNW_ARM_R1: addr = &uc->uc_mcontext.arm_r1; break;
|
||||
case UNW_ARM_R2: addr = &uc->uc_mcontext.arm_r2; break;
|
||||
case UNW_ARM_R3: addr = &uc->uc_mcontext.arm_r3; break;
|
||||
case UNW_ARM_R4: addr = &uc->uc_mcontext.arm_r4; break;
|
||||
case UNW_ARM_R5: addr = &uc->uc_mcontext.arm_r5; break;
|
||||
case UNW_ARM_R6: addr = &uc->uc_mcontext.arm_r6; break;
|
||||
case UNW_ARM_R7: addr = &uc->uc_mcontext.arm_r7; break;
|
||||
case UNW_ARM_R8: addr = &uc->uc_mcontext.arm_r8; break;
|
||||
case UNW_ARM_R9: addr = &uc->uc_mcontext.arm_r9; break;
|
||||
case UNW_ARM_R10: addr = &uc->uc_mcontext.arm_r10; break;
|
||||
case UNW_ARM_R11: addr = &uc->uc_mcontext.arm_fp; break;
|
||||
case UNW_ARM_R12: addr = &uc->uc_mcontext.arm_ip; break;
|
||||
case UNW_ARM_R13: addr = &uc->uc_mcontext.arm_sp; break;
|
||||
case UNW_ARM_R14: addr = &uc->uc_mcontext.arm_lr; break;
|
||||
case UNW_ARM_R15: addr = &uc->uc_mcontext.arm_pc; break;
|
||||
|
||||
default:
|
||||
addr = NULL;
|
||||
}
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
arm_local_addr_space_init (void)
|
||||
{
|
||||
memset (&local_addr_space, 0, sizeof (local_addr_space));
|
||||
local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
|
||||
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 = 0; /* arm_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 */
|
53
src/arm/Ginit_local.c
Normal file
53
src/arm/Ginit_local.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* 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
|
||||
|
||||
PROTECTED int
|
||||
unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
|
||||
{
|
||||
return -UNW_EINVAL;
|
||||
}
|
||||
|
||||
#else /* !UNW_REMOTE_ONLY */
|
||||
|
||||
PROTECTED int
|
||||
unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
|
||||
{
|
||||
struct cursor *c = (struct cursor *) cursor;
|
||||
|
||||
if (tdep_needs_initialization)
|
||||
tdep_init ();
|
||||
|
||||
Debug (1, "(cursor=%p)\n", c);
|
||||
|
||||
c->dwarf.as = unw_local_addr_space;
|
||||
c->dwarf.as_arg = uc;
|
||||
return common_init (c);
|
||||
}
|
||||
|
||||
#endif /* !UNW_REMOTE_ONLY */
|
45
src/arm/Ginit_remote.c
Normal file
45
src/arm/Ginit_remote.c
Normal file
|
@ -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"
|
||||
|
||||
PROTECTED 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_needs_initialization)
|
||||
tdep_init ();
|
||||
|
||||
Debug (1, "(cursor=%p)\n", c);
|
||||
|
||||
c->dwarf.as = as;
|
||||
c->dwarf.as_arg = as_arg;
|
||||
return common_init (c);
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
}
|
35
src/arm/Gis_signal_frame.c
Normal file
35
src/arm/Gis_signal_frame.c
Normal file
|
@ -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 <stdio.h>
|
||||
#include "unwind_i.h"
|
||||
|
||||
/* FIXME for ARM. */
|
||||
|
||||
PROTECTED int
|
||||
unw_is_signal_frame (unw_cursor_t *cursor)
|
||||
{
|
||||
printf ("%s: implement me\n", __FUNCTION__);
|
||||
return -UNW_ENOINFO;
|
||||
}
|
81
src/arm/Gregs.c
Normal file
81
src/arm/Gregs.c
Normal file
|
@ -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"
|
||||
|
||||
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_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;
|
||||
|
||||
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;
|
||||
}
|
45
src/arm/Gresume.c
Normal file
45
src/arm/Gresume.c
Normal file
|
@ -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 ARM. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "unwind_i.h"
|
||||
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
|
||||
HIDDEN inline int
|
||||
arm_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
|
||||
{
|
||||
return -UNW_EINVAL;
|
||||
}
|
||||
|
||||
#endif /* !UNW_REMOTE_ONLY */
|
||||
|
||||
PROTECTED int
|
||||
unw_resume (unw_cursor_t *cursor)
|
||||
{
|
||||
return -UNW_EINVAL;
|
||||
}
|
48
src/arm/Gstep.c
Normal file
48
src/arm/Gstep.c
Normal file
|
@ -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"
|
||||
#include "offsets.h"
|
||||
|
||||
PROTECTED int
|
||||
unw_step (unw_cursor_t *cursor)
|
||||
{
|
||||
struct cursor *c = (struct cursor *) cursor;
|
||||
int ret;
|
||||
|
||||
Debug (1, "(cursor=%p)\n", c);
|
||||
|
||||
/* Try DWARF-based unwinding... this is the only method likely to work for
|
||||
ARM. */
|
||||
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;
|
||||
}
|
5
src/arm/Lcreate_addr_space.c
Normal file
5
src/arm/Lcreate_addr_space.c
Normal file
|
@ -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
|
5
src/arm/Lget_proc_info.c
Normal file
5
src/arm/Lget_proc_info.c
Normal file
|
@ -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
|
5
src/arm/Lget_save_loc.c
Normal file
5
src/arm/Lget_save_loc.c
Normal file
|
@ -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
|
5
src/arm/Lglobal.c
Normal file
5
src/arm/Lglobal.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Gglobal.c"
|
||||
#endif
|
5
src/arm/Linit.c
Normal file
5
src/arm/Linit.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Ginit.c"
|
||||
#endif
|
5
src/arm/Linit_local.c
Normal file
5
src/arm/Linit_local.c
Normal file
|
@ -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
|
5
src/arm/Linit_remote.c
Normal file
5
src/arm/Linit_remote.c
Normal file
|
@ -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
|
5
src/arm/Lis_signal_frame.c
Normal file
5
src/arm/Lis_signal_frame.c
Normal file
|
@ -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
|
5
src/arm/Lregs.c
Normal file
5
src/arm/Lregs.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Gregs.c"
|
||||
#endif
|
5
src/arm/Lresume.c
Normal file
5
src/arm/Lresume.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Gresume.c"
|
||||
#endif
|
5
src/arm/Lstep.c
Normal file
5
src/arm/Lstep.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Gstep.c"
|
||||
#endif
|
54
src/arm/gen-offsets.c
Normal file
54
src/arm/gen-offsets.c
Normal file
|
@ -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;
|
||||
}
|
52
src/arm/getcontext.S
Normal file
52
src/arm/getcontext.S
Normal file
|
@ -0,0 +1,52 @@
|
|||
/* 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
|
||||
str r0, [r0, #LINUX_UC_MCONTEXT_OFF + LINUX_SC_R0_OFF]
|
||||
add r0, r0, #LINUX_UC_MCONTEXT_OFF + LINUX_SC_R0_OFF
|
||||
@ 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
|
71
src/arm/init.h
Normal file
71
src/arm/init.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/* 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)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
c->dwarf.loc[R0] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R0);
|
||||
c->dwarf.loc[R1] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R1);
|
||||
c->dwarf.loc[R2] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R2);
|
||||
c->dwarf.loc[R3] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R3);
|
||||
c->dwarf.loc[R4] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R4);
|
||||
c->dwarf.loc[R5] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R5);
|
||||
c->dwarf.loc[R6] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R6);
|
||||
c->dwarf.loc[R7] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R7);
|
||||
c->dwarf.loc[R8] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R8);
|
||||
c->dwarf.loc[R9] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R9);
|
||||
c->dwarf.loc[R10] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R10);
|
||||
c->dwarf.loc[R11] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R11);
|
||||
c->dwarf.loc[R12] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R12);
|
||||
c->dwarf.loc[R13] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R13);
|
||||
c->dwarf.loc[R14] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R14);
|
||||
c->dwarf.loc[R15] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R15);
|
||||
for (i = R15 + 1; i < DWARF_NUM_PRESERVED_REGS; ++i)
|
||||
c->dwarf.loc[i] = DWARF_NULL_LOC;
|
||||
|
||||
ret = dwarf_get (&c->dwarf, c->dwarf.loc[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;
|
||||
|
||||
/* FIXME: Initialisation for other registers. */
|
||||
|
||||
c->dwarf.args_size = 0;
|
||||
c->dwarf.ret_addr_column = 0;
|
||||
c->dwarf.pi_valid = 0;
|
||||
c->dwarf.pi_is_dynamic = 0;
|
||||
c->dwarf.hint = 0;
|
||||
c->dwarf.prev_rs = 0;
|
||||
|
||||
return 0;
|
||||
}
|
39
src/arm/is_fpreg.c
Normal file
39
src/arm/is_fpreg.c
Normal file
|
@ -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. */
|
||||
|
||||
PROTECTED 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));
|
||||
}
|
36
src/arm/offsets.h
Normal file
36
src/arm/offsets.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* 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
|
90
src/arm/regname.c
Normal file
90
src/arm/regname.c
Normal file
|
@ -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",
|
||||
};
|
||||
|
||||
PROTECTED const char *
|
||||
unw_regname (unw_regnum_t reg)
|
||||
{
|
||||
if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
|
||||
return regname[reg];
|
||||
else
|
||||
return "???";
|
||||
}
|
8
src/arm/siglongjmp.S
Normal file
8
src/arm/siglongjmp.S
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* Dummy implementation for now. */
|
||||
|
||||
.globl _UI_siglongjmp_cont
|
||||
.globl _UI_longjmp_cont
|
||||
|
||||
_UI_siglongjmp_cont:
|
||||
_UI_longjmp_cont:
|
||||
bx lr
|
39
src/arm/unwind_i.h
Normal file
39
src/arm/unwind_i.h
Normal file
|
@ -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. */
|
||||
|
||||
#ifndef unwind_i_h
|
||||
#define unwind_i_h
|
||||
|
||||
#include <memory.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libunwind-arm.h>
|
||||
|
||||
#include "libunwind_i.h"
|
||||
|
||||
#define arm_local_addr_space_init UNW_OBJ(local_addr_space_init)
|
||||
|
||||
extern void arm_local_addr_space_init (void);
|
||||
|
||||
#endif /* unwind_i_h */
|
|
@ -47,10 +47,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|||
#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 uint8_t operands[256] =
|
||||
{
|
||||
[DW_OP_addr] = OPND1 (sizeof (unw_word_t) == 4 ? VAL32 : VAL64),
|
||||
[DW_OP_addr] = OPND1 (ADDR),
|
||||
[DW_OP_const1u] = OPND1 (VAL8),
|
||||
[DW_OP_const1s] = OPND1 (VAL8),
|
||||
[DW_OP_const2u] = OPND1 (VAL16),
|
||||
|
@ -106,7 +107,18 @@ static uint8_t operands[256] =
|
|||
[DW_OP_call_ref] = OPND1 (OFFSET)
|
||||
};
|
||||
|
||||
#define sword(X) ((unw_sword_t) (X))
|
||||
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,
|
||||
|
@ -118,25 +130,43 @@ read_operand (unw_addr_space_t as, unw_accessors_t *a,
|
|||
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;
|
||||
|
||||
|
@ -345,8 +375,10 @@ do { \
|
|||
tmp1 = pop ();
|
||||
switch (operand1)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
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)
|
||||
|
@ -379,7 +411,7 @@ do { \
|
|||
case 8:
|
||||
if ((ret = dwarf_readu64 (as, a, &tmp1, &u64, arg)) < 0)
|
||||
return ret;
|
||||
tmp2 = u16;
|
||||
tmp2 = u64;
|
||||
if (operand1 != 8)
|
||||
{
|
||||
if (dwarf_is_big_endian (as))
|
||||
|
@ -433,7 +465,7 @@ do { \
|
|||
case DW_OP_abs:
|
||||
Debug (15, "OP_abs\n");
|
||||
tmp1 = pop ();
|
||||
if (tmp1 & ((unw_word_t) 1 << (8 * sizeof (unw_word_t) - 1)))
|
||||
if (tmp1 & ((unw_word_t) 1 << (8 * dwarf_addr_size (as) - 1)))
|
||||
tmp1 = -tmp1;
|
||||
push (tmp1);
|
||||
break;
|
||||
|
@ -450,7 +482,7 @@ do { \
|
|||
tmp1 = pop ();
|
||||
tmp2 = pop ();
|
||||
if (tmp1)
|
||||
tmp1 = sword (tmp2) / sword (tmp1);
|
||||
tmp1 = sword (as, tmp2) / sword (as, tmp1);
|
||||
push (tmp1);
|
||||
break;
|
||||
|
||||
|
@ -528,7 +560,7 @@ do { \
|
|||
Debug (15, "OP_shra\n");
|
||||
tmp1 = pop ();
|
||||
tmp2 = pop ();
|
||||
push (sword (tmp2) >> tmp1);
|
||||
push (sword (as, tmp2) >> tmp1);
|
||||
break;
|
||||
|
||||
case DW_OP_xor:
|
||||
|
@ -542,42 +574,42 @@ do { \
|
|||
Debug (15, "OP_le\n");
|
||||
tmp1 = pop ();
|
||||
tmp2 = pop ();
|
||||
push (sword (tmp1) <= sword (tmp2));
|
||||
push (sword (as, tmp1) <= sword (as, tmp2));
|
||||
break;
|
||||
|
||||
case DW_OP_ge:
|
||||
Debug (15, "OP_ge\n");
|
||||
tmp1 = pop ();
|
||||
tmp2 = pop ();
|
||||
push (sword (tmp1) >= sword (tmp2));
|
||||
push (sword (as, tmp1) >= sword (as, tmp2));
|
||||
break;
|
||||
|
||||
case DW_OP_eq:
|
||||
Debug (15, "OP_eq\n");
|
||||
tmp1 = pop ();
|
||||
tmp2 = pop ();
|
||||
push (sword (tmp1) == sword (tmp2));
|
||||
push (sword (as, tmp1) == sword (as, tmp2));
|
||||
break;
|
||||
|
||||
case DW_OP_lt:
|
||||
Debug (15, "OP_lt\n");
|
||||
tmp1 = pop ();
|
||||
tmp2 = pop ();
|
||||
push (sword (tmp1) < sword (tmp2));
|
||||
push (sword (as, tmp1) < sword (as, tmp2));
|
||||
break;
|
||||
|
||||
case DW_OP_gt:
|
||||
Debug (15, "OP_gt\n");
|
||||
tmp1 = pop ();
|
||||
tmp2 = pop ();
|
||||
push (sword (tmp1) > sword (tmp2));
|
||||
push (sword (as, tmp1) > sword (as, tmp2));
|
||||
break;
|
||||
|
||||
case DW_OP_ne:
|
||||
Debug (15, "OP_ne\n");
|
||||
tmp1 = pop ();
|
||||
tmp2 = pop ();
|
||||
push (sword (tmp1) != sword (tmp2));
|
||||
push (sword (as, tmp1) != sword (as, tmp2));
|
||||
break;
|
||||
|
||||
case DW_OP_skip:
|
||||
|
|
|
@ -26,12 +26,15 @@ 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)
|
||||
is_cie_id (unw_word_t val, int is_debug_frame)
|
||||
{
|
||||
/* DWARF spec says CIE_id is 0xffffffff (for 32-bit ELF) or
|
||||
0xffffffffffffffff (for 64-bit ELF). However, the GNU toolchain
|
||||
/* The CIE ID is normally 0xffffffff (for 32-bit ELF) or
|
||||
0xffffffffffffffff (for 64-bit ELF). However, .eh_frame
|
||||
uses 0. */
|
||||
return (val == 0 || val == - (unw_word_t) 1);
|
||||
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
|
||||
|
@ -41,7 +44,8 @@ is_cie_id (unw_word_t val)
|
|||
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, void *arg)
|
||||
const unw_proc_info_t *pi, struct dwarf_cie_info *dci,
|
||||
unw_word_t base, void *arg)
|
||||
{
|
||||
uint8_t version, ch, augstr[5], fde_encoding, handler_encoding;
|
||||
unw_word_t len, cie_end_addr, aug_size;
|
||||
|
@ -57,7 +61,7 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
|||
"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 (sizeof (unw_word_t))
|
||||
switch (dwarf_addr_size (as))
|
||||
{
|
||||
case 4: fde_encoding = DW_EH_PE_udata4; break;
|
||||
case 8: fde_encoding = DW_EH_PE_udata8; break;
|
||||
|
@ -74,13 +78,14 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
|||
{
|
||||
/* 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 = (base) ? 0xffffffff : 0;
|
||||
|
||||
len = u32val;
|
||||
cie_end_addr = addr + len;
|
||||
if ((ret = dwarf_readu32 (as, a, &addr, &cie_id, arg)) < 0)
|
||||
return ret;
|
||||
/* DWARF says CIE id should be 0xffffffff, but in .eh_frame, it's 0 */
|
||||
if (cie_id != 0)
|
||||
if (cie_id != expected_id)
|
||||
{
|
||||
Debug (1, "Unexpected CIE id %x\n", cie_id);
|
||||
return -UNW_EINVAL;
|
||||
|
@ -90,6 +95,9 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
|||
{
|
||||
/* 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 = (base) ? 0xffffffffffffffffull : 0;
|
||||
|
||||
if ((ret = dwarf_readu64 (as, a, &addr, &u64val, arg)) < 0)
|
||||
return ret;
|
||||
|
@ -97,9 +105,7 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
|||
cie_end_addr = addr + len;
|
||||
if ((ret = dwarf_readu64 (as, a, &addr, &cie_id, arg)) < 0)
|
||||
return ret;
|
||||
/* DWARF says CIE id should be 0xffffffffffffffff, but in
|
||||
.eh_frame, it's 0 */
|
||||
if (cie_id != 0)
|
||||
if (cie_id != expected_id)
|
||||
{
|
||||
Debug (1, "Unexpected CIE id %llx\n", (long long) cie_id);
|
||||
return -UNW_EINVAL;
|
||||
|
@ -146,14 +152,16 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
|||
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 = 1; i < sizeof (augstr) && augstr[i]; ++i)
|
||||
for (; i < sizeof (augstr) && augstr[i]; ++i)
|
||||
switch (augstr[i])
|
||||
{
|
||||
case 'L':
|
||||
|
@ -185,16 +193,15 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
|||
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. */
|
||||
return 0;
|
||||
goto done;
|
||||
else
|
||||
{
|
||||
Debug (1, "Unexpected augmentation string `%s'\n", augstr);
|
||||
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",
|
||||
|
@ -202,12 +209,15 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Extract proc-info from the FDE starting at adress ADDR. */
|
||||
/* 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,
|
||||
int need_unwind_info,
|
||||
int need_unwind_info, unw_word_t base,
|
||||
void *arg)
|
||||
{
|
||||
unw_word_t fde_end_addr, cie_addr, cie_offset_addr, aug_end_addr = 0;
|
||||
|
@ -226,7 +236,7 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
|
|||
|
||||
if (u32val != 0xffffffff)
|
||||
{
|
||||
uint32_t cie_offset;
|
||||
int32_t cie_offset;
|
||||
|
||||
/* In some configurations, an FDE with a 0 length indicates the
|
||||
end of the FDE-table. */
|
||||
|
@ -241,10 +251,13 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
|
|||
if ((ret = dwarf_reads32 (as, a, &addr, &cie_offset, arg)) < 0)
|
||||
return ret;
|
||||
|
||||
if (is_cie_id (cie_offset))
|
||||
if (is_cie_id (cie_offset, base != 0))
|
||||
/* ignore CIEs (happens during linear searches) */
|
||||
return 0;
|
||||
|
||||
if (base != 0)
|
||||
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
|
||||
|
@ -253,7 +266,7 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
|
|||
}
|
||||
else
|
||||
{
|
||||
uint64_t cie_offset;
|
||||
int64_t cie_offset;
|
||||
|
||||
/* the FDE is in the 64-bit DWARF format */
|
||||
|
||||
|
@ -266,10 +279,13 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
|
|||
if ((ret = dwarf_reads64 (as, a, &addr, &cie_offset, arg)) < 0)
|
||||
return ret;
|
||||
|
||||
if (is_cie_id (cie_offset))
|
||||
if (is_cie_id (cie_offset, base != 0))
|
||||
/* ignore CIEs (happens during linear searches) */
|
||||
return 0;
|
||||
|
||||
if (base != 0)
|
||||
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
|
||||
|
@ -277,7 +293,9 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
|
|||
cie_addr = (unw_word_t) ((uint64_t) cie_offset_addr - cie_offset);
|
||||
}
|
||||
|
||||
if ((ret = parse_cie (as, a, cie_addr, pi, &dci, arg)) < 0)
|
||||
Debug (15, "looking for CIE at address %x\n", (int) cie_addr);
|
||||
|
||||
if ((ret = parse_cie (as, a, cie_addr, pi, &dci, base, arg)) < 0)
|
||||
return ret;
|
||||
|
||||
/* IP-range has same encoding as FDE pointers, except that it's
|
||||
|
|
|
@ -28,6 +28,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|||
|
||||
#include <link.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "dwarf_i.h"
|
||||
#include "dwarf-eh.h"
|
||||
|
@ -41,6 +43,10 @@ struct table_entry
|
|||
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
|
||||
#ifdef __linux
|
||||
#include "os-linux.h"
|
||||
#endif
|
||||
|
||||
struct callback_data
|
||||
{
|
||||
/* in: */
|
||||
|
@ -50,6 +56,7 @@ struct callback_data
|
|||
/* 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 */
|
||||
};
|
||||
|
||||
static int
|
||||
|
@ -65,7 +72,7 @@ linear_search (unw_addr_space_t as, unw_word_t ip,
|
|||
while (i++ < fde_count && addr < eh_frame_end)
|
||||
{
|
||||
fde_addr = addr;
|
||||
if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi, 0, arg))
|
||||
if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi, 0, 0, arg))
|
||||
< 0)
|
||||
return ret;
|
||||
|
||||
|
@ -75,7 +82,8 @@ linear_search (unw_addr_space_t as, unw_word_t ip,
|
|||
return 1;
|
||||
addr = fde_addr;
|
||||
if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi,
|
||||
need_unwind_info, arg))
|
||||
need_unwind_info, 0,
|
||||
arg))
|
||||
< 0)
|
||||
return ret;
|
||||
return 1;
|
||||
|
@ -84,8 +92,316 @@ linear_search (unw_addr_space_t as, unw_word_t ip,
|
|||
return -UNW_ENOINFO;
|
||||
}
|
||||
|
||||
/* Info is a pointer to a unw_dyn_info_t structure and, on entry,
|
||||
member u.rti.segbase contains the instruction-pointer we're looking
|
||||
/* 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; or
|
||||
-1 for recursive calls following .gnu_debuglink. 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)
|
||||
{
|
||||
FILE *f;
|
||||
Elf_W (Ehdr) ehdr;
|
||||
Elf_W (Half) shstrndx;
|
||||
Elf_W (Shdr) *sec_hdrs;
|
||||
char *stringtab;
|
||||
unsigned int i;
|
||||
size_t linksize = 0;
|
||||
char *linkbuf = NULL;
|
||||
|
||||
*buf = NULL;
|
||||
*bufsize = 0;
|
||||
|
||||
f = fopen (file, "r");
|
||||
|
||||
if (!f)
|
||||
return 1;
|
||||
|
||||
fread (&ehdr, sizeof (Elf_W (Ehdr)), 1, f);
|
||||
|
||||
shstrndx = ehdr.e_shstrndx;
|
||||
|
||||
Debug (4, "opened file '%s'. Section header at offset %d\n",
|
||||
file, (int) ehdr.e_shoff);
|
||||
|
||||
fseek (f, ehdr.e_shoff, SEEK_SET);
|
||||
sec_hdrs = calloc (ehdr.e_shnum, sizeof (Elf_W (Shdr)));
|
||||
fread (sec_hdrs, sizeof (Elf_W (Shdr)), ehdr.e_shnum, f);
|
||||
|
||||
Debug (4, "loading string table of size %d\n",
|
||||
sec_hdrs[shstrndx].sh_size);
|
||||
stringtab = malloc (sec_hdrs[shstrndx].sh_size);
|
||||
fseek (f, sec_hdrs[shstrndx].sh_offset, SEEK_SET);
|
||||
fread (stringtab, 1, sec_hdrs[shstrndx].sh_size, f);
|
||||
|
||||
for (i = 1; i < ehdr.e_shnum && *buf == NULL; i++)
|
||||
{
|
||||
char *secname = &stringtab[sec_hdrs[i].sh_name];
|
||||
|
||||
if (strcmp (secname, ".debug_frame") == 0)
|
||||
{
|
||||
*bufsize = sec_hdrs[i].sh_size;
|
||||
*buf = malloc (*bufsize);
|
||||
|
||||
fseek (f, sec_hdrs[i].sh_offset, SEEK_SET);
|
||||
fread (*buf, 1, *bufsize, f);
|
||||
|
||||
Debug (4, "read %d bytes of .debug_frame from offset %d\n",
|
||||
*bufsize, sec_hdrs[i].sh_offset);
|
||||
}
|
||||
else if (is_local >= 0 && strcmp (secname, ".gnu_debuglink") == 0)
|
||||
{
|
||||
linksize = sec_hdrs[i].sh_size;
|
||||
linkbuf = malloc (linksize);
|
||||
|
||||
fseek (f, sec_hdrs[i].sh_offset, SEEK_SET);
|
||||
fread (linkbuf, 1, linksize, f);
|
||||
|
||||
Debug (4, "read %d bytes of .gnu_debuglink from offset %d\n",
|
||||
*bufsize, sec_hdrs[i].sh_offset);
|
||||
}
|
||||
}
|
||||
|
||||
free (stringtab);
|
||||
free (sec_hdrs);
|
||||
|
||||
fclose (f);
|
||||
|
||||
if (*buf == NULL && linkbuf != NULL && memchr (linkbuf, 0, linksize) != NULL)
|
||||
{
|
||||
char *newname, *basedir, *p;
|
||||
static const char *debugdir = "/usr/lib/debug";
|
||||
int ret;
|
||||
|
||||
/* XXX: Don't bother with the checksum; just search for the file. */
|
||||
basedir = malloc (strlen (file) + 1);
|
||||
newname = malloc (strlen (linkbuf) + strlen (debugdir)
|
||||
+ strlen (file) + 9);
|
||||
|
||||
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 = load_debug_frame (newname, buf, bufsize, -1);
|
||||
|
||||
if (ret == 1)
|
||||
{
|
||||
strcpy (newname, basedir);
|
||||
strcat (newname, "/.debug/");
|
||||
strcat (newname, linkbuf);
|
||||
ret = load_debug_frame (newname, buf, bufsize, -1);
|
||||
}
|
||||
|
||||
if (ret == 1 && is_local == 1)
|
||||
{
|
||||
strcpy (newname, debugdir);
|
||||
strcat (newname, basedir);
|
||||
strcat (newname, "/");
|
||||
strcat (newname, linkbuf);
|
||||
ret = load_debug_frame (newname, buf, bufsize, -1);
|
||||
}
|
||||
|
||||
free (basedir);
|
||||
free (newname);
|
||||
}
|
||||
free (linkbuf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Locate the binary which originated the contents of address ADDR. Return
|
||||
the name of the binary in *name (which is allocated on the heap, and must
|
||||
be freed 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)
|
||||
{
|
||||
#ifdef __linux
|
||||
struct map_iterator mi;
|
||||
char path[PATH_MAX];
|
||||
int found = 0;
|
||||
int pid = getpid ();
|
||||
unsigned long segbase, mapoff, hi;
|
||||
|
||||
maps_init (&mi, pid);
|
||||
while (maps_next (&mi, &segbase, &hi, &mapoff, path, sizeof (path)))
|
||||
if (ip >= segbase && ip < hi)
|
||||
{
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
maps_close (&mi);
|
||||
|
||||
if (found)
|
||||
{
|
||||
*name = strdup (path);
|
||||
return 0;
|
||||
}
|
||||
#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, struct dl_phdr_info *info,
|
||||
unw_word_t addr, const char *dlname)
|
||||
{
|
||||
struct unw_debug_frame_list *w, *fdesc = 0;
|
||||
char *name = 0;
|
||||
int err;
|
||||
uint64_t start = 0, end = 0;
|
||||
char *buf;
|
||||
size_t bufsize;
|
||||
unsigned int i;
|
||||
|
||||
/* First, see if we loaded this frame already. */
|
||||
|
||||
for (w = as->debug_frames; w; w = w->next)
|
||||
{
|
||||
Debug (4, "checking %p: %x-%x\n", w, (int)w->start, (int)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);
|
||||
if (err)
|
||||
{
|
||||
Debug (15, "tried to locate binary for 0x%" PRIx64 ", but no luck\n",
|
||||
(uint64_t) addr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
name = (char*) dlname;
|
||||
|
||||
/* Find the start/end of the described region by parsing the
|
||||
dl_phdr_info structure. */
|
||||
|
||||
start = info->dlpi_addr + info->dlpi_phdr[0].p_vaddr;
|
||||
end = start;
|
||||
|
||||
for (i = 0; i < info->dlpi_phnum; i++)
|
||||
{
|
||||
Elf_W (Addr) hdrbase = info->dlpi_addr + info->dlpi_phdr[i].p_vaddr;
|
||||
Elf_W (Addr) hdrlimit = hdrbase + info->dlpi_phdr[i].p_memsz;
|
||||
|
||||
if (info->dlpi_phdr[i].p_type != PT_LOAD)
|
||||
continue;
|
||||
|
||||
if (hdrbase < start)
|
||||
start = hdrbase;
|
||||
if (hdrlimit > end)
|
||||
end = hdrlimit;
|
||||
}
|
||||
|
||||
Debug (4, "calculated bounds of %x-%x for '%s'\n", (int)start, (int)end,
|
||||
name);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (name && name != dlname)
|
||||
free (name);
|
||||
|
||||
return fdesc;
|
||||
}
|
||||
|
||||
struct debug_frame_tab
|
||||
{
|
||||
struct table_entry *tab;
|
||||
uint32_t length;
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
static struct debug_frame_tab *
|
||||
debug_frame_tab_new (unsigned int base_size)
|
||||
{
|
||||
struct debug_frame_tab *tab = malloc (sizeof (struct debug_frame_tab));
|
||||
|
||||
tab->tab = calloc (base_size, sizeof (struct table_entry));
|
||||
tab->length = 0;
|
||||
tab->size = base_size;
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* ptr is a pointer to a callback_data structure and, on entry,
|
||||
member ip contains the instruction-pointer we're looking
|
||||
for. */
|
||||
static int
|
||||
callback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||
|
@ -100,6 +416,8 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr)
|
|||
struct dwarf_eh_frame_hdr *hdr;
|
||||
unw_accessors_t *a;
|
||||
long n;
|
||||
struct unw_debug_frame_list *fdesc = 0;
|
||||
int found = 0;
|
||||
|
||||
ip = cb_data->ip;
|
||||
|
||||
|
@ -136,9 +454,12 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr)
|
|||
else if (phdr->p_type == PT_DYNAMIC)
|
||||
p_dynamic = phdr;
|
||||
}
|
||||
if (!p_text || !p_eh_hdr)
|
||||
|
||||
if (!p_text)
|
||||
return 0;
|
||||
|
||||
if (p_eh_hdr)
|
||||
{
|
||||
if (likely (p_eh_hdr->p_vaddr >= p_text->p_vaddr
|
||||
&& p_eh_hdr->p_vaddr < p_text->p_vaddr + p_text->p_memsz))
|
||||
/* normal case: eh-hdr is inside text segment */
|
||||
|
@ -191,7 +512,7 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr)
|
|||
}
|
||||
|
||||
a = unw_get_accessors (unw_local_addr_space);
|
||||
addr = (unw_word_t) (hdr + 1);
|
||||
addr = (unw_word_t) (uintptr_t) (hdr + 1);
|
||||
|
||||
/* (Optionally) read eh_frame_ptr: */
|
||||
if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
|
||||
|
@ -223,30 +544,171 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr)
|
|||
if (hdr->eh_frame_ptr_enc == DW_EH_PE_omit)
|
||||
abort ();
|
||||
|
||||
/* XXX we know how to build a local binary search table for
|
||||
.debug_frame, so we could do that here too. */
|
||||
cb_data->single_fde = 1;
|
||||
return linear_search (unw_local_addr_space, ip,
|
||||
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;
|
||||
}
|
||||
|
||||
cb_data->single_fde = 0;
|
||||
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) info->dlpi_name;
|
||||
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) hdr;
|
||||
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 *) di->u.rti.name_ptr,
|
||||
"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);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
Debug (15, "Trying to find .debug_frame\n");
|
||||
di = &cb_data->di_debug;
|
||||
fdesc = locate_debug_info (unw_local_addr_space, info, ip, info->dlpi_name);
|
||||
|
||||
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 (unw_local_addr_space);
|
||||
|
||||
/* Find all FDE entries in debug_frame, and make into a sorted
|
||||
index. */
|
||||
|
||||
tab = debug_frame_tab_new (16);
|
||||
|
||||
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, 0,
|
||||
(uintptr_t) buf,
|
||||
NULL);
|
||||
if (err == 0)
|
||||
{
|
||||
Debug (15, "start_ip = %x, end_ip = %x\n",
|
||||
(int) this_pi.start_ip, (int) 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;
|
||||
free (tab);
|
||||
}
|
||||
|
||||
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) info->dlpi_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 = (unw_word_t) (uintptr_t) info->dlpi_addr;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
HIDDEN int
|
||||
|
@ -259,9 +721,12 @@ dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
|||
|
||||
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 (callback, &cb_data);
|
||||
|
@ -276,14 +741,22 @@ dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
|||
if (cb_data.single_fde)
|
||||
/* already got the result in *pi */
|
||||
return 0;
|
||||
else
|
||||
|
||||
/* search the table: */
|
||||
return dwarf_search_unwind_table (as, ip, &cb_data.di,
|
||||
if (cb_data.di.format != -1)
|
||||
ret = dwarf_search_unwind_table (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 (as, ip, &cb_data.di_debug, pi,
|
||||
need_unwind_info, arg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline const struct table_entry *
|
||||
lookup (struct table_entry *table, size_t table_size, int32_t rel_ip)
|
||||
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 = 0;
|
||||
|
@ -294,6 +767,7 @@ lookup (struct table_entry *table, size_t table_size, int32_t rel_ip)
|
|||
{
|
||||
mid = (lo + hi) / 2;
|
||||
e = table + mid;
|
||||
Debug (1, "e->start_ip_offset = %x\n", (int) e->start_ip_offset);
|
||||
if (rel_ip < e->start_ip_offset)
|
||||
hi = mid;
|
||||
else
|
||||
|
@ -353,16 +827,47 @@ 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;
|
||||
const struct table_entry *e = NULL, *table;
|
||||
unw_word_t segbase = 0, 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 (di->format == UNW_INFO_FORMAT_REMOTE_TABLE);
|
||||
#else
|
||||
assert (di->format == UNW_INFO_FORMAT_REMOTE_TABLE
|
||||
&& (ip >= di->start_ip && ip < di->end_ip));
|
||||
|| di->format == UNW_INFO_FORMAT_TABLE);
|
||||
#endif
|
||||
assert (ip >= di->start_ip && ip < di->end_ip);
|
||||
|
||||
if (di->format == UNW_INFO_FORMAT_REMOTE_TABLE)
|
||||
{
|
||||
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
|
||||
{
|
||||
#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 currently only
|
||||
supported for the 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. When the ptrace code adds support for
|
||||
.debug_frame something will have to change. */
|
||||
assert (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 (as);
|
||||
|
||||
|
@ -370,16 +875,14 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
|||
if (as == unw_local_addr_space)
|
||||
{
|
||||
segbase = di->u.rti.segbase;
|
||||
e = lookup ((struct table_entry *) di->u.rti.table_data,
|
||||
di->u.rti.table_len * sizeof (unw_word_t), ip - segbase);
|
||||
e = lookup (table, table_len, ip - segbase);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifndef UNW_LOCAL_ONLY
|
||||
segbase = di->u.rti.segbase;
|
||||
if ((ret = remote_lookup (as, di->u.rti.table_data,
|
||||
di->u.rti.table_len * sizeof (unw_word_t),
|
||||
if ((ret = remote_lookup (as, (uintptr_t) table, table_len,
|
||||
ip - segbase, &ent, arg)) < 0)
|
||||
return ret;
|
||||
if (ret)
|
||||
|
@ -390,17 +893,34 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
|||
}
|
||||
if (!e)
|
||||
{
|
||||
Debug (1, "IP %x inside range %x-%x, but no explicit unwind info found\n",
|
||||
(int) ip, (int) di->start_ip, (int) 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 + segbase));
|
||||
(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 = %x, segbase = %x, debug_frame_base = %x, "
|
||||
"fde_addr = %x\n", (int) e->fde_offset, (int) segbase,
|
||||
(int) debug_frame_base, (int) fde_addr);
|
||||
if ((ret = dwarf_extract_proc_info_from_fde (as, a, &fde_addr, pi,
|
||||
need_unwind_info, arg)) < 0)
|
||||
need_unwind_info,
|
||||
debug_frame_base, 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;
|
||||
}
|
||||
|
||||
if (ip < pi->start_ip || ip >= pi->end_ip)
|
||||
return -UNW_ENOINFO;
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ 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,
|
||||
|
|
|
@ -49,7 +49,7 @@ local_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
|
|||
return -UNW_ENOINFO;
|
||||
#endif
|
||||
|
||||
list = (unw_dyn_info_list_t *) _U_dyn_info_list_addr ();
|
||||
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,
|
||||
|
|
|
@ -49,7 +49,7 @@ backtrace (void **buffer, int size)
|
|||
|
||||
if (unw_get_reg (&cursor, UNW_REG_IP, &ip) < 0)
|
||||
return n;
|
||||
buffer[n++] = (void *) ip;
|
||||
buffer[n++] = (void *) (uintptr_t) ip;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
|
|
@ -30,5 +30,5 @@ HIDDEN unw_dyn_info_list_t _U_dyn_info_list;
|
|||
PROTECTED unw_word_t
|
||||
_U_dyn_info_list_addr (void)
|
||||
{
|
||||
return (unw_word_t) &_U_dyn_info_list;
|
||||
return (unw_word_t) (uintptr_t) &_U_dyn_info_list;
|
||||
}
|
||||
|
|
|
@ -28,9 +28,23 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|||
PROTECTED 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
|
||||
|
|
65
src/mips/Gcreate_addr_space.c
Normal file
65
src/mips/Gcreate_addr_space.c
Normal file
|
@ -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 <stdlib.h>
|
||||
|
||||
#include "unwind_i.h"
|
||||
|
||||
PROTECTED 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;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
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
|
||||
}
|
41
src/mips/Gget_proc_info.c
Normal file
41
src/mips/Gget_proc_info.c
Normal file
|
@ -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"
|
||||
|
||||
PROTECTED 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;
|
||||
}
|
99
src/mips/Gget_save_loc.c
Normal file
99
src/mips/Gget_save_loc.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
/* 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. */
|
||||
|
||||
PROTECTED 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:
|
||||
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;
|
||||
}
|
66
src/mips/Gglobal.c
Normal file
66
src/mips/Gglobal.c
Normal file
|
@ -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 "unwind_i.h"
|
||||
#include "dwarf_i.h"
|
||||
|
||||
HIDDEN pthread_mutex_t mips_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
HIDDEN int tdep_needs_initialization = 1;
|
||||
|
||||
/* FIXME: I'm pretty sure we don't need this at all for MIPS, but "generic"
|
||||
code (include/dwarf_i.h) seems to expect it to be here at present. */
|
||||
|
||||
HIDDEN 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
|
||||
};
|
||||
|
||||
HIDDEN void
|
||||
tdep_init (void)
|
||||
{
|
||||
intrmask_t saved_mask;
|
||||
|
||||
sigfillset (&unwi_full_mask);
|
||||
|
||||
sigprocmask (SIG_SETMASK, &unwi_full_mask, &saved_mask);
|
||||
mutex_lock (&mips_lock);
|
||||
{
|
||||
if (!tdep_needs_initialization)
|
||||
/* another thread else beat us to it... */
|
||||
goto out;
|
||||
|
||||
mi_init ();
|
||||
|
||||
dwarf_init ();
|
||||
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
mips_local_addr_space_init ();
|
||||
#endif
|
||||
tdep_needs_initialization = 0; /* signal that we're initialized... */
|
||||
}
|
||||
out:
|
||||
mutex_unlock (&mips_lock);
|
||||
sigprocmask (SIG_SETMASK, &saved_mask, NULL);
|
||||
}
|
208
src/mips/Ginit.c
Normal file
208
src/mips/Ginit.c
Normal file
|
@ -0,0 +1,208 @@
|
|||
/* 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. */
|
||||
PROTECTED unw_addr_space_t unw_local_addr_space;
|
||||
|
||||
#else /* !UNW_REMOTE_ONLY */
|
||||
|
||||
static struct unw_addr_space local_addr_space;
|
||||
|
||||
PROTECTED 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
|
||||
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
|
||||
&& 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 = UNW_CACHE_GLOBAL;
|
||||
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 = 0; /* 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 */
|
53
src/mips/Ginit_local.c
Normal file
53
src/mips/Ginit_local.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* 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
|
||||
|
||||
PROTECTED int
|
||||
unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
|
||||
{
|
||||
return -UNW_EINVAL;
|
||||
}
|
||||
|
||||
#else /* !UNW_REMOTE_ONLY */
|
||||
|
||||
PROTECTED int
|
||||
unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
|
||||
{
|
||||
struct cursor *c = (struct cursor *) cursor;
|
||||
|
||||
if (tdep_needs_initialization)
|
||||
tdep_init ();
|
||||
|
||||
Debug (1, "(cursor=%p)\n", c);
|
||||
|
||||
c->dwarf.as = unw_local_addr_space;
|
||||
c->dwarf.as_arg = uc;
|
||||
return common_init (c);
|
||||
}
|
||||
|
||||
#endif /* !UNW_REMOTE_ONLY */
|
45
src/mips/Ginit_remote.c
Normal file
45
src/mips/Ginit_remote.c
Normal file
|
@ -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"
|
||||
|
||||
PROTECTED 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_needs_initialization)
|
||||
tdep_init ();
|
||||
|
||||
Debug (1, "(cursor=%p)\n", c);
|
||||
|
||||
c->dwarf.as = as;
|
||||
c->dwarf.as_arg = as_arg;
|
||||
return common_init (c);
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
}
|
35
src/mips/Gis_signal_frame.c
Normal file
35
src/mips/Gis_signal_frame.c
Normal file
|
@ -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 "unwind_i.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/* FIXME for MIPS. */
|
||||
|
||||
PROTECTED int
|
||||
unw_is_signal_frame (unw_cursor_t *cursor)
|
||||
{
|
||||
printf ("%s: implement me\n", __FUNCTION__);
|
||||
return -UNW_ENOINFO;
|
||||
}
|
99
src/mips/Gregs.c
Normal file
99
src/mips/Gregs.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
/* 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_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;
|
||||
}
|
45
src/mips/Gresume.c
Normal file
45
src/mips/Gresume.c
Normal file
|
@ -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 */
|
||||
|
||||
PROTECTED int
|
||||
unw_resume (unw_cursor_t *cursor)
|
||||
{
|
||||
return -UNW_EINVAL;
|
||||
}
|
48
src/mips/Gstep.c
Normal file
48
src/mips/Gstep.c
Normal file
|
@ -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"
|
||||
#include "offsets.h"
|
||||
|
||||
PROTECTED int
|
||||
unw_step (unw_cursor_t *cursor)
|
||||
{
|
||||
struct cursor *c = (struct cursor *) cursor;
|
||||
int ret;
|
||||
|
||||
Debug (1, "(cursor=%p)\n", c);
|
||||
|
||||
/* Try DWARF-based unwinding... this is the only method likely to work for
|
||||
MIPS. */
|
||||
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;
|
||||
}
|
5
src/mips/Lcreate_addr_space.c
Normal file
5
src/mips/Lcreate_addr_space.c
Normal file
|
@ -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
|
5
src/mips/Lget_proc_info.c
Normal file
5
src/mips/Lget_proc_info.c
Normal file
|
@ -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
|
5
src/mips/Lget_save_loc.c
Normal file
5
src/mips/Lget_save_loc.c
Normal file
|
@ -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
|
5
src/mips/Lglobal.c
Normal file
5
src/mips/Lglobal.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Gglobal.c"
|
||||
#endif
|
5
src/mips/Linit.c
Normal file
5
src/mips/Linit.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Ginit.c"
|
||||
#endif
|
5
src/mips/Linit_local.c
Normal file
5
src/mips/Linit_local.c
Normal file
|
@ -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
|
5
src/mips/Linit_remote.c
Normal file
5
src/mips/Linit_remote.c
Normal file
|
@ -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
|
5
src/mips/Lis_signal_frame.c
Normal file
5
src/mips/Lis_signal_frame.c
Normal file
|
@ -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
|
5
src/mips/Lregs.c
Normal file
5
src/mips/Lregs.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Gregs.c"
|
||||
#endif
|
5
src/mips/Lresume.c
Normal file
5
src/mips/Lresume.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Gresume.c"
|
||||
#endif
|
5
src/mips/Lstep.c
Normal file
5
src/mips/Lstep.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Gstep.c"
|
||||
#endif
|
27
src/mips/elfxx.c
Normal file
27
src/mips/elfxx.c
Normal file
|
@ -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"
|
30
src/mips/gen-offsets.c
Normal file
30
src/mips/gen-offsets.c
Normal file
|
@ -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;
|
||||
}
|
85
src/mips/getcontext.S
Normal file
85
src/mips/getcontext.S
Normal file
|
@ -0,0 +1,85 @@
|
|||
/* 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"
|
||||
#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)
|
||||
#else
|
||||
# define SREG(X) sd $X, (LINUX_UC_MCONTEXT_GREGS + 8 * X) ($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)
|
||||
li $2, 0
|
||||
j $31
|
||||
|
||||
.size _Umips_getcontext, .-_Umips_getcontext
|
56
src/mips/init.h
Normal file
56
src/mips/init.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* 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)
|
||||
{
|
||||
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;
|
||||
|
||||
ret = dwarf_get (&c->dwarf, c->dwarf.loc[31], &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.ret_addr_column = 0;
|
||||
c->dwarf.pi_valid = 0;
|
||||
c->dwarf.pi_is_dynamic = 0;
|
||||
c->dwarf.hint = 0;
|
||||
c->dwarf.prev_rs = 0;
|
||||
|
||||
return 0;
|
||||
}
|
35
src/mips/is_fpreg.c
Normal file
35
src/mips/is_fpreg.c
Normal file
|
@ -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. */
|
||||
|
||||
PROTECTED int
|
||||
unw_is_fpreg (int regnum)
|
||||
{
|
||||
/* FIXME: Support FP. */
|
||||
return 0;
|
||||
}
|
39
src/mips/offsets.h
Normal file
39
src/mips/offsets.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/* 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": */
|
||||
|
||||
#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_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_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_GREGS 0x28
|
||||
|
||||
#endif
|
46
src/mips/regname.c
Normal file
46
src/mips/regname.c
Normal file
|
@ -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. */
|
||||
|
||||
#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",
|
||||
};
|
||||
|
||||
PROTECTED const char *
|
||||
unw_regname (unw_regnum_t reg)
|
||||
{
|
||||
if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
|
||||
return regname[reg];
|
||||
else
|
||||
return "???";
|
||||
}
|
8
src/mips/siglongjmp.S
Normal file
8
src/mips/siglongjmp.S
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* Dummy implementation for now. */
|
||||
|
||||
.globl _UI_siglongjmp_cont
|
||||
.globl _UI_longjmp_cont
|
||||
|
||||
_UI_siglongjmp_cont:
|
||||
_UI_longjmp_cont:
|
||||
j $31
|
48
src/mips/unwind_i.h
Normal file
48
src/mips/unwind_i.h
Normal file
|
@ -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. */
|
||||
|
||||
#ifndef unwind_i_h
|
||||
#define unwind_i_h
|
||||
|
||||
#include <memory.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libunwind-mips.h>
|
||||
|
||||
#include "libunwind_i.h"
|
||||
|
||||
/*
|
||||
#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)
|
||||
|
||||
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 void mips_local_addr_space_init (void);
|
||||
|
||||
#endif /* unwind_i_h */
|
|
@ -288,6 +288,8 @@ int _UPT_reg_offset[UNW_REG_LAST + 1] =
|
|||
// [UNW_X86_64_SS] = 0xa0
|
||||
#elif defined(UNW_TARGET_PPC32)
|
||||
#elif defined(UNW_TARGET_PPC64)
|
||||
#elif defined(UNW_TARGET_ARM)
|
||||
#elif defined(UNW_TARGET_MIPS)
|
||||
#else
|
||||
# error Fix me.
|
||||
#endif
|
||||
|
|
|
@ -63,7 +63,7 @@ _longjmp (jmp_buf env, int val)
|
|||
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) &_UI_longjmp_cont))
|
||||
(unw_word_t) (uintptr_t) &_UI_longjmp_cont))
|
||||
abort ();
|
||||
|
||||
unw_resume (&c);
|
||||
|
|
|
@ -81,7 +81,7 @@ siglongjmp (sigjmp_buf env, int val)
|
|||
|
||||
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) cont))
|
||||
|| unw_set_reg (&c, UNW_REG_IP, (unw_word_t) (uintptr_t) cont))
|
||||
abort ();
|
||||
|
||||
unw_resume (&c);
|
||||
|
|
|
@ -30,11 +30,12 @@ _Unwind_FindEnclosingFunction (void *ip)
|
|||
{
|
||||
unw_proc_info_t pi;
|
||||
|
||||
if (unw_get_proc_info_by_ip (unw_local_addr_space, (unw_word_t) ip, &pi, 0)
|
||||
if (unw_get_proc_info_by_ip (unw_local_addr_space,
|
||||
(unw_word_t) (uintptr_t) ip, &pi, 0)
|
||||
< 0)
|
||||
return NULL;
|
||||
|
||||
return (void *) pi.start_ip;
|
||||
return (void *) (uintptr_t) pi.start_ip;
|
||||
}
|
||||
|
||||
void *__libunwind_Unwind_FindEnclosingFunction (void *)
|
||||
|
|
|
@ -60,7 +60,7 @@ _Unwind_RaiseException (struct _Unwind_Exception *exception_object)
|
|||
if (unw_get_proc_info (&context.cursor, &pi) < 0)
|
||||
return _URC_FATAL_PHASE1_ERROR;
|
||||
|
||||
personality = (_Unwind_Personality_Fn) pi.handler;
|
||||
personality = (_Unwind_Personality_Fn) (uintptr_t) pi.handler;
|
||||
if (personality)
|
||||
{
|
||||
reason = (*personality) (_U_VERSION, _UA_SEARCH_PHASE,
|
||||
|
|
|
@ -103,7 +103,7 @@ _Unwind_Phase2 (struct _Unwind_Exception *exception_object,
|
|||
|| unw_get_proc_info (&context->cursor, &pi) < 0)
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
|
||||
personality = (_Unwind_Personality_Fn) pi.handler;
|
||||
personality = (_Unwind_Personality_Fn) (uintptr_t) pi.handler;
|
||||
if (personality)
|
||||
{
|
||||
if (!stop)
|
||||
|
|
|
@ -322,10 +322,14 @@ AMDEP_TRUE = @AMDEP_TRUE@
|
|||
AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
ARCH = @ARCH@
|
||||
ARCH_ARM_FALSE = @ARCH_ARM_FALSE@
|
||||
ARCH_ARM_TRUE = @ARCH_ARM_TRUE@
|
||||
ARCH_HPPA_FALSE = @ARCH_HPPA_FALSE@
|
||||
ARCH_HPPA_TRUE = @ARCH_HPPA_TRUE@
|
||||
ARCH_IA64_FALSE = @ARCH_IA64_FALSE@
|
||||
ARCH_IA64_TRUE = @ARCH_IA64_TRUE@
|
||||
ARCH_MIPS_FALSE = @ARCH_MIPS_FALSE@
|
||||
ARCH_MIPS_TRUE = @ARCH_MIPS_TRUE@
|
||||
ARCH_PPC32_FALSE = @ARCH_PPC32_FALSE@
|
||||
ARCH_PPC32_TRUE = @ARCH_PPC32_TRUE@
|
||||
ARCH_PPC64_FALSE = @ARCH_PPC64_FALSE@
|
||||
|
@ -396,6 +400,7 @@ PKG_MINOR = @PKG_MINOR@
|
|||
RANLIB = @RANLIB@
|
||||
REMOTE_ONLY_FALSE = @REMOTE_ONLY_FALSE@
|
||||
REMOTE_ONLY_TRUE = @REMOTE_ONLY_TRUE@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
|
|
Loading…
Reference in a new issue