12de3b87aSKai Wang /*-
22de3b87aSKai Wang  * Copyright (c) 2009,2011 Kai Wang
32de3b87aSKai Wang  * All rights reserved.
42de3b87aSKai Wang  *
52de3b87aSKai Wang  * Redistribution and use in source and binary forms, with or without
62de3b87aSKai Wang  * modification, are permitted provided that the following conditions
72de3b87aSKai Wang  * are met:
82de3b87aSKai Wang  * 1. Redistributions of source code must retain the above copyright
92de3b87aSKai Wang  *    notice, this list of conditions and the following disclaimer.
102de3b87aSKai Wang  * 2. Redistributions in binary form must reproduce the above copyright
112de3b87aSKai Wang  *    notice, this list of conditions and the following disclaimer in the
122de3b87aSKai Wang  *    documentation and/or other materials provided with the distribution.
132de3b87aSKai Wang  *
142de3b87aSKai Wang  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
152de3b87aSKai Wang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
162de3b87aSKai Wang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
172de3b87aSKai Wang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
182de3b87aSKai Wang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
192de3b87aSKai Wang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
202de3b87aSKai Wang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
212de3b87aSKai Wang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
222de3b87aSKai Wang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
232de3b87aSKai Wang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
242de3b87aSKai Wang  * SUCH DAMAGE.
252de3b87aSKai Wang  */
262de3b87aSKai Wang 
272de3b87aSKai Wang #include "_libdwarf.h"
282de3b87aSKai Wang 
29*4a85c691SEd Maste ELFTC_VCSID("$Id: libdwarf_init.c 3136 2014-12-24 16:04:38Z kaiwang27 $");
302de3b87aSKai Wang 
312de3b87aSKai Wang static int
_dwarf_consumer_init(Dwarf_Debug dbg,Dwarf_Error * error)322de3b87aSKai Wang _dwarf_consumer_init(Dwarf_Debug dbg, Dwarf_Error *error)
332de3b87aSKai Wang {
342de3b87aSKai Wang 	const Dwarf_Obj_Access_Methods *m;
352de3b87aSKai Wang 	Dwarf_Obj_Access_Section sec;
362de3b87aSKai Wang 	void *obj;
372de3b87aSKai Wang 	Dwarf_Unsigned cnt;
382de3b87aSKai Wang 	Dwarf_Half i;
392de3b87aSKai Wang 	int ret;
402de3b87aSKai Wang 
412de3b87aSKai Wang 	assert(dbg != NULL);
422de3b87aSKai Wang 	assert(dbg->dbg_iface != NULL);
432de3b87aSKai Wang 
442de3b87aSKai Wang 	m = dbg->dbg_iface->methods;
452de3b87aSKai Wang 	obj = dbg->dbg_iface->object;
462de3b87aSKai Wang 
472de3b87aSKai Wang 	assert(m != NULL);
482de3b87aSKai Wang 	assert(obj != NULL);
492de3b87aSKai Wang 
502de3b87aSKai Wang 	if (m->get_byte_order(obj) == DW_OBJECT_MSB) {
512de3b87aSKai Wang 		dbg->read = _dwarf_read_msb;
522de3b87aSKai Wang 		dbg->write = _dwarf_write_msb;
532de3b87aSKai Wang 		dbg->decode = _dwarf_decode_msb;
542de3b87aSKai Wang 	} else {
552de3b87aSKai Wang 		dbg->read = _dwarf_read_lsb;
562de3b87aSKai Wang 		dbg->write = _dwarf_write_lsb;
572de3b87aSKai Wang 		dbg->decode = _dwarf_decode_lsb;
582de3b87aSKai Wang 	}
592de3b87aSKai Wang 
602de3b87aSKai Wang 	dbg->dbg_pointer_size = m->get_pointer_size(obj);
612de3b87aSKai Wang 	dbg->dbg_offset_size = m->get_length_size(obj);
622de3b87aSKai Wang 
632de3b87aSKai Wang 	cnt = m->get_section_count(obj);
642de3b87aSKai Wang 
652de3b87aSKai Wang 	if (cnt == 0) {
662de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_INFO_NULL);
672de3b87aSKai Wang 		return (DW_DLE_DEBUG_INFO_NULL);
682de3b87aSKai Wang 	}
692de3b87aSKai Wang 
702de3b87aSKai Wang 	dbg->dbg_seccnt = cnt;
712de3b87aSKai Wang 
72cf781b2eSEd Maste 	if ((dbg->dbg_section = calloc(cnt + 1, sizeof(Dwarf_Section))) ==
73cf781b2eSEd Maste 	    NULL) {
742de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
752de3b87aSKai Wang 		return (DW_DLE_MEMORY);
762de3b87aSKai Wang 	}
772de3b87aSKai Wang 
782de3b87aSKai Wang 	for (i = 0; i < cnt; i++) {
792de3b87aSKai Wang 		if (m->get_section_info(obj, i, &sec, &ret) != DW_DLV_OK) {
802de3b87aSKai Wang 			DWARF_SET_ERROR(dbg, error, ret);
812de3b87aSKai Wang 			return (ret);
822de3b87aSKai Wang 		}
832de3b87aSKai Wang 
842de3b87aSKai Wang 		dbg->dbg_section[i].ds_addr = sec.addr;
852de3b87aSKai Wang 		dbg->dbg_section[i].ds_size = sec.size;
862de3b87aSKai Wang 		dbg->dbg_section[i].ds_name = sec.name;
872de3b87aSKai Wang 
882de3b87aSKai Wang 		if (m->load_section(obj, i, &dbg->dbg_section[i].ds_data, &ret)
892de3b87aSKai Wang 		    != DW_DLV_OK) {
902de3b87aSKai Wang 			DWARF_SET_ERROR(dbg, error, ret);
912de3b87aSKai Wang 			return (ret);
922de3b87aSKai Wang 		}
932de3b87aSKai Wang 	}
94cf781b2eSEd Maste 	dbg->dbg_section[cnt].ds_name = NULL;
952de3b87aSKai Wang 
96*4a85c691SEd Maste 	dbg->dbg_info_sec = _dwarf_find_section(dbg, ".debug_info");
972de3b87aSKai Wang 
98cf781b2eSEd Maste 	/* Try to find the optional DWARF4 .debug_types section. */
99cf781b2eSEd Maste 	dbg->dbg_types_sec = _dwarf_find_next_types_section(dbg, NULL);
100cf781b2eSEd Maste 
1012de3b87aSKai Wang 	/* Initialise call frame API related parameters. */
1022de3b87aSKai Wang 	_dwarf_frame_params_init(dbg);
1032de3b87aSKai Wang 
1042de3b87aSKai Wang 	return (DW_DLV_OK);
1052de3b87aSKai Wang }
1062de3b87aSKai Wang 
1072de3b87aSKai Wang static int
_dwarf_producer_init(Dwarf_Debug dbg,Dwarf_Unsigned pf,Dwarf_Error * error)1082de3b87aSKai Wang _dwarf_producer_init(Dwarf_Debug dbg, Dwarf_Unsigned pf, Dwarf_Error *error)
1092de3b87aSKai Wang {
1102de3b87aSKai Wang 
1112de3b87aSKai Wang 	/* Producer only support DWARF2 which has fixed 32bit offset. */
1122de3b87aSKai Wang 	dbg->dbg_offset_size = 4;
1132de3b87aSKai Wang 
1142de3b87aSKai Wang 	if (pf & DW_DLC_SIZE_32 && pf & DW_DLC_SIZE_64) {
1152de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
1162de3b87aSKai Wang 		return (DW_DLE_ARGUMENT);
1172de3b87aSKai Wang 	}
1182de3b87aSKai Wang 
1192de3b87aSKai Wang 	if ((pf & DW_DLC_SIZE_32) == 0 && (pf & DW_DLC_SIZE_64) == 0)
1202de3b87aSKai Wang 		pf |= DW_DLC_SIZE_32;
1212de3b87aSKai Wang 
1222de3b87aSKai Wang 	if (pf & DW_DLC_SIZE_64)
1232de3b87aSKai Wang 		dbg->dbg_pointer_size = 8;
1242de3b87aSKai Wang 	else
1252de3b87aSKai Wang 		dbg->dbg_pointer_size = 4;
1262de3b87aSKai Wang 
1272de3b87aSKai Wang 	if (pf & DW_DLC_ISA_IA64 && pf & DW_DLC_ISA_MIPS) {
1282de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
1292de3b87aSKai Wang 		return (DW_DLE_ARGUMENT);
1302de3b87aSKai Wang 	}
1312de3b87aSKai Wang 
1322de3b87aSKai Wang 	if (pf & DW_DLC_ISA_IA64)
1332de3b87aSKai Wang 		dbg->dbgp_isa = DW_ISA_IA64;
1342de3b87aSKai Wang 	else
1352de3b87aSKai Wang 		dbg->dbgp_isa = DW_ISA_MIPS;
1362de3b87aSKai Wang 
1372de3b87aSKai Wang 	if (pf & DW_DLC_TARGET_BIGENDIAN && pf & DW_DLC_TARGET_LITTLEENDIAN) {
1382de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
1392de3b87aSKai Wang 		return (DW_DLE_ARGUMENT);
1402de3b87aSKai Wang 	}
1412de3b87aSKai Wang 
1422de3b87aSKai Wang 	if ((pf & DW_DLC_TARGET_BIGENDIAN) == 0 &&
1432de3b87aSKai Wang 	    (pf & DW_DLC_TARGET_LITTLEENDIAN) == 0) {
1442de3b87aSKai Wang #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_BIG_ENDIAN
1452de3b87aSKai Wang 		pf |= DW_DLC_TARGET_BIGENDIAN;
1462de3b87aSKai Wang #else
1472de3b87aSKai Wang 		pf |= DW_DLC_TARGET_LITTLEENDIAN;
1482de3b87aSKai Wang #endif
1492de3b87aSKai Wang 	}
1502de3b87aSKai Wang 
1512de3b87aSKai Wang 	if (pf & DW_DLC_TARGET_BIGENDIAN) {
1522de3b87aSKai Wang 		dbg->write = _dwarf_write_msb;
1532de3b87aSKai Wang 		dbg->write_alloc = _dwarf_write_msb_alloc;
1542de3b87aSKai Wang 	} else if (pf & DW_DLC_TARGET_LITTLEENDIAN) {
1552de3b87aSKai Wang 		dbg->write = _dwarf_write_lsb;
1562de3b87aSKai Wang 		dbg->write_alloc = _dwarf_write_lsb_alloc;
1572de3b87aSKai Wang 	} else
1582de3b87aSKai Wang 		assert(0);
1592de3b87aSKai Wang 
1602de3b87aSKai Wang 	if (pf & DW_DLC_STREAM_RELOCATIONS &&
1612de3b87aSKai Wang 	    pf & DW_DLC_SYMBOLIC_RELOCATIONS) {
1622de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
1632de3b87aSKai Wang 		return (DW_DLE_ARGUMENT);
1642de3b87aSKai Wang 	}
1652de3b87aSKai Wang 
1662de3b87aSKai Wang 	if ((pf & DW_DLC_STREAM_RELOCATIONS) == 0 &&
1672de3b87aSKai Wang 	    (pf & DW_DLC_SYMBOLIC_RELOCATIONS) == 0)
1682de3b87aSKai Wang 		pf |= DW_DLC_STREAM_RELOCATIONS;
1692de3b87aSKai Wang 
1702de3b87aSKai Wang 	dbg->dbgp_flags = pf;
1712de3b87aSKai Wang 
1722de3b87aSKai Wang 	STAILQ_INIT(&dbg->dbgp_dielist);
1732de3b87aSKai Wang 	STAILQ_INIT(&dbg->dbgp_pelist);
1742de3b87aSKai Wang 	STAILQ_INIT(&dbg->dbgp_seclist);
1752de3b87aSKai Wang 	STAILQ_INIT(&dbg->dbgp_drslist);
1762de3b87aSKai Wang 	STAILQ_INIT(&dbg->dbgp_cielist);
1772de3b87aSKai Wang 	STAILQ_INIT(&dbg->dbgp_fdelist);
1782de3b87aSKai Wang 
1792de3b87aSKai Wang 	if ((dbg->dbgp_lineinfo = calloc(1, sizeof(struct _Dwarf_LineInfo))) ==
1802de3b87aSKai Wang 	    NULL) {
1812de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1822de3b87aSKai Wang 		return (DW_DLE_MEMORY);
1832de3b87aSKai Wang 	}
1842de3b87aSKai Wang 	STAILQ_INIT(&dbg->dbgp_lineinfo->li_lflist);
1852de3b87aSKai Wang 	STAILQ_INIT(&dbg->dbgp_lineinfo->li_lnlist);
1862de3b87aSKai Wang 
1872de3b87aSKai Wang 	if ((dbg->dbgp_as = calloc(1, sizeof(struct _Dwarf_ArangeSet))) ==
1882de3b87aSKai Wang 	    NULL) {
1892de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1902de3b87aSKai Wang 		return (DW_DLE_MEMORY);
1912de3b87aSKai Wang 	}
1922de3b87aSKai Wang 	STAILQ_INIT(&dbg->dbgp_as->as_arlist);
1932de3b87aSKai Wang 
1942de3b87aSKai Wang 	return (DW_DLE_NONE);
1952de3b87aSKai Wang }
1962de3b87aSKai Wang 
1972de3b87aSKai Wang int
_dwarf_init(Dwarf_Debug dbg,Dwarf_Unsigned pro_flags,Dwarf_Handler errhand,Dwarf_Ptr errarg,Dwarf_Error * error)1982de3b87aSKai Wang _dwarf_init(Dwarf_Debug dbg, Dwarf_Unsigned pro_flags, Dwarf_Handler errhand,
1992de3b87aSKai Wang     Dwarf_Ptr errarg, Dwarf_Error *error)
2002de3b87aSKai Wang {
2012de3b87aSKai Wang 	int ret;
2022de3b87aSKai Wang 
2032de3b87aSKai Wang 	ret = DW_DLE_NONE;
2042de3b87aSKai Wang 
2052de3b87aSKai Wang 	/*
2062de3b87aSKai Wang 	 * Set the error handler fields early, so that the application
2072de3b87aSKai Wang 	 * is notified of initialization errors.
2082de3b87aSKai Wang 	 */
2092de3b87aSKai Wang 	dbg->dbg_errhand = errhand;
2102de3b87aSKai Wang 	dbg->dbg_errarg = errarg;
2112de3b87aSKai Wang 
2122de3b87aSKai Wang 	STAILQ_INIT(&dbg->dbg_cu);
213cf781b2eSEd Maste 	STAILQ_INIT(&dbg->dbg_tu);
2142de3b87aSKai Wang 	STAILQ_INIT(&dbg->dbg_rllist);
2152de3b87aSKai Wang 	STAILQ_INIT(&dbg->dbg_aslist);
2162de3b87aSKai Wang 	STAILQ_INIT(&dbg->dbg_mslist);
2172de3b87aSKai Wang 
2182de3b87aSKai Wang 	if (dbg->dbg_mode == DW_DLC_READ || dbg->dbg_mode == DW_DLC_RDWR) {
2192de3b87aSKai Wang 		ret = _dwarf_consumer_init(dbg, error);
2202de3b87aSKai Wang 		if (ret != DW_DLE_NONE) {
2212de3b87aSKai Wang 			_dwarf_deinit(dbg);
2222de3b87aSKai Wang 			return (ret);
2232de3b87aSKai Wang 		}
2242de3b87aSKai Wang 	}
2252de3b87aSKai Wang 
2262de3b87aSKai Wang 	if (dbg->dbg_mode == DW_DLC_WRITE) {
2272de3b87aSKai Wang 		ret = _dwarf_producer_init(dbg, pro_flags, error);
2282de3b87aSKai Wang 		if (ret != DW_DLE_NONE) {
2292de3b87aSKai Wang 			_dwarf_deinit(dbg);
2302de3b87aSKai Wang 			return (ret);
2312de3b87aSKai Wang 		}
2322de3b87aSKai Wang 	}
2332de3b87aSKai Wang 
2342de3b87aSKai Wang 	/*
2352de3b87aSKai Wang 	 * Initialise internal string table.
2362de3b87aSKai Wang 	 */
2372de3b87aSKai Wang 	if ((ret = _dwarf_strtab_init(dbg, error)) != DW_DLE_NONE)
2382de3b87aSKai Wang 		return (ret);
2392de3b87aSKai Wang 
2402de3b87aSKai Wang 	return (DW_DLE_NONE);
2412de3b87aSKai Wang }
2422de3b87aSKai Wang 
2432de3b87aSKai Wang static void
_dwarf_producer_deinit(Dwarf_P_Debug dbg)2442de3b87aSKai Wang _dwarf_producer_deinit(Dwarf_P_Debug dbg)
2452de3b87aSKai Wang {
2462de3b87aSKai Wang 
2472de3b87aSKai Wang 	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
2482de3b87aSKai Wang 
2492de3b87aSKai Wang 	_dwarf_info_pro_cleanup(dbg);
2502de3b87aSKai Wang 	_dwarf_die_pro_cleanup(dbg);
2512de3b87aSKai Wang 	_dwarf_expr_cleanup(dbg);
2522de3b87aSKai Wang 	_dwarf_lineno_pro_cleanup(dbg);
2532de3b87aSKai Wang 	_dwarf_frame_pro_cleanup(dbg);
2542de3b87aSKai Wang 	_dwarf_arange_pro_cleanup(dbg);
2552de3b87aSKai Wang 	_dwarf_macinfo_pro_cleanup(dbg);
2562de3b87aSKai Wang 	_dwarf_strtab_cleanup(dbg);
2572de3b87aSKai Wang 	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_pubs);
2582de3b87aSKai Wang 	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_weaks);
2592de3b87aSKai Wang 	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_funcs);
2602de3b87aSKai Wang 	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_types);
2612de3b87aSKai Wang 	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_vars);
2622de3b87aSKai Wang 	_dwarf_section_cleanup(dbg);
2632de3b87aSKai Wang 	_dwarf_reloc_cleanup(dbg);
2642de3b87aSKai Wang }
2652de3b87aSKai Wang 
2662de3b87aSKai Wang static void
_dwarf_consumer_deinit(Dwarf_Debug dbg)2672de3b87aSKai Wang _dwarf_consumer_deinit(Dwarf_Debug dbg)
2682de3b87aSKai Wang {
2692de3b87aSKai Wang 
2702de3b87aSKai Wang 	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_READ);
2712de3b87aSKai Wang 
2722de3b87aSKai Wang 	_dwarf_info_cleanup(dbg);
2732de3b87aSKai Wang 	_dwarf_ranges_cleanup(dbg);
2742de3b87aSKai Wang 	_dwarf_frame_cleanup(dbg);
2752de3b87aSKai Wang 	_dwarf_arange_cleanup(dbg);
2762de3b87aSKai Wang 	_dwarf_macinfo_cleanup(dbg);
2772de3b87aSKai Wang 	_dwarf_strtab_cleanup(dbg);
2782de3b87aSKai Wang 	_dwarf_nametbl_cleanup(&dbg->dbg_globals);
2792de3b87aSKai Wang 	_dwarf_nametbl_cleanup(&dbg->dbg_pubtypes);
2802de3b87aSKai Wang 	_dwarf_nametbl_cleanup(&dbg->dbg_weaks);
2812de3b87aSKai Wang 	_dwarf_nametbl_cleanup(&dbg->dbg_funcs);
2822de3b87aSKai Wang 	_dwarf_nametbl_cleanup(&dbg->dbg_vars);
2832de3b87aSKai Wang 	_dwarf_nametbl_cleanup(&dbg->dbg_types);
2842de3b87aSKai Wang 
2852de3b87aSKai Wang 	free(dbg->dbg_section);
2862de3b87aSKai Wang }
2872de3b87aSKai Wang 
2882de3b87aSKai Wang void
_dwarf_deinit(Dwarf_Debug dbg)2892de3b87aSKai Wang _dwarf_deinit(Dwarf_Debug dbg)
2902de3b87aSKai Wang {
2912de3b87aSKai Wang 
2922de3b87aSKai Wang 	assert(dbg != NULL);
2932de3b87aSKai Wang 
2942de3b87aSKai Wang 	if (dbg->dbg_mode == DW_DLC_READ)
2952de3b87aSKai Wang 		_dwarf_consumer_deinit(dbg);
2962de3b87aSKai Wang 	else if (dbg->dbg_mode == DW_DLC_WRITE)
2972de3b87aSKai Wang 		_dwarf_producer_deinit(dbg);
2982de3b87aSKai Wang }
2992de3b87aSKai Wang 
3002de3b87aSKai Wang int
_dwarf_alloc(Dwarf_Debug * ret_dbg,int mode,Dwarf_Error * error)3012de3b87aSKai Wang _dwarf_alloc(Dwarf_Debug *ret_dbg, int mode, Dwarf_Error *error)
3022de3b87aSKai Wang {
3032de3b87aSKai Wang 	Dwarf_Debug dbg;
3042de3b87aSKai Wang 
3052de3b87aSKai Wang 	if ((dbg = calloc(sizeof(struct _Dwarf_Debug), 1)) == NULL) {
3062de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
3072de3b87aSKai Wang 		return (DW_DLE_MEMORY);
3082de3b87aSKai Wang 	}
3092de3b87aSKai Wang 
3102de3b87aSKai Wang 	dbg->dbg_mode = mode;
3112de3b87aSKai Wang 
3122de3b87aSKai Wang 	*ret_dbg = dbg;
3132de3b87aSKai Wang 
3142de3b87aSKai Wang 	return (DW_DLE_NONE);
3152de3b87aSKai Wang }
316