diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..e97c570c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 2.8) + +add_subdirectory(src) + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 00000000..6ff95b36 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,102 @@ + + +set(libunwind_sources_common + os-linux.c + mi/init.c + mi/flush_cache.c + mi/mempool.c + mi/strerror.c + dwarf/global.c + mi/backtrace.c + mi/dyn-cancel.c + mi/dyn-info-list.c + mi/dyn-register.c + mi/Ldyn-extract.c + mi/Lfind_dynamic_proc_info.c + mi/Lget_accessors.c + mi/Lget_proc_info_by_ip.c + mi/Lget_proc_name.c + mi/Lput_dynamic_unwind_info.c + mi/Ldestroy_addr_space.c + mi/Lget_reg.c + mi/Lset_reg.c + mi/Lget_fpreg.c + mi/Lset_fpreg.c + mi/Lset_caching_policy.c + dwarf/Lexpr.c + dwarf/Lfde.c + dwarf/Lparser.c + dwarf/Lpe.c + dwarf/Lstep.c + dwarf/Lfind_proc_info-lsb.c + ) + +set(libunwind_sources_x8664_32 + elf32.c + x86/is_fpreg.c + x86/regname.c + x86/setcontext.c + x86/Lcreate_addr_space.c + x86/Lget_save_loc.c + x86/Lglobal.c + x86/Linit.c + x86/Linit_local.c + x86/Linit_remote.c + x86/Lis_signal_frame.c + x86/Lget_proc_info.c + x86/Lregs.c + x86/Lresume.c + x86/getcontext.c + x86/Lstep.c + ) + +set(libunwind_sources_x8664_64 + elf64.c + x86_64/is_fpreg.c + x86_64/regname.c + x86_64/setcontext.S + x86_64/Lcreate_addr_space.c + x86_64/Lget_save_loc.c + x86_64/Lglobal.c + x86_64/Linit.c + x86_64/Linit_local.c + x86_64/Linit_remote.c + x86_64/Lis_signal_frame.c + x86_64/Lget_proc_info.c + x86_64/Lregs.c + x86_64/Lresume.c + x86_64/getcontext.S + x86_64/Lstep.c + ) + + +add_definitions(-DHAVE_CONFIG_H + -D_GNU_SOURCE + -fPIC + -DPIC + ) + +include_directories(. + ../include + ${CMAKE_CURRENT_BINARY_DIR}/include + ) + + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/include/config.h) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libunwind-common.h.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/include/libunwind-common.h) + + +# TODO: add checks for all platforms +if("${CMAKE_C_FLAGS}" MATCHES "-m32") + set(target "x8664_32") +elseif("${CMAKE_C_FLAGS}" MATCHES "-m64") + set(target "x8664_64") + include_directories(../include/tdep-x86_64) +else() + message(FATAL_ERROR "Unknown target") +endif() + +add_library(unwind STATIC ${libunwind_sources_common} ${libunwind_sources_${target}}) + diff --git a/src/config.h.cmake.in b/src/config.h.cmake.in new file mode 100644 index 00000000..bebbe094 --- /dev/null +++ b/src/config.h.cmake.in @@ -0,0 +1,125 @@ +/* include/config.h. Generated from config.h.in by configure. */ +/* include/config.h.in. Generated from configure.in by autoheader. */ + +/* Enable Debug Frame */ +/* #undef CONFIG_DEBUG_FRAME */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ASM_PTRACE_OFFSETS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ATOMIC_OPS_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `dlmodinfo' function. */ +/* #undef HAVE_DLMODINFO */ + +/* Define to 1 if you have the `dl_iterate_phdr' function. */ +#define HAVE_DL_ITERATE_PHDR 1 + +/* Define to 1 if you have the `dl_phdr_removals_counter' function. */ +/* #undef HAVE_DL_PHDR_REMOVALS_COUNTER */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ENDIAN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_EXECINFO_H 1 + +/* Define to 1 if you have the `getunwind' function. */ +/* #undef HAVE_GETUNWIND */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IA64INTRIN_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `uca' library (-luca). */ +/* #undef HAVE_LIBUCA */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if the system has the type `sighandler_t'. */ +#define HAVE_SIGHANDLER_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if `dlpi_subs' is member of `struct dl_phdr_info'. */ +#define HAVE_STRUCT_DL_PHDR_INFO_DLPI_SUBS 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_UC_ACCESS_H */ + +/* Define to 1 if you have the `ttrace' function. */ +/* #undef HAVE_TTRACE */ + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if __thread keyword is supported by the C compiler. */ +#define HAVE___THREAD 1 + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef NO_MINUS_C_MINUS_O */ + +/* Name of package */ +#define PACKAGE "libunwind" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "libunwind-devel@nongnu.org" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libunwind" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libunwind 0.99-beta" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "libunwind" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.99-beta" + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "0.99-beta" + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ diff --git a/src/libunwind-common.h.cmake.in b/src/libunwind-common.h.cmake.in new file mode 100644 index 00000000..18129f88 --- /dev/null +++ b/src/libunwind-common.h.cmake.in @@ -0,0 +1,252 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#define UNW_VERSION_MAJOR 0 +#define UNW_VERSION_MINOR 99 +#define UNW_VERSION_EXTRA -beta + +#define UNW_VERSION_CODE(maj,min) (((maj) << 16) | (min)) +#define UNW_VERSION UNW_VERSION_CODE(UNW_VERSION_MAJOR, UNW_VERSION_MINOR) + +#define UNW_PASTE2(x,y) x##y +#define UNW_PASTE(x,y) UNW_PASTE2(x,y) +#define UNW_OBJ(fn) UNW_PASTE(UNW_PREFIX, fn) +#define UNW_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_), fn) + +#ifdef UNW_LOCAL_ONLY +# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_UL,UNW_TARGET),_) +#else /* !UNW_LOCAL_ONLY */ +# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_) +#endif /* !UNW_LOCAL_ONLY */ + +/* Error codes. The unwind routines return the *negated* values of + these error codes on error and a non-negative value on success. */ +typedef enum + { + UNW_ESUCCESS = 0, /* no error */ + UNW_EUNSPEC, /* unspecified (general) error */ + UNW_ENOMEM, /* out of memory */ + UNW_EBADREG, /* bad register number */ + UNW_EREADONLYREG, /* attempt to write read-only register */ + UNW_ESTOPUNWIND, /* stop unwinding */ + UNW_EINVALIDIP, /* invalid IP */ + UNW_EBADFRAME, /* bad frame */ + UNW_EINVAL, /* unsupported operation or bad value */ + UNW_EBADVERSION, /* unwind info has unsupported version */ + UNW_ENOINFO /* no unwind info found */ + } +unw_error_t; + +/* The following enum defines the indices for a couple of + (pseudo-)registers which have the same meaning across all + platforms. (RO) means read-only. (RW) means read-write. General + registers (aka "integer registers") are expected to start with + index 0. The number of such registers is architecture-dependent. + The remaining indices can be used as an architecture sees fit. The + last valid register index is given by UNW_REG_LAST. */ +typedef enum + { + UNW_REG_IP = UNW_TDEP_IP, /* (rw) instruction pointer (pc) */ + UNW_REG_SP = UNW_TDEP_SP, /* (ro) stack pointer */ + UNW_REG_EH = UNW_TDEP_EH, /* (rw) exception-handling reg base */ + UNW_REG_LAST = UNW_TDEP_LAST_REG + } +unw_frame_regnum_t; + +/* Number of exception-handler argument registers: */ +#define UNW_NUM_EH_REGS UNW_TDEP_NUM_EH_REGS + +typedef enum + { + UNW_CACHE_NONE, /* no caching */ + UNW_CACHE_GLOBAL, /* shared global cache */ + UNW_CACHE_PER_THREAD /* per-thread caching */ + } +unw_caching_policy_t; + +typedef int unw_regnum_t; + +/* The unwind cursor starts at the youngest (most deeply nested) frame + and is used to track the frame state as the unwinder steps from + frame to frame. It is safe to make (shallow) copies of variables + of this type. */ +typedef struct unw_cursor + { + unw_word_t opaque[UNW_TDEP_CURSOR_LEN]; + } +unw_cursor_t; + +/* This type encapsulates the entire (preserved) machine-state. */ +typedef unw_tdep_context_t unw_context_t; + +/* unw_getcontext() fills the unw_context_t pointed to by UC with the + machine state as it exists at the call-site. For implementation + reasons, this needs to be a target-dependent macro. It's easiest + to think of unw_getcontext() as being identical to getcontext(). */ +#define unw_getcontext(uc) unw_tdep_getcontext(uc) + +/* Return 1 if register number R is a floating-point register, zero + otherwise. + This routine is signal-safe. */ +#define unw_is_fpreg(r) unw_tdep_is_fpreg(r) + +typedef unw_tdep_fpreg_t unw_fpreg_t; + +typedef struct unw_addr_space *unw_addr_space_t; + +/* Each target may define it's own set of flags, but bits 0-15 are + reserved for general libunwind-use. */ +#define UNW_PI_FLAG_FIRST_TDEP_BIT 16 + +typedef struct unw_proc_info + { + unw_word_t start_ip; /* first IP covered by this procedure */ + unw_word_t end_ip; /* first IP NOT covered by this procedure */ + unw_word_t lsda; /* address of lang.-spec. data area (if any) */ + unw_word_t handler; /* optional personality routine */ + unw_word_t gp; /* global-pointer value for this procedure */ + unw_word_t flags; /* misc. flags */ + + int format; /* unwind-info format (arch-specific) */ + int unwind_info_size; /* size of the information (if applicable) */ + void *unwind_info; /* unwind-info (arch-specific) */ + unw_tdep_proc_info_t extra; /* target-dependent auxiliary proc-info */ + } +unw_proc_info_t; + +/* These are backend callback routines that provide access to the + state of a "remote" process. This can be used, for example, to + unwind another process through the ptrace() interface. */ +typedef struct unw_accessors + { + /* Look up the unwind info associated with instruction-pointer IP. + On success, the routine fills in the PROC_INFO structure. */ + int (*find_proc_info) (unw_addr_space_t, unw_word_t, unw_proc_info_t *, + int, void *); + + /* Release any resources (e.g., memory) that were allocated for + the unwind info returned in by a previous call to + find_proc_info() with NEED_UNWIND_INFO set to 1. */ + void (*put_unwind_info) (unw_addr_space_t, unw_proc_info_t *, void *); + + /* Return the list-head of the dynamically registered unwind + info. */ + int (*get_dyn_info_list_addr) (unw_addr_space_t, unw_word_t *, void *); + + /* Access aligned word at address ADDR. The value is returned + according to the endianness of the host (e.g., if the host is + little-endian and the target is big-endian, access_mem() needs + to byte-swap the value before returning it). */ + int (*access_mem) (unw_addr_space_t, unw_word_t, unw_word_t *, int, + void *); + + /* Access register number REG at address ADDR. */ + int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *, int, + void *); + + /* Access register number REG at address ADDR. */ + int (*access_fpreg) (unw_addr_space_t, unw_regnum_t, + unw_fpreg_t *, int, void *); + + int (*resume) (unw_addr_space_t, unw_cursor_t *, void *); + + /* Optional call back to obtain the name of a (static) procedure. + Dynamically generated procedures are handled automatically by + libunwind. This callback is optional and may be set to + NULL. */ + int (*get_proc_name) (unw_addr_space_t, unw_word_t, char *, size_t, + unw_word_t *, void *); + } +unw_accessors_t; + +typedef enum unw_save_loc_type + { + UNW_SLT_NONE, /* register is not saved ("not an l-value") */ + UNW_SLT_MEMORY, /* register has been saved in memory */ + UNW_SLT_REG /* register has been saved in (another) register */ + } +unw_save_loc_type_t; + +typedef struct unw_save_loc + { + unw_save_loc_type_t type; + union + { + unw_word_t addr; /* valid if type==UNW_SLT_MEMORY */ + unw_regnum_t regnum; /* valid if type==UNW_SLT_REG */ + } + u; + unw_tdep_save_loc_t extra; /* target-dependent additional information */ + } +unw_save_loc_t; + +/* These routines work both for local and remote unwinding. */ + +#define unw_local_addr_space UNW_OBJ(local_addr_space) +#define unw_create_addr_space UNW_OBJ(create_addr_space) +#define unw_destroy_addr_space UNW_OBJ(destroy_addr_space) +#define unw_get_accessors UNW_ARCH_OBJ(get_accessors) +#define unw_init_local UNW_OBJ(init_local) +#define unw_init_remote UNW_OBJ(init_remote) +#define unw_step UNW_OBJ(step) +#define unw_resume UNW_OBJ(resume) +#define unw_get_proc_info UNW_OBJ(get_proc_info) +#define unw_get_proc_info_by_ip UNW_OBJ(get_proc_info_by_ip) +#define unw_get_reg UNW_OBJ(get_reg) +#define unw_set_reg UNW_OBJ(set_reg) +#define unw_get_fpreg UNW_OBJ(get_fpreg) +#define unw_set_fpreg UNW_OBJ(set_fpreg) +#define unw_get_save_loc UNW_OBJ(get_save_loc) +#define unw_is_signal_frame UNW_OBJ(is_signal_frame) +#define unw_get_proc_name UNW_OBJ(get_proc_name) +#define unw_set_caching_policy UNW_OBJ(set_caching_policy) +#define unw_regname UNW_ARCH_OBJ(regname) +#define unw_flush_cache UNW_ARCH_OBJ(flush_cache) +#define unw_strerror UNW_ARCH_OBJ(strerror) + +extern unw_addr_space_t unw_create_addr_space (unw_accessors_t *, int); +extern void unw_destroy_addr_space (unw_addr_space_t); +extern unw_accessors_t *unw_get_accessors (unw_addr_space_t); +extern void unw_flush_cache (unw_addr_space_t, unw_word_t, unw_word_t); +extern int unw_set_caching_policy (unw_addr_space_t, unw_caching_policy_t); +extern const char *unw_regname (unw_regnum_t); + +extern int unw_init_local (unw_cursor_t *, unw_context_t *); +extern int unw_init_remote (unw_cursor_t *, unw_addr_space_t, void *); +extern int unw_step (unw_cursor_t *); +extern int unw_resume (unw_cursor_t *); +extern int unw_get_proc_info (unw_cursor_t *, unw_proc_info_t *); +extern int unw_get_proc_info_by_ip (unw_addr_space_t, unw_word_t, + unw_proc_info_t *, void *); +extern int unw_get_reg (unw_cursor_t *, int, unw_word_t *); +extern int unw_set_reg (unw_cursor_t *, int, unw_word_t); +extern int unw_get_fpreg (unw_cursor_t *, int, unw_fpreg_t *); +extern int unw_set_fpreg (unw_cursor_t *, int, unw_fpreg_t); +extern int unw_get_save_loc (unw_cursor_t *, int, unw_save_loc_t *); +extern int unw_is_signal_frame (unw_cursor_t *); +extern int unw_get_proc_name (unw_cursor_t *, char *, size_t, unw_word_t *); +extern const char *unw_strerror (int); + +extern unw_addr_space_t unw_local_addr_space;