libdwarf_init.c revision 276371
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
29ELFTC_VCSID("$Id: libdwarf_init.c 3061 2014-06-02 00:42:41Z kaiwang27 $");
30
31static int
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	if (_dwarf_find_section(dbg, ".debug_abbrev") == NULL ||
97	    ((dbg->dbg_info_sec = _dwarf_find_section(dbg, ".debug_info")) ==
98	     NULL)) {
99		DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_INFO_NULL);
100		return (DW_DLE_DEBUG_INFO_NULL);
101	}
102
103	/* Try to find the optional DWARF4 .debug_types section. */
104	dbg->dbg_types_sec = _dwarf_find_next_types_section(dbg, NULL);
105
106	/* Initialise call frame API related parameters. */
107	_dwarf_frame_params_init(dbg);
108
109	return (DW_DLV_OK);
110}
111
112static int
113_dwarf_producer_init(Dwarf_Debug dbg, Dwarf_Unsigned pf, Dwarf_Error *error)
114{
115
116	/* Producer only support DWARF2 which has fixed 32bit offset. */
117	dbg->dbg_offset_size = 4;
118
119	if (pf & DW_DLC_SIZE_32 && pf & DW_DLC_SIZE_64) {
120		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
121		return (DW_DLE_ARGUMENT);
122	}
123
124	if ((pf & DW_DLC_SIZE_32) == 0 && (pf & DW_DLC_SIZE_64) == 0)
125		pf |= DW_DLC_SIZE_32;
126
127	if (pf & DW_DLC_SIZE_64)
128		dbg->dbg_pointer_size = 8;
129	else
130		dbg->dbg_pointer_size = 4;
131
132	if (pf & DW_DLC_ISA_IA64 && pf & DW_DLC_ISA_MIPS) {
133		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
134		return (DW_DLE_ARGUMENT);
135	}
136
137	if (pf & DW_DLC_ISA_IA64)
138		dbg->dbgp_isa = DW_ISA_IA64;
139	else
140		dbg->dbgp_isa = DW_ISA_MIPS;
141
142	if (pf & DW_DLC_TARGET_BIGENDIAN && pf & DW_DLC_TARGET_LITTLEENDIAN) {
143		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
144		return (DW_DLE_ARGUMENT);
145	}
146
147	if ((pf & DW_DLC_TARGET_BIGENDIAN) == 0 &&
148	    (pf & DW_DLC_TARGET_LITTLEENDIAN) == 0) {
149#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_BIG_ENDIAN
150		pf |= DW_DLC_TARGET_BIGENDIAN;
151#else
152		pf |= DW_DLC_TARGET_LITTLEENDIAN;
153#endif
154	}
155
156	if (pf & DW_DLC_TARGET_BIGENDIAN) {
157		dbg->write = _dwarf_write_msb;
158		dbg->write_alloc = _dwarf_write_msb_alloc;
159	} else if (pf & DW_DLC_TARGET_LITTLEENDIAN) {
160		dbg->write = _dwarf_write_lsb;
161		dbg->write_alloc = _dwarf_write_lsb_alloc;
162	} else
163		assert(0);
164
165	if (pf & DW_DLC_STREAM_RELOCATIONS &&
166	    pf & DW_DLC_SYMBOLIC_RELOCATIONS) {
167		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
168		return (DW_DLE_ARGUMENT);
169	}
170
171	if ((pf & DW_DLC_STREAM_RELOCATIONS) == 0 &&
172	    (pf & DW_DLC_SYMBOLIC_RELOCATIONS) == 0)
173		pf |= DW_DLC_STREAM_RELOCATIONS;
174
175	dbg->dbgp_flags = pf;
176
177	STAILQ_INIT(&dbg->dbgp_dielist);
178	STAILQ_INIT(&dbg->dbgp_pelist);
179	STAILQ_INIT(&dbg->dbgp_seclist);
180	STAILQ_INIT(&dbg->dbgp_drslist);
181	STAILQ_INIT(&dbg->dbgp_cielist);
182	STAILQ_INIT(&dbg->dbgp_fdelist);
183
184	if ((dbg->dbgp_lineinfo = calloc(1, sizeof(struct _Dwarf_LineInfo))) ==
185	    NULL) {
186		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
187		return (DW_DLE_MEMORY);
188	}
189	STAILQ_INIT(&dbg->dbgp_lineinfo->li_lflist);
190	STAILQ_INIT(&dbg->dbgp_lineinfo->li_lnlist);
191
192	if ((dbg->dbgp_as = calloc(1, sizeof(struct _Dwarf_ArangeSet))) ==
193	    NULL) {
194		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
195		return (DW_DLE_MEMORY);
196	}
197	STAILQ_INIT(&dbg->dbgp_as->as_arlist);
198
199	return (DW_DLE_NONE);
200}
201
202int
203_dwarf_init(Dwarf_Debug dbg, Dwarf_Unsigned pro_flags, Dwarf_Handler errhand,
204    Dwarf_Ptr errarg, Dwarf_Error *error)
205{
206	int ret;
207
208	ret = DW_DLE_NONE;
209
210	/*
211	 * Set the error handler fields early, so that the application
212	 * is notified of initialization errors.
213	 */
214	dbg->dbg_errhand = errhand;
215	dbg->dbg_errarg = errarg;
216
217	STAILQ_INIT(&dbg->dbg_cu);
218	STAILQ_INIT(&dbg->dbg_tu);
219	STAILQ_INIT(&dbg->dbg_rllist);
220	STAILQ_INIT(&dbg->dbg_aslist);
221	STAILQ_INIT(&dbg->dbg_mslist);
222
223	if (dbg->dbg_mode == DW_DLC_READ || dbg->dbg_mode == DW_DLC_RDWR) {
224		ret = _dwarf_consumer_init(dbg, error);
225		if (ret != DW_DLE_NONE) {
226			_dwarf_deinit(dbg);
227			return (ret);
228		}
229	}
230
231	if (dbg->dbg_mode == DW_DLC_WRITE) {
232		ret = _dwarf_producer_init(dbg, pro_flags, error);
233		if (ret != DW_DLE_NONE) {
234			_dwarf_deinit(dbg);
235			return (ret);
236		}
237	}
238
239	/*
240	 * Initialise internal string table.
241	 */
242	if ((ret = _dwarf_strtab_init(dbg, error)) != DW_DLE_NONE)
243		return (ret);
244
245	return (DW_DLE_NONE);
246}
247
248static void
249_dwarf_producer_deinit(Dwarf_P_Debug dbg)
250{
251
252	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
253
254	_dwarf_info_pro_cleanup(dbg);
255	_dwarf_die_pro_cleanup(dbg);
256	_dwarf_expr_cleanup(dbg);
257	_dwarf_lineno_pro_cleanup(dbg);
258	_dwarf_frame_pro_cleanup(dbg);
259	_dwarf_arange_pro_cleanup(dbg);
260	_dwarf_macinfo_pro_cleanup(dbg);
261	_dwarf_strtab_cleanup(dbg);
262	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_pubs);
263	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_weaks);
264	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_funcs);
265	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_types);
266	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_vars);
267	_dwarf_section_cleanup(dbg);
268	_dwarf_reloc_cleanup(dbg);
269}
270
271static void
272_dwarf_consumer_deinit(Dwarf_Debug dbg)
273{
274
275	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_READ);
276
277	_dwarf_info_cleanup(dbg);
278	_dwarf_ranges_cleanup(dbg);
279	_dwarf_frame_cleanup(dbg);
280	_dwarf_arange_cleanup(dbg);
281	_dwarf_macinfo_cleanup(dbg);
282	_dwarf_strtab_cleanup(dbg);
283	_dwarf_nametbl_cleanup(&dbg->dbg_globals);
284	_dwarf_nametbl_cleanup(&dbg->dbg_pubtypes);
285	_dwarf_nametbl_cleanup(&dbg->dbg_weaks);
286	_dwarf_nametbl_cleanup(&dbg->dbg_funcs);
287	_dwarf_nametbl_cleanup(&dbg->dbg_vars);
288	_dwarf_nametbl_cleanup(&dbg->dbg_types);
289
290	free(dbg->dbg_section);
291}
292
293void
294_dwarf_deinit(Dwarf_Debug dbg)
295{
296
297	assert(dbg != NULL);
298
299	if (dbg->dbg_mode == DW_DLC_READ)
300		_dwarf_consumer_deinit(dbg);
301	else if (dbg->dbg_mode == DW_DLC_WRITE)
302		_dwarf_producer_deinit(dbg);
303}
304
305int
306_dwarf_alloc(Dwarf_Debug *ret_dbg, int mode, Dwarf_Error *error)
307{
308	Dwarf_Debug dbg;
309
310	if ((dbg = calloc(sizeof(struct _Dwarf_Debug), 1)) == NULL) {
311		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
312		return (DW_DLE_MEMORY);
313	}
314
315	dbg->dbg_mode = mode;
316
317	*ret_dbg = dbg;
318
319	return (DW_DLE_NONE);
320}
321