libdwarf_init.c revision 276398
154095Ssemenu/*-
247060Ssemenu * Copyright (c) 2009,2011 Kai Wang
343552Ssemenu * All rights reserved.
443552Ssemenu *
543552Ssemenu * Redistribution and use in source and binary forms, with or without
643552Ssemenu * modification, are permitted provided that the following conditions
743552Ssemenu * are met:
843552Ssemenu * 1. Redistributions of source code must retain the above copyright
943552Ssemenu *    notice, this list of conditions and the following disclaimer.
1043552Ssemenu * 2. Redistributions in binary form must reproduce the above copyright
1143552Ssemenu *    notice, this list of conditions and the following disclaimer in the
1243552Ssemenu *    documentation and/or other materials provided with the distribution.
1343552Ssemenu *
1443552Ssemenu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1543552Ssemenu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1643552Ssemenu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1743552Ssemenu * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1843552Ssemenu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1943552Ssemenu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2043552Ssemenu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2143552Ssemenu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2243552Ssemenu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2343552Ssemenu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2443552Ssemenu * SUCH DAMAGE.
2543552Ssemenu */
2643552Ssemenu
2743552Ssemenu#include "_libdwarf.h"
2850477Speter
2943552SsemenuELFTC_VCSID("$Id: libdwarf_init.c 3136 2014-12-24 16:04:38Z kaiwang27 $");
3043552Ssemenu
3143552Ssemenustatic int
3247060Ssemenu_dwarf_consumer_init(Dwarf_Debug dbg, Dwarf_Error *error)
3343552Ssemenu{
3443552Ssemenu	const Dwarf_Obj_Access_Methods *m;
3543552Ssemenu	Dwarf_Obj_Access_Section sec;
3643552Ssemenu	void *obj;
3743552Ssemenu	Dwarf_Unsigned cnt;
3843552Ssemenu	Dwarf_Half i;
3943552Ssemenu	int ret;
4047060Ssemenu
4147060Ssemenu	assert(dbg != NULL);
4243552Ssemenu	assert(dbg->dbg_iface != NULL);
4343552Ssemenu
4443552Ssemenu	m = dbg->dbg_iface->methods;
4543552Ssemenu	obj = dbg->dbg_iface->object;
4643552Ssemenu
4743552Ssemenu	assert(m != NULL);
4843552Ssemenu	assert(obj != NULL);
4943552Ssemenu
5043552Ssemenu	if (m->get_byte_order(obj) == DW_OBJECT_MSB) {
5143552Ssemenu		dbg->read = _dwarf_read_msb;
5243552Ssemenu		dbg->write = _dwarf_write_msb;
5343552Ssemenu		dbg->decode = _dwarf_decode_msb;
5443552Ssemenu	} else {
5547060Ssemenu		dbg->read = _dwarf_read_lsb;
5643552Ssemenu		dbg->write = _dwarf_write_lsb;
5743552Ssemenu		dbg->decode = _dwarf_decode_lsb;
5843552Ssemenu	}
5943552Ssemenu
6054095Ssemenu	dbg->dbg_pointer_size = m->get_pointer_size(obj);
6154095Ssemenu	dbg->dbg_offset_size = m->get_length_size(obj);
6254095Ssemenu
6360938Sjake	cnt = m->get_section_count(obj);
6443552Ssemenu
6543552Ssemenu	if (cnt == 0) {
6645879Ssemenu		DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_INFO_NULL);
6744142Ssemenu		return (DW_DLE_DEBUG_INFO_NULL);
6843552Ssemenu	}
6954095Ssemenu
7054095Ssemenu	dbg->dbg_seccnt = cnt;
7154095Ssemenu
7254095Ssemenu	if ((dbg->dbg_section = calloc(cnt + 1, sizeof(Dwarf_Section))) ==
7344142Ssemenu	    NULL) {
7454095Ssemenu		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
7560938Sjake		return (DW_DLE_MEMORY);
7660938Sjake	}
7744142Ssemenu
7843552Ssemenu	for (i = 0; i < cnt; i++) {
7943552Ssemenu		if (m->get_section_info(obj, i, &sec, &ret) != DW_DLV_OK) {
8043552Ssemenu			DWARF_SET_ERROR(dbg, error, ret);
8144142Ssemenu			return (ret);
8243552Ssemenu		}
8344142Ssemenu
8445879Ssemenu		dbg->dbg_section[i].ds_addr = sec.addr;
8544142Ssemenu		dbg->dbg_section[i].ds_size = sec.size;
8644142Ssemenu		dbg->dbg_section[i].ds_name = sec.name;
8754095Ssemenu
8854095Ssemenu		if (m->load_section(obj, i, &dbg->dbg_section[i].ds_data, &ret)
8954095Ssemenu		    != DW_DLV_OK) {
9044142Ssemenu			DWARF_SET_ERROR(dbg, error, ret);
9160938Sjake			return (ret);
9244142Ssemenu		}
9354095Ssemenu	}
9444142Ssemenu	dbg->dbg_section[cnt].ds_name = NULL;
9543552Ssemenu
9644142Ssemenu	dbg->dbg_info_sec = _dwarf_find_section(dbg, ".debug_info");
9744142Ssemenu
9844142Ssemenu	/* Try to find the optional DWARF4 .debug_types section. */
9944142Ssemenu	dbg->dbg_types_sec = _dwarf_find_next_types_section(dbg, NULL);
10044142Ssemenu
10144142Ssemenu	/* Initialise call frame API related parameters. */
10244142Ssemenu	_dwarf_frame_params_init(dbg);
10344142Ssemenu
10444142Ssemenu	return (DW_DLV_OK);
10544142Ssemenu}
10644142Ssemenu
10744142Ssemenustatic int
10844142Ssemenu_dwarf_producer_init(Dwarf_Debug dbg, Dwarf_Unsigned pf, Dwarf_Error *error)
10944142Ssemenu{
11044142Ssemenu
11144142Ssemenu	/* Producer only support DWARF2 which has fixed 32bit offset. */
11243552Ssemenu	dbg->dbg_offset_size = 4;
11354095Ssemenu
11454095Ssemenu	if (pf & DW_DLC_SIZE_32 && pf & DW_DLC_SIZE_64) {
11554095Ssemenu		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
11654095Ssemenu		return (DW_DLE_ARGUMENT);
11754095Ssemenu	}
11854095Ssemenu
11954095Ssemenu	if ((pf & DW_DLC_SIZE_32) == 0 && (pf & DW_DLC_SIZE_64) == 0)
12054095Ssemenu		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
197int
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
243static void
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
266static void
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
288void
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
300int
301_dwarf_alloc(Dwarf_Debug *ret_dbg, int mode, Dwarf_Error *error)
302{
303	Dwarf_Debug dbg;
304
305	if ((dbg = calloc(sizeof(struct _Dwarf_Debug), 1)) == 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