1 /*-
2 * Copyright (c) 2009,2011 Kai Wang
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include "_libdwarf.h"
28
29 ELFTC_VCSID("$Id: libdwarf_init.c 3136 2014-12-24 16:04:38Z kaiwang27 $");
30
31 static int
_dwarf_consumer_init(Dwarf_Debug dbg,Dwarf_Error * error)32 _dwarf_consumer_init(Dwarf_Debug dbg, Dwarf_Error *error)
33 {
34 const Dwarf_Obj_Access_Methods *m;
35 Dwarf_Obj_Access_Section sec;
36 void *obj;
37 Dwarf_Unsigned cnt;
38 Dwarf_Half i;
39 int ret;
40
41 assert(dbg != NULL);
42 assert(dbg->dbg_iface != NULL);
43
44 m = dbg->dbg_iface->methods;
45 obj = dbg->dbg_iface->object;
46
47 assert(m != NULL);
48 assert(obj != NULL);
49
50 if (m->get_byte_order(obj) == DW_OBJECT_MSB) {
51 dbg->read = _dwarf_read_msb;
52 dbg->write = _dwarf_write_msb;
53 dbg->decode = _dwarf_decode_msb;
54 } else {
55 dbg->read = _dwarf_read_lsb;
56 dbg->write = _dwarf_write_lsb;
57 dbg->decode = _dwarf_decode_lsb;
58 }
59
60 dbg->dbg_pointer_size = m->get_pointer_size(obj);
61 dbg->dbg_offset_size = m->get_length_size(obj);
62
63 cnt = m->get_section_count(obj);
64
65 if (cnt == 0) {
66 DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_INFO_NULL);
67 return (DW_DLE_DEBUG_INFO_NULL);
68 }
69
70 dbg->dbg_seccnt = cnt;
71
72 if ((dbg->dbg_section = calloc(cnt + 1, sizeof(Dwarf_Section))) ==
73 NULL) {
74 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
75 return (DW_DLE_MEMORY);
76 }
77
78 for (i = 0; i < cnt; i++) {
79 if (m->get_section_info(obj, i, &sec, &ret) != DW_DLV_OK) {
80 DWARF_SET_ERROR(dbg, error, ret);
81 return (ret);
82 }
83
84 dbg->dbg_section[i].ds_addr = sec.addr;
85 dbg->dbg_section[i].ds_size = sec.size;
86 dbg->dbg_section[i].ds_name = sec.name;
87
88 if (m->load_section(obj, i, &dbg->dbg_section[i].ds_data, &ret)
89 != DW_DLV_OK) {
90 DWARF_SET_ERROR(dbg, error, ret);
91 return (ret);
92 }
93 }
94 dbg->dbg_section[cnt].ds_name = NULL;
95
96 dbg->dbg_info_sec = _dwarf_find_section(dbg, ".debug_info");
97
98 /* Try to find the optional DWARF4 .debug_types section. */
99 dbg->dbg_types_sec = _dwarf_find_next_types_section(dbg, NULL);
100
101 /* Initialise call frame API related parameters. */
102 _dwarf_frame_params_init(dbg);
103
104 return (DW_DLV_OK);
105 }
106
107 static int
_dwarf_producer_init(Dwarf_Debug dbg,Dwarf_Unsigned pf,Dwarf_Error * error)108 _dwarf_producer_init(Dwarf_Debug dbg, Dwarf_Unsigned pf, Dwarf_Error *error)
109 {
110
111 /* Producer only support DWARF2 which has fixed 32bit offset. */
112 dbg->dbg_offset_size = 4;
113
114 if (pf & DW_DLC_SIZE_32 && pf & DW_DLC_SIZE_64) {
115 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
116 return (DW_DLE_ARGUMENT);
117 }
118
119 if ((pf & DW_DLC_SIZE_32) == 0 && (pf & DW_DLC_SIZE_64) == 0)
120 pf |= DW_DLC_SIZE_32;
121
122 if (pf & DW_DLC_SIZE_64)
123 dbg->dbg_pointer_size = 8;
124 else
125 dbg->dbg_pointer_size = 4;
126
127 if (pf & DW_DLC_ISA_IA64 && pf & DW_DLC_ISA_MIPS) {
128 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
129 return (DW_DLE_ARGUMENT);
130 }
131
132 if (pf & DW_DLC_ISA_IA64)
133 dbg->dbgp_isa = DW_ISA_IA64;
134 else
135 dbg->dbgp_isa = DW_ISA_MIPS;
136
137 if (pf & DW_DLC_TARGET_BIGENDIAN && pf & DW_DLC_TARGET_LITTLEENDIAN) {
138 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
139 return (DW_DLE_ARGUMENT);
140 }
141
142 if ((pf & DW_DLC_TARGET_BIGENDIAN) == 0 &&
143 (pf & DW_DLC_TARGET_LITTLEENDIAN) == 0) {
144 #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_BIG_ENDIAN
145 pf |= DW_DLC_TARGET_BIGENDIAN;
146 #else
147 pf |= DW_DLC_TARGET_LITTLEENDIAN;
148 #endif
149 }
150
151 if (pf & DW_DLC_TARGET_BIGENDIAN) {
152 dbg->write = _dwarf_write_msb;
153 dbg->write_alloc = _dwarf_write_msb_alloc;
154 } else if (pf & DW_DLC_TARGET_LITTLEENDIAN) {
155 dbg->write = _dwarf_write_lsb;
156 dbg->write_alloc = _dwarf_write_lsb_alloc;
157 } else
158 assert(0);
159
160 if (pf & DW_DLC_STREAM_RELOCATIONS &&
161 pf & DW_DLC_SYMBOLIC_RELOCATIONS) {
162 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
163 return (DW_DLE_ARGUMENT);
164 }
165
166 if ((pf & DW_DLC_STREAM_RELOCATIONS) == 0 &&
167 (pf & DW_DLC_SYMBOLIC_RELOCATIONS) == 0)
168 pf |= DW_DLC_STREAM_RELOCATIONS;
169
170 dbg->dbgp_flags = pf;
171
172 STAILQ_INIT(&dbg->dbgp_dielist);
173 STAILQ_INIT(&dbg->dbgp_pelist);
174 STAILQ_INIT(&dbg->dbgp_seclist);
175 STAILQ_INIT(&dbg->dbgp_drslist);
176 STAILQ_INIT(&dbg->dbgp_cielist);
177 STAILQ_INIT(&dbg->dbgp_fdelist);
178
179 if ((dbg->dbgp_lineinfo = calloc(1, sizeof(struct _Dwarf_LineInfo))) ==
180 NULL) {
181 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
182 return (DW_DLE_MEMORY);
183 }
184 STAILQ_INIT(&dbg->dbgp_lineinfo->li_lflist);
185 STAILQ_INIT(&dbg->dbgp_lineinfo->li_lnlist);
186
187 if ((dbg->dbgp_as = calloc(1, sizeof(struct _Dwarf_ArangeSet))) ==
188 NULL) {
189 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
190 return (DW_DLE_MEMORY);
191 }
192 STAILQ_INIT(&dbg->dbgp_as->as_arlist);
193
194 return (DW_DLE_NONE);
195 }
196
197 int
_dwarf_init(Dwarf_Debug dbg,Dwarf_Unsigned pro_flags,Dwarf_Handler errhand,Dwarf_Ptr errarg,Dwarf_Error * error)198 _dwarf_init(Dwarf_Debug dbg, Dwarf_Unsigned pro_flags, Dwarf_Handler errhand,
199 Dwarf_Ptr errarg, Dwarf_Error *error)
200 {
201 int ret;
202
203 ret = DW_DLE_NONE;
204
205 /*
206 * Set the error handler fields early, so that the application
207 * is notified of initialization errors.
208 */
209 dbg->dbg_errhand = errhand;
210 dbg->dbg_errarg = errarg;
211
212 STAILQ_INIT(&dbg->dbg_cu);
213 STAILQ_INIT(&dbg->dbg_tu);
214 STAILQ_INIT(&dbg->dbg_rllist);
215 STAILQ_INIT(&dbg->dbg_aslist);
216 STAILQ_INIT(&dbg->dbg_mslist);
217
218 if (dbg->dbg_mode == DW_DLC_READ || dbg->dbg_mode == DW_DLC_RDWR) {
219 ret = _dwarf_consumer_init(dbg, error);
220 if (ret != DW_DLE_NONE) {
221 _dwarf_deinit(dbg);
222 return (ret);
223 }
224 }
225
226 if (dbg->dbg_mode == DW_DLC_WRITE) {
227 ret = _dwarf_producer_init(dbg, pro_flags, error);
228 if (ret != DW_DLE_NONE) {
229 _dwarf_deinit(dbg);
230 return (ret);
231 }
232 }
233
234 /*
235 * Initialise internal string table.
236 */
237 if ((ret = _dwarf_strtab_init(dbg, error)) != DW_DLE_NONE)
238 return (ret);
239
240 return (DW_DLE_NONE);
241 }
242
243 static void
_dwarf_producer_deinit(Dwarf_P_Debug dbg)244 _dwarf_producer_deinit(Dwarf_P_Debug dbg)
245 {
246
247 assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
248
249 _dwarf_info_pro_cleanup(dbg);
250 _dwarf_die_pro_cleanup(dbg);
251 _dwarf_expr_cleanup(dbg);
252 _dwarf_lineno_pro_cleanup(dbg);
253 _dwarf_frame_pro_cleanup(dbg);
254 _dwarf_arange_pro_cleanup(dbg);
255 _dwarf_macinfo_pro_cleanup(dbg);
256 _dwarf_strtab_cleanup(dbg);
257 _dwarf_nametbl_pro_cleanup(&dbg->dbgp_pubs);
258 _dwarf_nametbl_pro_cleanup(&dbg->dbgp_weaks);
259 _dwarf_nametbl_pro_cleanup(&dbg->dbgp_funcs);
260 _dwarf_nametbl_pro_cleanup(&dbg->dbgp_types);
261 _dwarf_nametbl_pro_cleanup(&dbg->dbgp_vars);
262 _dwarf_section_cleanup(dbg);
263 _dwarf_reloc_cleanup(dbg);
264 }
265
266 static void
_dwarf_consumer_deinit(Dwarf_Debug dbg)267 _dwarf_consumer_deinit(Dwarf_Debug dbg)
268 {
269
270 assert(dbg != NULL && dbg->dbg_mode == DW_DLC_READ);
271
272 _dwarf_info_cleanup(dbg);
273 _dwarf_ranges_cleanup(dbg);
274 _dwarf_frame_cleanup(dbg);
275 _dwarf_arange_cleanup(dbg);
276 _dwarf_macinfo_cleanup(dbg);
277 _dwarf_strtab_cleanup(dbg);
278 _dwarf_nametbl_cleanup(&dbg->dbg_globals);
279 _dwarf_nametbl_cleanup(&dbg->dbg_pubtypes);
280 _dwarf_nametbl_cleanup(&dbg->dbg_weaks);
281 _dwarf_nametbl_cleanup(&dbg->dbg_funcs);
282 _dwarf_nametbl_cleanup(&dbg->dbg_vars);
283 _dwarf_nametbl_cleanup(&dbg->dbg_types);
284
285 free(dbg->dbg_section);
286 }
287
288 void
_dwarf_deinit(Dwarf_Debug dbg)289 _dwarf_deinit(Dwarf_Debug dbg)
290 {
291
292 assert(dbg != NULL);
293
294 if (dbg->dbg_mode == DW_DLC_READ)
295 _dwarf_consumer_deinit(dbg);
296 else if (dbg->dbg_mode == DW_DLC_WRITE)
297 _dwarf_producer_deinit(dbg);
298 }
299
300 int
_dwarf_alloc(Dwarf_Debug * ret_dbg,int mode,Dwarf_Error * error)301 _dwarf_alloc(Dwarf_Debug *ret_dbg, int mode, Dwarf_Error *error)
302 {
303 Dwarf_Debug dbg;
304
305 if ((dbg = calloc(1, sizeof(struct _Dwarf_Debug))) == NULL) {
306 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
307 return (DW_DLE_MEMORY);
308 }
309
310 dbg->dbg_mode = mode;
311
312 *ret_dbg = dbg;
313
314 return (DW_DLE_NONE);
315 }
316