1260684Skaiw/*-
2260684Skaiw * Copyright (c) 2009,2011 Kai Wang
3260684Skaiw * All rights reserved.
4260684Skaiw *
5260684Skaiw * Redistribution and use in source and binary forms, with or without
6260684Skaiw * modification, are permitted provided that the following conditions
7260684Skaiw * are met:
8260684Skaiw * 1. Redistributions of source code must retain the above copyright
9260684Skaiw *    notice, this list of conditions and the following disclaimer.
10260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright
11260684Skaiw *    notice, this list of conditions and the following disclaimer in the
12260684Skaiw *    documentation and/or other materials provided with the distribution.
13260684Skaiw *
14260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15260684Skaiw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16260684Skaiw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17260684Skaiw * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18260684Skaiw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19260684Skaiw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20260684Skaiw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21260684Skaiw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22260684Skaiw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23260684Skaiw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24260684Skaiw * SUCH DAMAGE.
25260684Skaiw */
26260684Skaiw
27260684Skaiw#include "_libdwarf.h"
28260684Skaiw
29276398SemasteELFTC_VCSID("$Id: libdwarf_init.c 3136 2014-12-24 16:04:38Z kaiwang27 $");
30260684Skaiw
31260684Skaiwstatic int
32260684Skaiw_dwarf_consumer_init(Dwarf_Debug dbg, Dwarf_Error *error)
33260684Skaiw{
34260684Skaiw	const Dwarf_Obj_Access_Methods *m;
35260684Skaiw	Dwarf_Obj_Access_Section sec;
36260684Skaiw	void *obj;
37260684Skaiw	Dwarf_Unsigned cnt;
38260684Skaiw	Dwarf_Half i;
39260684Skaiw	int ret;
40260684Skaiw
41260684Skaiw	assert(dbg != NULL);
42260684Skaiw	assert(dbg->dbg_iface != NULL);
43260684Skaiw
44260684Skaiw	m = dbg->dbg_iface->methods;
45260684Skaiw	obj = dbg->dbg_iface->object;
46260684Skaiw
47260684Skaiw	assert(m != NULL);
48260684Skaiw	assert(obj != NULL);
49260684Skaiw
50260684Skaiw	if (m->get_byte_order(obj) == DW_OBJECT_MSB) {
51260684Skaiw		dbg->read = _dwarf_read_msb;
52260684Skaiw		dbg->write = _dwarf_write_msb;
53260684Skaiw		dbg->decode = _dwarf_decode_msb;
54260684Skaiw	} else {
55260684Skaiw		dbg->read = _dwarf_read_lsb;
56260684Skaiw		dbg->write = _dwarf_write_lsb;
57260684Skaiw		dbg->decode = _dwarf_decode_lsb;
58260684Skaiw	}
59260684Skaiw
60260684Skaiw	dbg->dbg_pointer_size = m->get_pointer_size(obj);
61260684Skaiw	dbg->dbg_offset_size = m->get_length_size(obj);
62260684Skaiw
63260684Skaiw	cnt = m->get_section_count(obj);
64260684Skaiw
65260684Skaiw	if (cnt == 0) {
66260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_INFO_NULL);
67260684Skaiw		return (DW_DLE_DEBUG_INFO_NULL);
68260684Skaiw	}
69260684Skaiw
70260684Skaiw	dbg->dbg_seccnt = cnt;
71260684Skaiw
72276371Semaste	if ((dbg->dbg_section = calloc(cnt + 1, sizeof(Dwarf_Section))) ==
73276371Semaste	    NULL) {
74260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
75260684Skaiw		return (DW_DLE_MEMORY);
76260684Skaiw	}
77260684Skaiw
78260684Skaiw	for (i = 0; i < cnt; i++) {
79260684Skaiw		if (m->get_section_info(obj, i, &sec, &ret) != DW_DLV_OK) {
80260684Skaiw			DWARF_SET_ERROR(dbg, error, ret);
81260684Skaiw			return (ret);
82260684Skaiw		}
83260684Skaiw
84260684Skaiw		dbg->dbg_section[i].ds_addr = sec.addr;
85260684Skaiw		dbg->dbg_section[i].ds_size = sec.size;
86260684Skaiw		dbg->dbg_section[i].ds_name = sec.name;
87260684Skaiw
88260684Skaiw		if (m->load_section(obj, i, &dbg->dbg_section[i].ds_data, &ret)
89260684Skaiw		    != DW_DLV_OK) {
90260684Skaiw			DWARF_SET_ERROR(dbg, error, ret);
91260684Skaiw			return (ret);
92260684Skaiw		}
93260684Skaiw	}
94276371Semaste	dbg->dbg_section[cnt].ds_name = NULL;
95260684Skaiw
96276398Semaste	dbg->dbg_info_sec = _dwarf_find_section(dbg, ".debug_info");
97260684Skaiw
98276371Semaste	/* Try to find the optional DWARF4 .debug_types section. */
99276371Semaste	dbg->dbg_types_sec = _dwarf_find_next_types_section(dbg, NULL);
100276371Semaste
101260684Skaiw	/* Initialise call frame API related parameters. */
102260684Skaiw	_dwarf_frame_params_init(dbg);
103260684Skaiw
104260684Skaiw	return (DW_DLV_OK);
105260684Skaiw}
106260684Skaiw
107260684Skaiwstatic int
108260684Skaiw_dwarf_producer_init(Dwarf_Debug dbg, Dwarf_Unsigned pf, Dwarf_Error *error)
109260684Skaiw{
110260684Skaiw
111260684Skaiw	/* Producer only support DWARF2 which has fixed 32bit offset. */
112260684Skaiw	dbg->dbg_offset_size = 4;
113260684Skaiw
114260684Skaiw	if (pf & DW_DLC_SIZE_32 && pf & DW_DLC_SIZE_64) {
115260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
116260684Skaiw		return (DW_DLE_ARGUMENT);
117260684Skaiw	}
118260684Skaiw
119260684Skaiw	if ((pf & DW_DLC_SIZE_32) == 0 && (pf & DW_DLC_SIZE_64) == 0)
120260684Skaiw		pf |= DW_DLC_SIZE_32;
121260684Skaiw
122260684Skaiw	if (pf & DW_DLC_SIZE_64)
123260684Skaiw		dbg->dbg_pointer_size = 8;
124260684Skaiw	else
125260684Skaiw		dbg->dbg_pointer_size = 4;
126260684Skaiw
127260684Skaiw	if (pf & DW_DLC_ISA_IA64 && pf & DW_DLC_ISA_MIPS) {
128260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
129260684Skaiw		return (DW_DLE_ARGUMENT);
130260684Skaiw	}
131260684Skaiw
132260684Skaiw	if (pf & DW_DLC_ISA_IA64)
133260684Skaiw		dbg->dbgp_isa = DW_ISA_IA64;
134260684Skaiw	else
135260684Skaiw		dbg->dbgp_isa = DW_ISA_MIPS;
136260684Skaiw
137260684Skaiw	if (pf & DW_DLC_TARGET_BIGENDIAN && pf & DW_DLC_TARGET_LITTLEENDIAN) {
138260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
139260684Skaiw		return (DW_DLE_ARGUMENT);
140260684Skaiw	}
141260684Skaiw
142260684Skaiw	if ((pf & DW_DLC_TARGET_BIGENDIAN) == 0 &&
143260684Skaiw	    (pf & DW_DLC_TARGET_LITTLEENDIAN) == 0) {
144260684Skaiw#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_BIG_ENDIAN
145260684Skaiw		pf |= DW_DLC_TARGET_BIGENDIAN;
146260684Skaiw#else
147260684Skaiw		pf |= DW_DLC_TARGET_LITTLEENDIAN;
148260684Skaiw#endif
149260684Skaiw	}
150260684Skaiw
151260684Skaiw	if (pf & DW_DLC_TARGET_BIGENDIAN) {
152260684Skaiw		dbg->write = _dwarf_write_msb;
153260684Skaiw		dbg->write_alloc = _dwarf_write_msb_alloc;
154260684Skaiw	} else if (pf & DW_DLC_TARGET_LITTLEENDIAN) {
155260684Skaiw		dbg->write = _dwarf_write_lsb;
156260684Skaiw		dbg->write_alloc = _dwarf_write_lsb_alloc;
157260684Skaiw	} else
158260684Skaiw		assert(0);
159260684Skaiw
160260684Skaiw	if (pf & DW_DLC_STREAM_RELOCATIONS &&
161260684Skaiw	    pf & DW_DLC_SYMBOLIC_RELOCATIONS) {
162260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
163260684Skaiw		return (DW_DLE_ARGUMENT);
164260684Skaiw	}
165260684Skaiw
166260684Skaiw	if ((pf & DW_DLC_STREAM_RELOCATIONS) == 0 &&
167260684Skaiw	    (pf & DW_DLC_SYMBOLIC_RELOCATIONS) == 0)
168260684Skaiw		pf |= DW_DLC_STREAM_RELOCATIONS;
169260684Skaiw
170260684Skaiw	dbg->dbgp_flags = pf;
171260684Skaiw
172260684Skaiw	STAILQ_INIT(&dbg->dbgp_dielist);
173260684Skaiw	STAILQ_INIT(&dbg->dbgp_pelist);
174260684Skaiw	STAILQ_INIT(&dbg->dbgp_seclist);
175260684Skaiw	STAILQ_INIT(&dbg->dbgp_drslist);
176260684Skaiw	STAILQ_INIT(&dbg->dbgp_cielist);
177260684Skaiw	STAILQ_INIT(&dbg->dbgp_fdelist);
178260684Skaiw
179260684Skaiw	if ((dbg->dbgp_lineinfo = calloc(1, sizeof(struct _Dwarf_LineInfo))) ==
180260684Skaiw	    NULL) {
181260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
182260684Skaiw		return (DW_DLE_MEMORY);
183260684Skaiw	}
184260684Skaiw	STAILQ_INIT(&dbg->dbgp_lineinfo->li_lflist);
185260684Skaiw	STAILQ_INIT(&dbg->dbgp_lineinfo->li_lnlist);
186260684Skaiw
187260684Skaiw	if ((dbg->dbgp_as = calloc(1, sizeof(struct _Dwarf_ArangeSet))) ==
188260684Skaiw	    NULL) {
189260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
190260684Skaiw		return (DW_DLE_MEMORY);
191260684Skaiw	}
192260684Skaiw	STAILQ_INIT(&dbg->dbgp_as->as_arlist);
193260684Skaiw
194260684Skaiw	return (DW_DLE_NONE);
195260684Skaiw}
196260684Skaiw
197260684Skaiwint
198260684Skaiw_dwarf_init(Dwarf_Debug dbg, Dwarf_Unsigned pro_flags, Dwarf_Handler errhand,
199260684Skaiw    Dwarf_Ptr errarg, Dwarf_Error *error)
200260684Skaiw{
201260684Skaiw	int ret;
202260684Skaiw
203260684Skaiw	ret = DW_DLE_NONE;
204260684Skaiw
205260684Skaiw	/*
206260684Skaiw	 * Set the error handler fields early, so that the application
207260684Skaiw	 * is notified of initialization errors.
208260684Skaiw	 */
209260684Skaiw	dbg->dbg_errhand = errhand;
210260684Skaiw	dbg->dbg_errarg = errarg;
211260684Skaiw
212260684Skaiw	STAILQ_INIT(&dbg->dbg_cu);
213276371Semaste	STAILQ_INIT(&dbg->dbg_tu);
214260684Skaiw	STAILQ_INIT(&dbg->dbg_rllist);
215260684Skaiw	STAILQ_INIT(&dbg->dbg_aslist);
216260684Skaiw	STAILQ_INIT(&dbg->dbg_mslist);
217260684Skaiw
218260684Skaiw	if (dbg->dbg_mode == DW_DLC_READ || dbg->dbg_mode == DW_DLC_RDWR) {
219260684Skaiw		ret = _dwarf_consumer_init(dbg, error);
220260684Skaiw		if (ret != DW_DLE_NONE) {
221260684Skaiw			_dwarf_deinit(dbg);
222260684Skaiw			return (ret);
223260684Skaiw		}
224260684Skaiw	}
225260684Skaiw
226260684Skaiw	if (dbg->dbg_mode == DW_DLC_WRITE) {
227260684Skaiw		ret = _dwarf_producer_init(dbg, pro_flags, error);
228260684Skaiw		if (ret != DW_DLE_NONE) {
229260684Skaiw			_dwarf_deinit(dbg);
230260684Skaiw			return (ret);
231260684Skaiw		}
232260684Skaiw	}
233260684Skaiw
234260684Skaiw	/*
235260684Skaiw	 * Initialise internal string table.
236260684Skaiw	 */
237260684Skaiw	if ((ret = _dwarf_strtab_init(dbg, error)) != DW_DLE_NONE)
238260684Skaiw		return (ret);
239260684Skaiw
240260684Skaiw	return (DW_DLE_NONE);
241260684Skaiw}
242260684Skaiw
243260684Skaiwstatic void
244260684Skaiw_dwarf_producer_deinit(Dwarf_P_Debug dbg)
245260684Skaiw{
246260684Skaiw
247260684Skaiw	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
248260684Skaiw
249260684Skaiw	_dwarf_info_pro_cleanup(dbg);
250260684Skaiw	_dwarf_die_pro_cleanup(dbg);
251260684Skaiw	_dwarf_expr_cleanup(dbg);
252260684Skaiw	_dwarf_lineno_pro_cleanup(dbg);
253260684Skaiw	_dwarf_frame_pro_cleanup(dbg);
254260684Skaiw	_dwarf_arange_pro_cleanup(dbg);
255260684Skaiw	_dwarf_macinfo_pro_cleanup(dbg);
256260684Skaiw	_dwarf_strtab_cleanup(dbg);
257260684Skaiw	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_pubs);
258260684Skaiw	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_weaks);
259260684Skaiw	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_funcs);
260260684Skaiw	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_types);
261260684Skaiw	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_vars);
262260684Skaiw	_dwarf_section_cleanup(dbg);
263260684Skaiw	_dwarf_reloc_cleanup(dbg);
264260684Skaiw}
265260684Skaiw
266260684Skaiwstatic void
267260684Skaiw_dwarf_consumer_deinit(Dwarf_Debug dbg)
268260684Skaiw{
269260684Skaiw
270260684Skaiw	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_READ);
271260684Skaiw
272260684Skaiw	_dwarf_info_cleanup(dbg);
273260684Skaiw	_dwarf_ranges_cleanup(dbg);
274260684Skaiw	_dwarf_frame_cleanup(dbg);
275260684Skaiw	_dwarf_arange_cleanup(dbg);
276260684Skaiw	_dwarf_macinfo_cleanup(dbg);
277260684Skaiw	_dwarf_strtab_cleanup(dbg);
278260684Skaiw	_dwarf_nametbl_cleanup(&dbg->dbg_globals);
279260684Skaiw	_dwarf_nametbl_cleanup(&dbg->dbg_pubtypes);
280260684Skaiw	_dwarf_nametbl_cleanup(&dbg->dbg_weaks);
281260684Skaiw	_dwarf_nametbl_cleanup(&dbg->dbg_funcs);
282260684Skaiw	_dwarf_nametbl_cleanup(&dbg->dbg_vars);
283260684Skaiw	_dwarf_nametbl_cleanup(&dbg->dbg_types);
284260684Skaiw
285260684Skaiw	free(dbg->dbg_section);
286260684Skaiw}
287260684Skaiw
288260684Skaiwvoid
289260684Skaiw_dwarf_deinit(Dwarf_Debug dbg)
290260684Skaiw{
291260684Skaiw
292260684Skaiw	assert(dbg != NULL);
293260684Skaiw
294260684Skaiw	if (dbg->dbg_mode == DW_DLC_READ)
295260684Skaiw		_dwarf_consumer_deinit(dbg);
296260684Skaiw	else if (dbg->dbg_mode == DW_DLC_WRITE)
297260684Skaiw		_dwarf_producer_deinit(dbg);
298260684Skaiw}
299260684Skaiw
300260684Skaiwint
301260684Skaiw_dwarf_alloc(Dwarf_Debug *ret_dbg, int mode, Dwarf_Error *error)
302260684Skaiw{
303260684Skaiw	Dwarf_Debug dbg;
304260684Skaiw
305260684Skaiw	if ((dbg = calloc(sizeof(struct _Dwarf_Debug), 1)) == NULL) {
306260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
307260684Skaiw		return (DW_DLE_MEMORY);
308260684Skaiw	}
309260684Skaiw
310260684Skaiw	dbg->dbg_mode = mode;
311260684Skaiw
312260684Skaiw	*ret_dbg = dbg;
313260684Skaiw
314260684Skaiw	return (DW_DLE_NONE);
315260684Skaiw}
316