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
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
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
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
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
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
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
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