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