blob: a68343b0804b989cb4c9ccd0a96d2dd460a1c6dd [file] [log] [blame]
hp.com!davidmd7e9f752002-11-23 02:12:30 +00001/* libunwind - a platform-independent unwind library
2 Copyright (C) 2002 Hewlett-Packard Co
3 Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4
5This file is part of libunwind.
6
7Permission is hereby granted, free of charge, to any person obtaining
8a copy of this software and associated documentation files (the
9"Software"), to deal in the Software without restriction, including
10without limitation the rights to use, copy, modify, merge, publish,
11distribute, sublicense, and/or sell copies of the Software, and to
12permit persons to whom the Software is furnished to do so, subject to
13the following conditions:
14
15The above copyright notice and this permission notice shall be
16included in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
25
hp.com!davidmd7e9f752002-11-23 02:12:30 +000026/* This file defines the runtime-support routines for dynamically
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +000027generated code. Even though it is implemented as part of libunwind,
28it is logically separate from the interface to perform the actual
29unwinding. In particular, this interface is always used in the
30context of the unwind target, whereas the rest of the unwind API is
31used in context of the process that is doing the unwind (which may be
32a debugger running on another machine, for example).
33
34Note that the data-structures declared here server a dual purpose:
35when a program registers a dynamically generated procedure, it uses
36these structures directly. On the other hand, with remote-unwinding,
37the data-structures are read from the remote process's memory and
38translated into internalized versions. Because of this, care needs to
39be taken when choosing the types of structure members: use a pointer
40only if the member can be translated into an internalized equivalent
41(such as a string). Similarly, for members that need to hold an
42address in the unwindee, unw_word_t needs to be used. */
hp.com!davidmd7e9f752002-11-23 02:12:30 +000043
44typedef enum
45 {
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +000046 UNW_DYN_STOP = 0, /* end-of-unwind-info marker */
47 UNW_DYN_SAVE_REG, /* save register to another register */
48 UNW_DYN_SPILL_FP_REL, /* frame-pointer-relative register spill */
49 UNW_DYN_SPILL_SP_REL, /* stack-pointer-relative register spill */
50 UNW_DYN_ADD, /* add constant value to a register */
51 UNW_DYN_POP_FRAMES, /* drop one or more stack frames */
52 UNW_DYN_LABEL_STATE, /* name the current state */
53 UNW_DYN_COPY_STATE, /* set the region's entry-state */
54 UNW_DYN_ALIAS /* get unwind info from an alias */
hp.com!davidmd7e9f752002-11-23 02:12:30 +000055 }
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +000056unw_dyn_operation_t;
hp.com!davidmd7e9f752002-11-23 02:12:30 +000057
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +000058typedef struct unw_dyn_op
hp.com!davidmd7e9f752002-11-23 02:12:30 +000059 {
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +000060 uint16_t tag; /* what operation? */
61 int16_t reg; /* what register */
62 int16_t qp; /* qualifying predicate register */
63 int16_t pad0;
64 int32_t when; /* when does it take effect? */
65 unw_word_t val; /* auxiliary value */
hp.com!davidmd7e9f752002-11-23 02:12:30 +000066 }
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +000067unw_dyn_op_t;
hp.com!davidmd7e9f752002-11-23 02:12:30 +000068
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +000069typedef struct unw_dyn_region_info
hp.com!davidmd7e9f752002-11-23 02:12:30 +000070 {
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +000071 struct unw_dyn_region_info *next; /* linked list of regions */
72 uint32_t insn_count; /* region length (# of instructions) */
73 uint32_t op_count; /* length of op-array */
74 unw_dyn_op_t op[1]; /* variable-length op-array */
75 }
76unw_dyn_region_info_t;
77
78typedef struct unw_dyn_proc_info
79 {
80 const char *name; /* unique & human-readable procedure name */
81 unw_word_t handler; /* address of personality routine */
82 uint32_t flags;
83 unw_dyn_region_info_t *regions;
84 }
85unw_dyn_proc_info_t;
86
87typedef struct unw_dyn_table_info
88 {
89 const char *name; /* table name (e.g., name of library) */
90 unw_word_t segbase; /* segment base */
91 unw_word_t table_size;
92 void *table_data;
93 }
94unw_dyn_table_info_t;
95
96typedef struct unw_dyn_info
97 {
98 struct unw_dyn_info *next; /* linked list of dyn-info structures */
99 unw_word_t start_ip; /* first IP covered by this entry */
100 unw_word_t end_ip; /* first IP NOT covered by this entry */
101 unw_word_t gp; /* global-pointer in effect for this entry */
102 enum
hp.com!davidmd7e9f752002-11-23 02:12:30 +0000103 {
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +0000104 UNW_INFO_FORMAT_DYNAMIC, /* unw_dyn_proc_info_t */
105 UNW_INFO_FORMAT_TABLE /* unw_dyn_table_t */
hp.com!davidmd7e9f752002-11-23 02:12:30 +0000106 }
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +0000107 format;
108 union
109 {
110 unw_dyn_proc_info_t pi;
111 unw_dyn_table_info_t ti;
112 }
113 u;
hp.com!davidmd7e9f752002-11-23 02:12:30 +0000114 }
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +0000115unw_dyn_info_t;
hp.com!davidmd7e9f752002-11-23 02:12:30 +0000116
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +0000117typedef struct unw_dyn_info_list
118 {
119 unsigned long generation;
120 unw_dyn_info_t *first;
121 }
122unw_dyn_info_list_t;
123
124/* Return the size (in bytes) of an unw_dyn_region_info_t structure that can
hp.com!davidmd7e9f752002-11-23 02:12:30 +0000125 hold OP_COUNT ops. */
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +0000126#define _U_dyn_region_info_size(op_count) \
127 (sizeof (unw_dyn_region_info_t) \
128 + (op_count > 0) ? ((op_count) - 1) * sizeof (unw_dyn_op_t) : 0)
hp.com!davidmd7e9f752002-11-23 02:12:30 +0000129
130/* Register the unwind info for a single procedure.
131 This routine is NOT signal-safe. */
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +0000132extern int _U_dyn_register (unw_dyn_info_t *di);
hp.com!davidmd7e9f752002-11-23 02:12:30 +0000133
134/* Cancel the unwind info for a single procedure.
135 This routine is NOT signal-safe. */
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +0000136extern int _U_dyn_cancel (unw_dyn_info_t *di);
hp.com!davidmd7e9f752002-11-23 02:12:30 +0000137
138
139/* Convenience routines. */
140
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +0000141#define _U_dyn_op(_t, _q, _w, _r, _v) \
142 ((unw_dyn_op_t) { \
143 .tag = (_t), \
144 .qp = (_q), \
145 .when = (_w), \
146 .reg = (_r), \
147 .val = (_v) \
148 })
hp.com!davidmd7e9f752002-11-23 02:12:30 +0000149
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +0000150#define _U_dyn_op_save_reg(op, qp, when, reg, dst) \
151 (*(op) = _U_dyn_op (UNW_DYN_SAVE_REG, (qp), (when), (reg), (dst)))
hp.com!davidmd7e9f752002-11-23 02:12:30 +0000152
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +0000153#define _U_dyn_op_spill_fp_rel(op, qp, when, reg, offset) \
154 (*(op) = _U_dyn_op (UNW_DYN_SPILL_FP_REL, (qp), (when), (reg), \
155 (offset)))
hp.com!davidmd7e9f752002-11-23 02:12:30 +0000156
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +0000157#define _U_dyn_op_spill_sp_rel(op, qp, when, reg, offset) \
158 (*(op) = _U_dyn_op (UNW_DYN_SPILL_SP_REL, (qp), (when), (reg), \
159 (offset)))
hp.com!davidmd7e9f752002-11-23 02:12:30 +0000160
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +0000161#define _U_dyn_op_add(op, qp, when, reg, value) \
162 (*(op) = _U_dyn_op (UNW_DYN_ADD, (qp), (when), (reg), (value)))
hp.com!davidmd7e9f752002-11-23 02:12:30 +0000163
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +0000164#define _U_dyn_op_pop_frames(op, qp, when, num_frames) \
165 (*(op) = _U_dyn_op (UNW_DYN_POP_frames, (qp), (when), 0, (num_frames)))
hp.com!davidmd7e9f752002-11-23 02:12:30 +0000166
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +0000167#define _U_dyn_op_label_state(op, qp, when, label) \
168 (*(op) = _U_dyn_op (UNW_DYN_LABEL_STATE, (qp), (when), 0, (label)))
hp.com!davidmd7e9f752002-11-23 02:12:30 +0000169
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +0000170#define _U_dyn_op_copy_state(op, qp, when, label) \
171 (*(op) = _U_dyn_op (UNW_DYN_COPY_STATE, (qp), (when), 0, (label)))
hp.com!davidmd7e9f752002-11-23 02:12:30 +0000172
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +0000173#define _U_dyn_op_alias(op, qp, when, addr) \
174 (*(op) = _U_dyn_op (UNW_DYN_ALIAS, (qp), (when), 0, (addr)))
hp.com!davidmd7e9f752002-11-23 02:12:30 +0000175
mostang.com!davidmdfc08ea2002-12-03 08:19:58 +0000176#define _U_dyn_op_stop(op) \
177 ((op)->tag = UNW_DYN_STOP)