xref: /freebsd/contrib/elftoolchain/libdwarf/libdwarf_init.c (revision cf781b2e16c26535788abe648f5917f4db09c123)
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 3061 2014-06-02 00:42:41Z 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 	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 
112 static 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 
202 int
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 
248 static 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 
271 static 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 
293 void
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 
305 int
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