Home | History | Annotate | Line # | Download | only in libdwarf
      1 /*	$NetBSD: libdwarf_init.c,v 1.5 2024/03/03 17:37:32 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.5 2024/03/03 17:37:32 christos Exp $");
     32 ELFTC_VCSID("Id: libdwarf_init.c 3136 2014-12-24 16:04:38Z kaiwang27");
     33 
     34 static int
     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 + 1, sizeof(Dwarf_Section))) ==
     76 	    NULL) {
     77 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
     78 		return (DW_DLE_MEMORY);
     79 	}
     80 
     81 	for (i = 0; i < cnt; i++) {
     82 		if (m->get_section_info(obj, i, &sec, &ret) != DW_DLV_OK) {
     83 			DWARF_SET_ERROR(dbg, error, ret);
     84 			return (ret);
     85 		}
     86 
     87 		dbg->dbg_section[i].ds_addr = sec.addr;
     88 		dbg->dbg_section[i].ds_size = sec.size;
     89 		dbg->dbg_section[i].ds_name = sec.name;
     90 
     91 		if (m->load_section(obj, i, &dbg->dbg_section[i].ds_data, &ret)
     92 		    != DW_DLV_OK) {
     93 			DWARF_SET_ERROR(dbg, error, ret);
     94 			return (ret);
     95 		}
     96 	}
     97 	dbg->dbg_section[cnt].ds_name = NULL;
     98 
     99 	dbg->dbg_info_sec = _dwarf_find_section(dbg, ".debug_info");
    100 
    101 	/* Try to find the optional DWARF4 .debug_types section. */
    102 	dbg->dbg_types_sec = _dwarf_find_next_types_section(dbg, NULL);
    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
    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
    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_tu);
    217 	STAILQ_INIT(&dbg->dbg_rllist);
    218 	STAILQ_INIT(&dbg->dbg_aslist);
    219 	STAILQ_INIT(&dbg->dbg_mslist);
    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
    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
    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_ranges_cleanup(dbg);
    277 	_dwarf_frame_cleanup(dbg);
    278 	_dwarf_arange_cleanup(dbg);
    279 	_dwarf_macinfo_cleanup(dbg);
    280 	_dwarf_strtab_cleanup(dbg);
    281 	_dwarf_nametbl_cleanup(&dbg->dbg_globals);
    282 	_dwarf_nametbl_cleanup(&dbg->dbg_pubtypes);
    283 	_dwarf_nametbl_cleanup(&dbg->dbg_weaks);
    284 	_dwarf_nametbl_cleanup(&dbg->dbg_funcs);
    285 	_dwarf_nametbl_cleanup(&dbg->dbg_vars);
    286 	_dwarf_nametbl_cleanup(&dbg->dbg_types);
    287 
    288 	free(dbg->dbg_section);
    289 }
    290 
    291 void
    292 _dwarf_deinit(Dwarf_Debug dbg)
    293 {
    294 
    295 	assert(dbg != NULL);
    296 
    297 	if (dbg->dbg_mode == DW_DLC_READ)
    298 		_dwarf_consumer_deinit(dbg);
    299 	else if (dbg->dbg_mode == DW_DLC_WRITE)
    300 		_dwarf_producer_deinit(dbg);
    301 }
    302 
    303 int
    304 _dwarf_alloc(Dwarf_Debug *ret_dbg, int mode, Dwarf_Error *error)
    305 {
    306 	Dwarf_Debug dbg;
    307 
    308 	if ((dbg = calloc(sizeof(struct _Dwarf_Debug), 1)) == NULL) {
    309 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
    310 		return (DW_DLE_MEMORY);
    311 	}
    312 
    313 	dbg->dbg_mode = mode;
    314 
    315 	*ret_dbg = dbg;
    316 
    317 	return (DW_DLE_NONE);
    318 }
    319