Back to index

plt-scheme  4.2.1
libunwind_i.h
Go to the documentation of this file.
00001 /* libunwind - a platform-independent unwind library
00002    Copyright (C) 2001-2005 Hewlett-Packard Co
00003        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
00004 
00005 This file is several parts of libunwind concatenated.
00006 
00007 Permission is hereby granted, free of charge, to any person obtaining
00008 a copy of this software and associated documentation files (the
00009 "Software"), to deal in the Software without restriction, including
00010 without limitation the rights to use, copy, modify, merge, publish,
00011 distribute, sublicense, and/or sell copies of the Software, and to
00012 permit persons to whom the Software is furnished to do so, subject to
00013 the following conditions:
00014 
00015 The above copyright notice and this permission notice shall be
00016 included in all copies or substantial portions of the Software.
00017 
00018 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00019 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00021 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00022 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00023 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00024 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
00025 
00026 /* This files contains libunwind-internal definitions which are
00027    subject to frequent change and are not to be exposed to
00028    libunwind-users.  */
00029 
00030 #ifndef libunwind_i_h
00031 #define libunwind_i_h
00032 
00033 #ifdef HAVE___THREAD
00034   /* For now, turn off per-thread caching.  It uses up too much TLS
00035      memory per thread even when the thread never uses libunwind at
00036      all.  */
00037 # undef HAVE___THREAD
00038 #endif
00039 
00040 /* Platform-independent libunwind-internal declarations.  */
00041 
00042 #include <sys/types.h>      /* HP-UX needs this before include of pthread.h */
00043 
00044 #include <assert.h>
00045 #include "libunwind.h"
00046 #include <signal.h>
00047 #include <stdlib.h>
00048 #include <string.h>
00049 #include <unistd.h>
00050 
00051 /* FIXME: hard-wired */
00052 # define __LITTLE_ENDIAN    1234
00053 # define __BIG_ENDIAN              4321
00054 # define __BYTE_ORDER __LITTLE_ENDIAN
00055 
00056 
00057 #   define __BYTE_ORDER __LITTLE_ENDIAN
00058 
00059 #ifdef __GNUC__
00060 # define UNUSED             __attribute__((unused))
00061 # define NORETURN    __attribute__((noreturn))
00062 # define ALIAS(name) __attribute__((alias (#name)))
00063 # if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
00064 #  define ALWAYS_INLINE     inline __attribute__((always_inline))
00065 #  define HIDDEN     __attribute__((visibility ("hidden")))
00066 #  define PROTECTED  __attribute__((visibility ("protected")))
00067 # else
00068 #  define ALWAYS_INLINE
00069 #  define HIDDEN
00070 #  define PROTECTED
00071 # endif
00072 # if (__GNUC__ >= 3)
00073 #  define likely(x)  __builtin_expect ((x), 1)
00074 #  define unlikely(x)       __builtin_expect ((x), 0)
00075 # else
00076 #  define likely(x)  (x)
00077 #  define unlikely(x)       (x)
00078 # endif
00079 #else
00080 # define ALWAYS_INLINE
00081 # define UNUSED
00082 # define NORETURN
00083 # define ALIAS(name)
00084 # define HIDDEN
00085 # define PROTECTED
00086 # define likely(x)   (x)
00087 # define unlikely(x) (x)
00088 #endif
00089 
00090 #undef HIDDEN
00091 #define HIDDEN static
00092 
00093 #define ARRAY_SIZE(a)       (sizeof (a) / sizeof ((a)[0]))
00094 
00095 /* Make it easy to write thread-safe code which may or may not be
00096    linked against libpthread.  The macros below can be used
00097    unconditionally and if -lpthread is around, they'll call the
00098    corresponding routines otherwise, they do nothing.  */
00099 
00100 #pragma weak pthread_mutex_init
00101 #pragma weak pthread_mutex_lock
00102 #pragma weak pthread_mutex_unlock
00103 
00104 #define mutex_init(l)                                                 \
00105        (pthread_mutex_init != 0 ? pthread_mutex_init ((l), 0) : 0)
00106 #define mutex_lock(l)                                                 \
00107        (pthread_mutex_lock != 0 ? pthread_mutex_lock (l) : 0)
00108 #define mutex_unlock(l)                                               \
00109        (pthread_mutex_unlock != 0 ? pthread_mutex_unlock (l) : 0)
00110 
00111 #ifdef HAVE_ATOMIC_OPS_H
00112 # include <atomic_ops.h>
00113 static inline int
00114 cmpxchg_ptr (void *addr, void *old, void *new)
00115 {
00116   union
00117     {
00118       void *vp;
00119       AO_t *aop;
00120     }
00121   u;
00122 
00123   u.vp = addr;
00124   return AO_compare_and_swap(u.aop, (AO_t) old, (AO_t) new);
00125 }
00126 # define fetch_and_add1(_ptr)             AO_fetch_and_add1(_ptr)
00127    /* GCC 3.2.0 on HP-UX crashes on cmpxchg_ptr() */
00128 #  if !(defined(__hpux) && __GNUC__ == 3 && __GNUC_MINOR__ == 2)
00129 #   define HAVE_CMPXCHG
00130 #  endif
00131 # define HAVE_FETCH_AND_ADD1
00132 #else
00133 # ifdef HAVE_IA64INTRIN_H
00134 #  include <ia64intrin.h>
00135 static inline int
00136 cmpxchg_ptr (void *addr, void *old, void *new)
00137 {
00138   union
00139     {
00140       void *vp;
00141       long *vlp;
00142     }
00143   u;
00144 
00145   u.vp = addr;
00146   return __sync_bool_compare_and_swap(u.vlp, (long) old, (long) new);
00147 }
00148 #  define fetch_and_add1(_ptr)            __sync_fetch_and_add(_ptr, 1)
00149 #  define HAVE_CMPXCHG
00150 #  define HAVE_FETCH_AND_ADD1
00151 # endif
00152 #endif
00153 #define atomic_read(ptr)    (*(ptr))
00154 
00155 #define UNWI_OBJ(fn)   UNW_PASTE(UNW_PREFIX,UNW_PASTE(I,fn))
00156 #define UNWI_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_UI,UNW_TARGET),_), fn)
00157 
00158 #define unwi_full_mask    UNWI_ARCH_OBJ(full_mask)
00159 
00160 /* Type of a mask that can be used to inhibit preemption.  At the
00161    userlevel, preemption is caused by signals and hence sigset_t is
00162    appropriate.  In constrast, the Linux kernel uses "unsigned long"
00163    to hold the processor "flags" instead.  */
00164 typedef sigset_t intrmask_t;
00165 
00166 extern intrmask_t unwi_full_mask;
00167 
00168 #define define_lock(name) \
00169   pthread_mutex_t name = PTHREAD_MUTEX_INITIALIZER
00170 #define lock_init(l)        mutex_init (l)
00171 #define lock_acquire(l,m)                        \
00172 do {                                             \
00173   sigprocmask (SIG_SETMASK, &unwi_full_mask, &(m));     \
00174   mutex_lock (l);                                \
00175 } while (0)
00176 #define lock_release(l,m)                 \
00177 do {                                      \
00178   mutex_unlock (l);                       \
00179   sigprocmask (SIG_SETMASK, &(m), NULL);  \
00180 } while (0)
00181 
00182 #define GET_MEMORY(mem, size_in_bytes)                             \
00183 do {                                                               \
00184   /* Hopefully, mmap() goes straight through to a system call stub...  */   \
00185   mem = mmap (0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, \
00186              -1, 0);                                               \
00187   if (mem == MAP_FAILED)                                           \
00188     mem = NULL;                                                           \
00189 } while (0)
00190 
00191 #define UNW_DEBUG 0
00192 #if UNW_DEBUG
00193 #define unwi_debug_level           UNWI_ARCH_OBJ(debug_level)
00194 extern int unwi_debug_level;
00195 
00196 # include <stdio.h>
00197 # define Debug(level,format...)                                       \
00198 do {                                                           \
00199   if (unwi_debug_level >= level)                               \
00200     {                                                          \
00201       int _n = level;                                                 \
00202       if (_n > 16)                                             \
00203        _n = 16;                                                \
00204       fprintf (stderr, "%*c>%s: ", _n, ' ', __FUNCTION__);            \
00205       fprintf (stderr, format);                                       \
00206     }                                                          \
00207 } while (0)
00208 # define dprintf(format...)            fprintf (stderr, format)
00209 # ifdef __GNUC__
00210 #  undef inline
00211 #  define inline     UNUSED
00212 # endif
00213 #else
00214 # define Debug(level,format...)
00215 # define dprintf(format...)
00216 #endif
00217 
00218 static ALWAYS_INLINE void
00219 print_error (const char *string)
00220 {
00221   write (2, string, strlen (string));
00222 }
00223 
00224 #define mi_init             UNWI_ARCH_OBJ(mi_init)
00225 
00226 extern void mi_init (void); /* machine-independent initializations */
00227 extern unw_word_t _U_dyn_info_list_addr (void);
00228 
00229 /* This is needed/used by ELF targets only.  */
00230 
00231 struct elf_image
00232   {
00233     void *image;            /* pointer to mmap'd image */
00234     size_t size;            /* (file-) size of the image */
00235   };
00236 
00237 /* Target-dependent definitions that are internal to libunwind but need
00238    to be shared with target-independent code.  */
00239 
00240 /*XXXXXXXXXXXXXXXXXXXXXXXXX Start unwind_dl.h XXXXXXXXXXXXXXXXXXXXXXXXXX*/
00241 
00242 #ifdef OS_X
00243 
00244 #define elf_w(x) x
00245 #define Elf_W(x) x
00246 
00247 #include <mach-o/loader.h>
00248 #include <mach-o/dyld.h>
00249 
00250 #define PT_LOAD LC_SEGMENT
00251 #define PT_GNU_EH_FRAME -1
00252 #define PT_DYNAMIC -1
00253 
00254 #define DT_NULL   0
00255 #define DT_PLTGOT 1
00256 
00257 #define DW_EH_VERSION 1
00258 
00259 typedef long Addr;
00260 typedef struct {
00261   long p_type;
00262   Addr p_vaddr;
00263   long p_memsz;
00264   long p_filesz;
00265 } Phdr;
00266 
00267 typedef struct {
00268   long d_tag;
00269   struct { long d_ptr; } d_un;
00270 } Dyn;
00271 
00272 struct dl_phdr_info {
00273   Phdr *dlpi_phdr;
00274   Addr dlpi_addr;
00275   long dlpi_phnum;
00276   char *dlpi_name;
00277 };
00278 
00279 typedef int (*DL_Iter_Callback)(struct dl_phdr_info *info, size_t size, void *ptr);
00280 int dl_iterate_phdr (DL_Iter_Callback callback, void *p);
00281 
00282 #else
00283 
00284 #define __USE_GNU
00285 #include <link.h>
00286 #undef __USE_GNU
00287 
00288 #define elf_w(x) elf64_ ## x
00289 #define Elf_W(x) ElfW(x)
00290 
00291 typedef int (*DL_Iter_Callback)(struct dl_phdr_info *info, size_t size, void *ptr);
00292 
00293 #endif
00294 
00295 extern int elf_w(get_proc_name) (pid_t pid, unw_word_t ip,
00296                              char *buf, size_t len,
00297                              unw_word_t *offp);
00298 
00299 /*XXXXXXXXXXXXXXXXXXXXXXXXX End unwind_dl.h XXXXXXXXXXXXXXXXXXXXXXXXXX*/
00300 
00301 /*XXXXXXXXXXXXXXXXXXXXXXXXX Start dwarf.h XXXXXXXXXXXXXXXXXXXXXXXXXX*/
00302 
00303 struct dwarf_cursor; /* forward-declaration */
00304 
00305 /* This matches the value used by GCC (see
00306    gcc/config/i386.h:DWARF_FRAME_REGISTERS), which leaves plenty of
00307    room for expansion.  */
00308 #define DWARF_NUM_PRESERVED_REGS   17
00309 
00310 #ifdef PLAIN_X86
00311 #define DWARF_REGNUM_MAP_LENGTH           19
00312 #else
00313 #define DWARF_REGNUM_MAP_LENGTH           17
00314 #endif
00315 
00316 /* Return TRUE if the ADDR_SPACE uses big-endian byte-order.  */
00317 #define dwarf_is_big_endian(addr_space)   0
00318 
00319 /* Convert a pointer to a dwarf_cursor structure to a pointer to
00320    unw_cursor_t.  */
00321 #define dwarf_to_cursor(c)  ((unw_cursor_t *) (c))
00322 
00323 typedef struct dwarf_loc
00324   {
00325     unw_word_t val;
00326   }
00327 dwarf_loc_t;
00328 
00329 /* DWARF expression opcodes.  */
00330 
00331 typedef enum
00332   {
00333     DW_OP_addr                     = 0x03,
00334     DW_OP_deref                    = 0x06,
00335     DW_OP_const1u           = 0x08,
00336     DW_OP_const1s           = 0x09,
00337     DW_OP_const2u           = 0x0a,
00338     DW_OP_const2s           = 0x0b,
00339     DW_OP_const4u           = 0x0c,
00340     DW_OP_const4s           = 0x0d,
00341     DW_OP_const8u           = 0x0e,
00342     DW_OP_const8s           = 0x0f,
00343     DW_OP_constu            = 0x10,
00344     DW_OP_consts            = 0x11,
00345     DW_OP_dup               = 0x12,
00346     DW_OP_drop                     = 0x13,
00347     DW_OP_over                     = 0x14,
00348     DW_OP_pick                     = 0x15,
00349     DW_OP_swap                     = 0x16,
00350     DW_OP_rot               = 0x17,
00351     DW_OP_xderef            = 0x18,
00352     DW_OP_abs               = 0x19,
00353     DW_OP_and               = 0x1a,
00354     DW_OP_div               = 0x1b,
00355     DW_OP_minus                    = 0x1c,
00356     DW_OP_mod               = 0x1d,
00357     DW_OP_mul               = 0x1e,
00358     DW_OP_neg               = 0x1f,
00359     DW_OP_not               = 0x20,
00360     DW_OP_or                = 0x21,
00361     DW_OP_plus                     = 0x22,
00362     DW_OP_plus_uconst              = 0x23,
00363     DW_OP_shl               = 0x24,
00364     DW_OP_shr               = 0x25,
00365     DW_OP_shra                     = 0x26,
00366     DW_OP_xor               = 0x27,
00367     DW_OP_skip                     = 0x2f,
00368     DW_OP_bra               = 0x28,
00369     DW_OP_eq                = 0x29,
00370     DW_OP_ge                = 0x2a,
00371     DW_OP_gt                = 0x2b,
00372     DW_OP_le                = 0x2c,
00373     DW_OP_lt                = 0x2d,
00374     DW_OP_ne                = 0x2e,
00375     DW_OP_lit0                     = 0x30,
00376     DW_OP_lit1,  DW_OP_lit2,  DW_OP_lit3,  DW_OP_lit4,  DW_OP_lit5,
00377     DW_OP_lit6,  DW_OP_lit7,  DW_OP_lit8,  DW_OP_lit9,  DW_OP_lit10,
00378     DW_OP_lit11, DW_OP_lit12, DW_OP_lit13, DW_OP_lit14, DW_OP_lit15,
00379     DW_OP_lit16, DW_OP_lit17, DW_OP_lit18, DW_OP_lit19, DW_OP_lit20,
00380     DW_OP_lit21, DW_OP_lit22, DW_OP_lit23, DW_OP_lit24, DW_OP_lit25,
00381     DW_OP_lit26, DW_OP_lit27, DW_OP_lit28, DW_OP_lit29, DW_OP_lit30,
00382     DW_OP_lit31,
00383     DW_OP_reg0                     = 0x50,
00384     DW_OP_reg1,  DW_OP_reg2,  DW_OP_reg3,  DW_OP_reg4,  DW_OP_reg5,
00385     DW_OP_reg6,  DW_OP_reg7,  DW_OP_reg8,  DW_OP_reg9,  DW_OP_reg10,
00386     DW_OP_reg11, DW_OP_reg12, DW_OP_reg13, DW_OP_reg14, DW_OP_reg15,
00387     DW_OP_reg16, DW_OP_reg17, DW_OP_reg18, DW_OP_reg19, DW_OP_reg20,
00388     DW_OP_reg21, DW_OP_reg22, DW_OP_reg23, DW_OP_reg24, DW_OP_reg25,
00389     DW_OP_reg26, DW_OP_reg27, DW_OP_reg28, DW_OP_reg29, DW_OP_reg30,
00390     DW_OP_reg31,
00391     DW_OP_breg0                    = 0x70,
00392     DW_OP_breg1,  DW_OP_breg2,  DW_OP_breg3,  DW_OP_breg4,  DW_OP_breg5,
00393     DW_OP_breg6,  DW_OP_breg7,  DW_OP_breg8,  DW_OP_breg9,  DW_OP_breg10,
00394     DW_OP_breg11, DW_OP_breg12, DW_OP_breg13, DW_OP_breg14, DW_OP_breg15,
00395     DW_OP_breg16, DW_OP_breg17, DW_OP_breg18, DW_OP_breg19, DW_OP_breg20,
00396     DW_OP_breg21, DW_OP_breg22, DW_OP_breg23, DW_OP_breg24, DW_OP_breg25,
00397     DW_OP_breg26, DW_OP_breg27, DW_OP_breg28, DW_OP_breg29, DW_OP_breg30,
00398     DW_OP_breg31,
00399     DW_OP_regx                     = 0x90,
00400     DW_OP_fbreg                    = 0x91,
00401     DW_OP_bregx                    = 0x92,
00402     DW_OP_piece                    = 0x93,
00403     DW_OP_deref_size        = 0x94,
00404     DW_OP_xderef_size              = 0x95,
00405     DW_OP_nop               = 0x96,
00406     DW_OP_push_object_address      = 0x97,
00407     DW_OP_call2                    = 0x98,
00408     DW_OP_call4                    = 0x99,
00409     DW_OP_call_ref          = 0x9a,
00410     DW_OP_lo_user           = 0xe0,
00411     DW_OP_hi_user           = 0xff
00412   }
00413 dwarf_expr_op_t;
00414 
00415 #define DWARF_CIE_VERSION   3      /* GCC emits version 1??? */
00416 
00417 #define DWARF_CFA_OPCODE_MASK      0xc0
00418 #define DWARF_CFA_OPERAND_MASK     0x3f
00419 
00420 typedef enum
00421   {
00422     DW_CFA_advance_loc             = 0x40,
00423     DW_CFA_offset           = 0x80,
00424     DW_CFA_restore          = 0xc0,
00425     DW_CFA_nop                     = 0x00,
00426     DW_CFA_set_loc          = 0x01,
00427     DW_CFA_advance_loc1            = 0x02,
00428     DW_CFA_advance_loc2            = 0x03,
00429     DW_CFA_advance_loc4            = 0x04,
00430     DW_CFA_offset_extended  = 0x05,
00431     DW_CFA_restore_extended = 0x06,
00432     DW_CFA_undefined        = 0x07,
00433     DW_CFA_same_value              = 0x08,
00434     DW_CFA_register         = 0x09,
00435     DW_CFA_remember_state   = 0x0a,
00436     DW_CFA_restore_state    = 0x0b,
00437     DW_CFA_def_cfa          = 0x0c,
00438     DW_CFA_def_cfa_register = 0x0d,
00439     DW_CFA_def_cfa_offset   = 0x0e,
00440     DW_CFA_def_cfa_expression      = 0x0f,
00441     DW_CFA_expression              = 0x10,
00442     DW_CFA_offset_extended_sf      = 0x11,
00443     DW_CFA_def_cfa_sf              = 0x12,
00444     DW_CFA_def_cfa_offset_sf       = 0x13,
00445     DW_CFA_lo_user          = 0x1c,
00446     DW_CFA_MIPS_advance_loc8       = 0x1d,
00447     DW_CFA_GNU_window_save  = 0x2d,
00448     DW_CFA_GNU_args_size    = 0x2e,
00449     DW_CFA_GNU_negative_offset_extended   = 0x2f,
00450     DW_CFA_hi_user          = 0x3c
00451   }
00452 dwarf_cfa_t;
00453 
00454 /* DWARF Pointer-Encoding (PEs).
00455 
00456    Pointer-Encodings were invented for the GCC exception-handling
00457    support for C++, but they represent a rather generic way of
00458    describing the format in which an address/pointer is stored and
00459    hence we include the definitions here, in the main dwarf.h file.
00460    The Pointer-Encoding format is partially documented in Linux Base
00461    Spec v1.3 (http://www.linuxbase.org/spec/).  The rest is reverse
00462    engineered from GCC.
00463 
00464 */
00465 #define DW_EH_PE_FORMAT_MASK       0x0f   /* format of the encoded value */
00466 #define DW_EH_PE_APPL_MASK  0x70   /* how the value is to be applied */
00467 /* Flag bit.  If set, the resulting pointer is the address of the word
00468    that contains the final address.  */
00469 #define DW_EH_PE_indirect   0x80
00470 
00471 /* Pointer-encoding formats: */
00472 #define DW_EH_PE_omit              0xff
00473 #define DW_EH_PE_ptr        0x00   /* pointer-sized unsigned value */
00474 #define DW_EH_PE_uleb128    0x01   /* unsigned LE base-128 value */
00475 #define DW_EH_PE_udata2            0x02   /* unsigned 16-bit value */
00476 #define DW_EH_PE_udata4            0x03   /* unsigned 32-bit value */
00477 #define DW_EH_PE_udata8            0x04   /* unsigned 64-bit value */
00478 #define DW_EH_PE_sleb128    0x09   /* signed LE base-128 value */
00479 #define DW_EH_PE_sdata2            0x0a   /* signed 16-bit value */
00480 #define DW_EH_PE_sdata4            0x0b   /* signed 32-bit value */
00481 #define DW_EH_PE_sdata8            0x0c   /* signed 64-bit value */
00482 
00483 /* Pointer-encoding application: */
00484 #define DW_EH_PE_absptr            0x00   /* absolute value */
00485 #define DW_EH_PE_pcrel             0x10   /* rel. to addr. of encoded value */
00486 #define DW_EH_PE_textrel    0x20   /* text-relative (GCC-specific???) */
00487 #define DW_EH_PE_datarel    0x30   /* data-relative */
00488 /* The following are not documented by LSB v1.3, yet they are used by
00489    GCC, presumably they aren't documented by LSB since they aren't
00490    used on Linux:  */
00491 #define DW_EH_PE_funcrel    0x40   /* start-of-procedure-relative */
00492 #define DW_EH_PE_aligned    0x50   /* aligned pointer */
00493 
00494 typedef enum
00495   {
00496     DWARF_WHERE_UNDEF,             /* register isn't saved at all */
00497     DWARF_WHERE_SAME,              /* register has same value as in prev. frame */
00498     DWARF_WHERE_CFAREL,            /* register saved at CFA-relative address */
00499     DWARF_WHERE_REG,        /* register saved in another register */
00500     DWARF_WHERE_EXPR,              /* register saved */
00501   }
00502 dwarf_where_t;
00503 
00504 typedef struct
00505   {
00506     dwarf_where_t where;    /* how is the register saved? */
00507     unw_word_t val;         /* where it's saved */
00508   }
00509 dwarf_save_loc_t;
00510 
00511 /* For uniformity, we'd like to treat the CFA save-location like any
00512    other register save-location, but this doesn't quite work, because
00513    the CFA can be expressed as a (REGISTER,OFFSET) pair.  To handle
00514    this, we use two dwarf_save_loc structures to describe the CFA.
00515    The first one (CFA_REG_COLUMN), tells us where the CFA is saved.
00516    In the case of DWARF_WHERE_EXPR, the CFA is defined by a DWARF
00517    location expression whose address is given by member "val".  In the
00518    case of DWARF_WHERE_REG, member "val" gives the number of the
00519    base-register and the "val" member of DWARF_CFA_OFF_COLUMN gives
00520    the offset value.  */
00521 #define DWARF_CFA_REG_COLUMN       DWARF_NUM_PRESERVED_REGS
00522 #define DWARF_CFA_OFF_COLUMN       (DWARF_NUM_PRESERVED_REGS + 1)
00523 
00524 typedef struct dwarf_reg_state
00525   {
00526     struct dwarf_reg_state *next;  /* for rs_stack */
00527     dwarf_save_loc_t reg[DWARF_NUM_PRESERVED_REGS + 2];
00528     unw_word_t ip;                    /* ip this rs is for */
00529     unw_word_t ret_addr_column;           /* indicates which column in the rule table represents return address */
00530     unsigned short lru_chain;        /* used for least-recently-used chain */
00531     unsigned short coll_chain;     /* used for hash collisions */
00532     unsigned short hint;          /* hint for next rs to try (or -1) */
00533   }
00534 dwarf_reg_state_t;
00535 
00536 typedef struct dwarf_cie_info
00537   {
00538     unw_word_t cie_instr_start;    /* start addr. of CIE "initial_instructions" */
00539     unw_word_t cie_instr_end;      /* end addr. of CIE "initial_instructions" */
00540     unw_word_t fde_instr_start;    /* start addr. of FDE "instructions" */
00541     unw_word_t fde_instr_end;      /* end addr. of FDE "instructions" */
00542     unw_word_t code_align;  /* code-alignment factor */
00543     unw_word_t data_align;  /* data-alignment factor */
00544     unw_word_t ret_addr_column;    /* column of return-address register */
00545     unw_word_t handler;            /* address of personality-routine */
00546     uint16_t abi;
00547     uint16_t tag;
00548     uint8_t fde_encoding;
00549     uint8_t lsda_encoding;
00550     unsigned int sized_augmentation : 1;
00551     unsigned int have_abi_marker : 1;
00552   }
00553 dwarf_cie_info_t;
00554 
00555 typedef struct dwarf_state_record
00556   {
00557     unsigned char fde_encoding;
00558     unw_word_t args_size;
00559 
00560     dwarf_reg_state_t rs_initial;  /* reg-state after CIE instructions */
00561     dwarf_reg_state_t rs_current;  /* current reg-state */
00562   }
00563 dwarf_state_record_t;
00564 
00565 typedef struct dwarf_cursor
00566   {
00567     void *as_arg;           /* argument to address-space callbacks */
00568     unw_addr_space_t as;    /* reference to per-address-space info */
00569 
00570     unw_word_t cfa;  /* canonical frame address; aka frame-/stack-pointer */
00571     unw_word_t ip;          /* instruction pointer */
00572     unw_word_t args_size;   /* size of arguments */
00573     unw_word_t ret_addr_column;    /* column for return-address */
00574     unw_word_t eh_args[UNW_TDEP_NUM_EH_REGS];
00575     unsigned int eh_valid_mask;
00576 
00577     dwarf_loc_t loc[DWARF_NUM_PRESERVED_REGS];
00578 
00579     unsigned int pi_valid :1;      /* is proc_info valid? */
00580     unw_proc_info_t pi;            /* info about current procedure */
00581 
00582     short hint; /* faster lookup of the rs cache */
00583     short prev_rs;
00584   }
00585 dwarf_cursor_t;
00586 
00587 #define DWARF_LOG_UNW_CACHE_SIZE   7
00588 #define DWARF_UNW_CACHE_SIZE       (1 << DWARF_LOG_UNW_CACHE_SIZE)
00589 
00590 #define DWARF_LOG_UNW_HASH_SIZE    (DWARF_LOG_UNW_CACHE_SIZE + 1)
00591 #define DWARF_UNW_HASH_SIZE (1 << DWARF_LOG_UNW_HASH_SIZE)
00592 
00593 typedef unsigned char unw_hash_index_t;
00594 
00595 struct dwarf_rs_cache
00596   {
00597     unsigned short lru_head;       /* index of lead-recently used rs */
00598     unsigned short lru_tail;       /* index of most-recently used rs */
00599 
00600     /* hash table that maps instruction pointer to rs index: */
00601     unsigned short hash[DWARF_UNW_HASH_SIZE];
00602 
00603     uint32_t generation;    /* generation number */
00604 
00605     /* rs cache: */
00606     dwarf_reg_state_t buckets[DWARF_UNW_CACHE_SIZE];
00607   };
00608 
00609 /* Convenience macros: */
00610 #define dwarf_init                 UNW_ARCH_OBJ (dwarf_init)
00611 #define dwarf_find_proc_info              UNW_OBJ (dwarf_find_proc_info)
00612 #define dwarf_search_unwind_table  UNW_OBJ (dwarf_search_unwind_table)
00613 #define dwarf_put_unwind_info             UNW_OBJ (dwarf_put_unwind_info)
00614 #define dwarf_put_unwind_info             UNW_OBJ (dwarf_put_unwind_info)
00615 #define dwarf_eval_expr                   UNW_OBJ (dwarf_eval_expr)
00616 #define dwarf_extract_proc_info_from_fde \
00617               UNW_OBJ (dwarf_extract_proc_info_from_fde)
00618 #define dwarf_find_save_locs              UNW_OBJ (dwarf_find_save_locs)
00619 #define dwarf_create_state_record  UNW_OBJ (dwarf_create_state_record)
00620 #define dwarf_make_proc_info              UNW_OBJ (dwarf_make_proc_info)
00621 #define dwarf_read_encoded_pointer UNW_OBJ (dwarf_read_encoded_pointer)
00622 #define dwarf_step                 UNW_OBJ (dwarf_step)
00623 
00624 HIDDEN int dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
00625                              unw_proc_info_t *pi,
00626                              int need_unwind_info, void *arg);
00627 HIDDEN int dwarf_search_unwind_table (unw_addr_space_t as,
00628                                   unw_word_t ip,
00629                                   unw_dyn_info_t *di,
00630                                   unw_proc_info_t *pi,
00631                                   int need_unwind_info, void *arg);
00632 HIDDEN int dwarf_eval_expr (struct dwarf_cursor *c, unw_word_t *addr,
00633                          unw_word_t len, unw_word_t *valp,
00634                          int *is_register);
00635 HIDDEN int dwarf_extract_proc_info_from_fde (unw_addr_space_t as,
00636                                         unw_accessors_t *a,
00637                                         unw_word_t *fde_addr,
00638                                         unw_proc_info_t *pi,
00639                                         int need_unwind_info,
00640                                         void *arg);
00641 HIDDEN int dwarf_find_save_locs (struct dwarf_cursor *c);
00642 HIDDEN int dwarf_read_encoded_pointer (unw_addr_space_t as,
00643                                    unw_accessors_t *a,
00644                                    unw_word_t *addr,
00645                                    unsigned char encoding,
00646                                    const unw_proc_info_t *pi,
00647                                    unw_word_t *valp, void *arg);
00648 HIDDEN int dwarf_step (struct dwarf_cursor *c);
00649 
00650 /*XXXXXXXXXXXXXXXXXXXXXXXXX End dwarf.h XXXXXXXXXXXXXXXXXXXXXXXXXX*/
00651 
00652 struct unw_addr_space
00653   {
00654     struct unw_accessors acc;
00655     unw_caching_policy_t caching_policy;
00656 #ifdef HAVE_ATOMIC_OPS_H
00657     AO_t cache_generation;
00658 #else
00659     uint32_t cache_generation;
00660 #endif
00661     struct dwarf_rs_cache global_cache;
00662    };
00663 
00664 struct cursor
00665   {
00666     struct dwarf_cursor dwarf;            /* must be first */
00667 
00668     /* Format of sigcontext structure and address at which it is
00669        stored: */
00670     enum
00671       {
00672        X86_SCF_NONE,               /* no signal frame encountered */
00673        X86_SCF_LINUX_SIGFRAME,            /* classic x86 sigcontext */
00674        X86_SCF_LINUX_RT_SIGFRAME   /* POSIX ucontext_t */
00675       }
00676     sigcontext_format;
00677     unw_word_t sigcontext_addr;
00678   };
00679 
00680 #define DWARF_GET_LOC(l)    ((l).val)
00681 
00682 # define DWARF_NULL_LOC            DWARF_LOC (0, 0)
00683 # define DWARF_IS_NULL_LOC(l)      (DWARF_GET_LOC (l) == 0)
00684 # define DWARF_LOC(r, t)    ((dwarf_loc_t) { .val = (r) })
00685 # define DWARF_IS_REG_LOC(l)       0
00686 # define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t)                        \
00687                              tdep_uc_addr((c)->as_arg, (r)), 0))
00688 # define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
00689 # define DWARF_FPREG_LOC(c,r)      (DWARF_LOC((unw_word_t)                        \
00690                              tdep_uc_addr((c)->as_arg, (r)), 0))
00691 
00692 static void *safe_pointer(unw_word_t);
00693 
00694 static inline int
00695 dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
00696 {
00697   if (!DWARF_GET_LOC (loc))
00698     return -1;
00699   *val = *(unw_fpreg_t *) safe_pointer(DWARF_GET_LOC (loc));
00700   return 0;
00701 }
00702 
00703 static inline int
00704 dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
00705 {
00706   if (!DWARF_GET_LOC (loc))
00707     return -1;
00708   *(unw_fpreg_t *) safe_pointer(DWARF_GET_LOC (loc)) = val;
00709   return 0;
00710 }
00711 
00712 static inline int
00713 dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
00714 {
00715   if (!DWARF_GET_LOC (loc))
00716     return -1;
00717   *val = *(unw_word_t *) safe_pointer(DWARF_GET_LOC (loc));
00718   return 0;
00719 }
00720 
00721 static inline int
00722 dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
00723 {
00724   if (!DWARF_GET_LOC (loc))
00725     return -1;
00726   *(unw_word_t *) safe_pointer(DWARF_GET_LOC (loc)) = val;
00727   return 0;
00728 }
00729 
00730 #define tdep_needs_initialization  UNW_OBJ(needs_initialization)
00731 #define tdep_init                  UNW_OBJ(init)
00732 /* Platforms that support UNW_INFO_FORMAT_TABLE need to define
00733    tdep_search_unwind_table.  */
00734 #define tdep_search_unwind_table   dwarf_search_unwind_table
00735 #define tdep_uc_addr               UNW_ARCH_OBJ(uc_addr)
00736 #define tdep_get_elf_image         UNW_ARCH_OBJ(get_elf_image)
00737 #define tdep_access_reg                   UNW_OBJ(access_reg)
00738 #define tdep_access_fpreg          UNW_OBJ(access_fpreg)
00739 
00740 # define tdep_find_proc_info(c,ip,n)                           \
00741        dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n),      \
00742                                    (c)->as_arg)
00743 # define tdep_put_unwind_info(as,pi,arg)         \
00744        dwarf_put_unwind_info((as), (pi), (arg))
00745 
00746 #define tdep_get_as(c)                    ((c)->dwarf.as)
00747 #define tdep_get_as_arg(c)         ((c)->dwarf.as_arg)
00748 #define tdep_get_ip(c)                    ((c)->dwarf.ip)
00749 #define tdep_get_cfa(c)                   ((c)->dwarf.cfa)
00750 #define tdep_big_endian(as)        0
00751 
00752 extern int tdep_needs_initialization;
00753 
00754 extern void tdep_init (void);
00755 extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
00756                                  unw_dyn_info_t *di, unw_proc_info_t *pi,
00757                                  int need_unwind_info, void *arg);
00758 extern void *tdep_uc_addr (ucontext_t *uc, int reg);
00759 extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
00760                             unsigned long *segbase, unsigned long *mapoff);
00761 extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
00762                          unw_word_t *valp, int write);
00763 extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
00764                            unw_fpreg_t *valp, int write);
00765 
00766 
00767 /*XXXXXXXXXXXXXXXXXXXXXXXXX Start dwarf_i.h XXXXXXXXXXXXXXXXXXXXXXXXXX*/
00768 
00769 #define dwarf_to_unw_regnum_map           UNW_OBJ (dwarf_to_unw_regnum_map)
00770 
00771 HIDDEN int dwarf_to_unw_regnum(int reg);
00772 
00773 /* In the local-only case, we can let the compiler directly access
00774    memory and don't need to worry about differing byte-order.  */
00775 
00776 typedef union
00777   {
00778     int8_t s8;
00779     int16_t s16;
00780     int32_t s32;
00781     int64_t s64;
00782     uint8_t u8;
00783     uint16_t u16;
00784     uint32_t u32;
00785     uint64_t u64;
00786     unw_word_t w;
00787     void *ptr;
00788   }
00789   dwarf_misaligned_value_t;
00790 
00791 static inline int
00792 dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
00793              int8_t *val, void *arg)
00794 {
00795   dwarf_misaligned_value_t *mvp = (void *) *addr;
00796 
00797   *val = mvp->s8;
00798   *addr += sizeof (mvp->s8);
00799   return 0;
00800 }
00801 
00802 static inline int
00803 dwarf_reads16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
00804               int16_t *val, void *arg)
00805 {
00806   dwarf_misaligned_value_t *mvp = (void *) *addr;
00807 
00808   *val = mvp->s16;
00809   *addr += sizeof (mvp->s16);
00810   return 0;
00811 }
00812 
00813 static inline int
00814 dwarf_reads32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
00815               int32_t *val, void *arg)
00816 {
00817   dwarf_misaligned_value_t *mvp = (void *) *addr;
00818 
00819   *val = mvp->s32;
00820   *addr += sizeof (mvp->s32);
00821   return 0;
00822 }
00823 
00824 static inline int
00825 dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
00826               int64_t *val, void *arg)
00827 {
00828   dwarf_misaligned_value_t *mvp = (void *) *addr;
00829 
00830   *val = mvp->s64;
00831   *addr += sizeof (mvp->s64);
00832   return 0;
00833 }
00834 
00835 static inline int
00836 dwarf_readu8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
00837              uint8_t *val, void *arg)
00838 {
00839   dwarf_misaligned_value_t *mvp = (void *) *addr;
00840 
00841   *val = mvp->u8;
00842   *addr += sizeof (mvp->u8);
00843   return 0;
00844 }
00845 
00846 static inline int
00847 dwarf_readu16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
00848               uint16_t *val, void *arg)
00849 {
00850   dwarf_misaligned_value_t *mvp = (void *) *addr;
00851 
00852   *val = mvp->u16;
00853   *addr += sizeof (mvp->u16);
00854   return 0;
00855 }
00856 
00857 static inline int
00858 dwarf_readu32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
00859               uint32_t *val, void *arg)
00860 {
00861   dwarf_misaligned_value_t *mvp = (void *) *addr;
00862 
00863   *val = mvp->u32;
00864   *addr += sizeof (mvp->u32);
00865   return 0;
00866 }
00867 
00868 static inline int
00869 dwarf_readu64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
00870               uint64_t *val, void *arg)
00871 {
00872   dwarf_misaligned_value_t *mvp = (void *) *addr;
00873 
00874   *val = mvp->u64;
00875   *addr += sizeof (mvp->u64);
00876   return 0;
00877 }
00878 
00879 static inline int
00880 dwarf_readw (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
00881             unw_word_t *val, void *arg)
00882 {
00883   dwarf_misaligned_value_t *mvp = (void *) *addr;
00884 
00885   *val = mvp->w;
00886   *addr += sizeof (mvp->w);
00887   return 0;
00888 }
00889 
00890 /* Read an unsigned "little-endian base 128" value.  See Chapter 7.6
00891    of DWARF spec v3.  */
00892 
00893 static inline int
00894 dwarf_read_uleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
00895                   unw_word_t *valp, void *arg)
00896 {
00897   unw_word_t val = 0, shift = 0;
00898   unsigned char byte;
00899   int ret;
00900 
00901   do
00902     {
00903       if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0)
00904        return ret;
00905 
00906       val |= ((unw_word_t) byte & 0x7f) << shift;
00907       shift += 7;
00908     }
00909   while (byte & 0x80);
00910 
00911   *valp = val;
00912   return 0;
00913 }
00914 
00915 /* Read a signed "little-endian base 128" value.  See Chapter 7.6 of
00916    DWARF spec v3.  */
00917 
00918 static inline int
00919 dwarf_read_sleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
00920                   unw_word_t *valp, void *arg)
00921 {
00922   unw_word_t val = 0, shift = 0;
00923   unsigned char byte;
00924   int ret;
00925 
00926   do
00927     {
00928       if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0)
00929        return ret;
00930 
00931       val |= ((unw_word_t) byte & 0x7f) << shift;
00932       shift += 7;
00933     }
00934   while (byte & 0x80);
00935 
00936   if (shift < 8 * sizeof (unw_word_t) && (byte & 0x40) != 0)
00937     /* sign-extend negative value */
00938     val |= ((unw_word_t) -1) << shift;
00939 
00940   *valp = val;
00941   return 0;
00942 }
00943 
00944 static ALWAYS_INLINE int
00945 dwarf_read_encoded_pointer_inlined (unw_addr_space_t as, unw_accessors_t *a,
00946                                 unw_word_t *addr, unsigned char encoding,
00947                                 const unw_proc_info_t *pi,
00948                                 unw_word_t *valp, void *arg)
00949 {
00950   unw_word_t val, initial_addr = *addr;
00951   uint16_t uval16;
00952   uint32_t uval32;
00953   uint64_t uval64;
00954   int16_t sval16;
00955   int32_t sval32;
00956   int64_t sval64;
00957   int ret;
00958 
00959   /* DW_EH_PE_omit and DW_EH_PE_aligned don't follow the normal
00960      format/application encoding.  Handle them first.  */
00961   if (encoding == DW_EH_PE_omit)
00962     {
00963       *valp = 0;
00964       return 0;
00965     }
00966   else if (encoding == DW_EH_PE_aligned)
00967     {
00968       *addr = (initial_addr + sizeof (unw_word_t) - 1) & -sizeof (unw_word_t);
00969       return dwarf_readw (as, a, addr, valp, arg);
00970     }
00971 
00972   switch (encoding & DW_EH_PE_FORMAT_MASK)
00973     {
00974     case DW_EH_PE_ptr:
00975       if ((ret = dwarf_readw (as, a, addr, &val, arg)) < 0)
00976        return ret;
00977       break;
00978 
00979     case DW_EH_PE_uleb128:
00980       if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
00981        return ret;
00982       break;
00983 
00984     case DW_EH_PE_udata2:
00985       if ((ret = dwarf_readu16 (as, a, addr, &uval16, arg)) < 0)
00986        return ret;
00987       val = uval16;
00988       break;
00989 
00990     case DW_EH_PE_udata4:
00991       if ((ret = dwarf_readu32 (as, a, addr, &uval32, arg)) < 0)
00992        return ret;
00993       val = uval32;
00994       break;
00995 
00996     case DW_EH_PE_udata8:
00997       if ((ret = dwarf_readu64 (as, a, addr, &uval64, arg)) < 0)
00998        return ret;
00999       val = uval64;
01000       break;
01001 
01002     case DW_EH_PE_sleb128:
01003       if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
01004        return ret;
01005       break;
01006 
01007     case DW_EH_PE_sdata2:
01008       if ((ret = dwarf_reads16 (as, a, addr, &sval16, arg)) < 0)
01009        return ret;
01010       val = sval16;
01011       break;
01012 
01013     case DW_EH_PE_sdata4:
01014       if ((ret = dwarf_reads32 (as, a, addr, &sval32, arg)) < 0)
01015        return ret;
01016       val = sval32;
01017       break;
01018 
01019     case DW_EH_PE_sdata8:
01020       if ((ret = dwarf_reads64 (as, a, addr, &sval64, arg)) < 0)
01021        return ret;
01022       val = sval64;
01023       break;
01024 
01025     default:
01026       Debug (1, "unexpected encoding format 0x%x\n",
01027             encoding & DW_EH_PE_FORMAT_MASK);
01028       return -UNW_EINVAL;
01029     }
01030 
01031   if (val == 0)
01032     {
01033       /* 0 is a special value and always absolute.  */
01034       *valp = 0;
01035       return 0;
01036     }
01037 
01038   switch (encoding & DW_EH_PE_APPL_MASK)
01039     {
01040     case DW_EH_PE_absptr:
01041       break;
01042 
01043     case DW_EH_PE_pcrel:
01044       val += initial_addr;
01045       break;
01046 
01047     case DW_EH_PE_datarel:
01048       /* XXX For now, assume that data-relative addresses are relative
01049          to the global pointer.  */
01050       val += pi->gp;
01051       break;
01052 
01053     case DW_EH_PE_funcrel:
01054       val += pi->start_ip;
01055       break;
01056 
01057     case DW_EH_PE_textrel:
01058       /* XXX For now we don't support text-rel values.  If there is a
01059          platform which needs this, we probably would have to add a
01060          "segbase" member to unw_proc_info_t.  */
01061     default:
01062       Debug (1, "unexpected application type 0x%x\n",
01063             encoding & DW_EH_PE_APPL_MASK);
01064       return -UNW_EINVAL;
01065     }
01066 
01067   if (encoding & DW_EH_PE_indirect)
01068     {
01069       unw_word_t indirect_addr = val;
01070 
01071       if ((ret = dwarf_readw (as, a, &indirect_addr, &val, arg)) < 0)
01072        return ret;
01073     }
01074 
01075   *valp = val;
01076   return 0;
01077 }
01078 
01079 /*XXXXXXXXXXXXXXXXXXXXXXXXX End dwarf_i.h XXXXXXXXXXXXXXXXXXXXXXXXXX*/
01080 
01081 /*XXXXXXXXXXXXXXXXXXXXXXXXX Start dwarf-eh.h XXXXXXXXXXXXXXXXXXXXXXXXXX*/
01082 
01083 /* This header file defines the format of a DWARF exception-header
01084    section (.eh_frame_hdr, pointed to by program-header
01085    PT_GNU_EH_FRAME).  The exception-header is self-describing in the
01086    sense that the format of the addresses contained in it is expressed
01087    as a one-byte type-descriptor called a "pointer-encoding" (PE).
01088 
01089    The exception header encodes the address of the .eh_frame section
01090    and optionally contains a binary search table for the
01091    Frame Descriptor Entries (FDEs) in the .eh_frame.  The contents of
01092    .eh_frame has the format described by the DWARF v3 standard
01093    (http://www.eagercon.com/dwarf/dwarf3std.htm), except that code
01094    addresses may be encoded in different ways.  Also, .eh_frame has
01095    augmentations that allow encoding a language-specific data-area
01096    (LSDA) pointer and a pointer to a personality-routine.
01097 
01098    Details:
01099 
01100     The Common Information Entry (CIE) associated with an FDE may
01101     contain an augmentation string.  Each character in this string has
01102     a specific meaning and either one or two associated operands.  The
01103     operands are stored in an augmentation body which appears right
01104     after the "return_address_register" member and before the
01105     "initial_instructions" member.  The operands appear in the order
01106     in which the characters appear in the string.  For example, if the
01107     augmentation string is "zL", the operand for 'z' would be first in
01108     the augmentation body and the operand for 'L' would be second.
01109     The following characters are supported for the CIE augmentation
01110     string:
01111 
01112      'z': The operand for this character is a uleb128 value that gives the
01113          length of the CIE augmentation body, not counting the length
01114          of the uleb128 operand itself.  If present, this code must
01115          appear as the first character in the augmentation body.
01116 
01117      'L': Indicates that the FDE's augmentation body contains an LSDA
01118           pointer.  The operand for this character is a single byte
01119           that specifies the pointer-encoding (PE) that is used for
01120           the LSDA pointer.
01121 
01122      'R': Indicates that the code-pointers (FDE members
01123           "initial_location" and "address_range" and the operand for
01124           DW_CFA_set_loc) in the FDE have a non-default encoding.  The
01125           operand for this character is a single byte that specifies
01126           the pointer-encoding (PE) that is used for the
01127           code-pointers.  Note: the "address_range" member is always
01128          encoded as an absolute value.  Apart from that, the specified
01129          FDE pointer-encoding applies.
01130 
01131      'P': Indicates the presence of a personality routine (handler).
01132           The first operand for this character specifies the
01133          pointer-encoding (PE) that is used for the second operand,
01134          which specifies the address of the personality routine.
01135 
01136     If the augmentation string contains any other characters, the
01137     remainder of the augmentation string should be ignored.
01138     Furthermore, if the size of the augmentation body is unknown
01139     (i.e., 'z' is not the first character of the augmentation string),
01140     then the entire CIE as well all associated FDEs must be ignored.
01141 
01142     A Frame Descriptor Entries (FDE) may contain an augmentation body
01143     which, if present, appears right after the "address_range" member
01144     and before the "instructions" member.  The contents of this body
01145     is implicitly defined by the augmentation string of the associated
01146     CIE.  The meaning of the characters in the CIE's augmentation
01147     string as far as FDEs are concerned is as follows:
01148 
01149      'z': The first operand in the FDE's augmentation body specifies
01150           the total length of the augmentation body as a uleb128 (not
01151           counting the length of the uleb128 operand itself).
01152 
01153      'L': The operand for this character is an LSDA pointer, encoded
01154           in the format specified by the corresponding operand in the
01155           CIE's augmentation body.
01156 
01157 */
01158 
01159 #define DW_EH_VERSION              1      /* The version we're implementing */
01160 
01161 struct dwarf_eh_frame_hdr
01162   {
01163     unsigned char version;
01164     unsigned char eh_frame_ptr_enc;
01165     unsigned char fde_count_enc;
01166     unsigned char table_enc;
01167     /* The rest of the header is variable-length and consists of the
01168        following members:
01169 
01170        encoded_t eh_frame_ptr;
01171        encoded_t fde_count;
01172        struct
01173          {
01174            encoded_t start_ip;     // first address covered by this FDE
01175            encoded_t fde_addr;     // address of the FDE
01176          }
01177        binary_search_table[fde_count];  */
01178   };
01179 
01180 /*XXXXXXXXXXXXXXXXXXXXXXXXX End dwarf-eh.h XXXXXXXXXXXXXXXXXXXXXXXXXX*/
01181 
01182 #endif /* libunwind_i_h */