Home | History | Annotate | Line # | Download | only in libdwarf
libdwarf_init.c revision 1.1
      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 2948 2013-05-30 21:25:52Z 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, sizeof(Dwarf_Section))) == NULL) {
     73 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
     74 		return (DW_DLE_MEMORY);
     75 	}
     76 
     77 	for (i = 0; i < cnt; i++) {
     78 		if (m->get_section_info(obj, i, &sec, &ret) != DW_DLV_OK) {
     79 			DWARF_SET_ERROR(dbg, error, ret);
     80 			return (ret);
     81 		}
     82 
     83 		dbg->dbg_section[i].ds_addr = sec.addr;
     84 		dbg->dbg_section[i].ds_size = sec.size;
     85 		dbg->dbg_section[i].ds_name = sec.name;
     86 
     87 		if (m->load_section(obj, i, &dbg->dbg_section[i].ds_data, &ret)
     88 		    != DW_DLV_OK) {
     89 			DWARF_SET_ERROR(dbg, error, ret);
     90 			return (ret);
     91 		}
     92 	}
     93 
     94 	if (_dwarf_find_section(dbg, ".debug_abbrev") == NULL ||
     95 	    ((dbg->dbg_info_sec = _dwarf_find_section(dbg, ".debug_info")) ==
     96 	     NULL)) {
     97 		DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_INFO_NULL);
     98 		return (DW_DLE_DEBUG_INFO_NULL);
     99 	}
    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_rllist);
    214 	STAILQ_INIT(&dbg->dbg_aslist);
    215 	STAILQ_INIT(&dbg->dbg_mslist);
    216 	TAILQ_INIT(&dbg->dbg_loclist);
    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_loclist_cleanup(dbg);
    274 	_dwarf_ranges_cleanup(dbg);
    275 	_dwarf_frame_cleanup(dbg);
    276 	_dwarf_arange_cleanup(dbg);
    277 	_dwarf_macinfo_cleanup(dbg);
    278 	_dwarf_strtab_cleanup(dbg);
    279 	_dwarf_nametbl_cleanup(&dbg->dbg_globals);
    280 	_dwarf_nametbl_cleanup(&dbg->dbg_pubtypes);
    281 	_dwarf_nametbl_cleanup(&dbg->dbg_weaks);
    282 	_dwarf_nametbl_cleanup(&dbg->dbg_funcs);
    283 	_dwarf_nametbl_cleanup(&dbg->dbg_vars);
    284 	_dwarf_nametbl_cleanup(&dbg->dbg_types);
    285 
    286 	free(dbg->dbg_section);
    287 }
    288 
    289 void
    290 _dwarf_deinit(Dwarf_Debug dbg)
    291 {
    292 
    293 	assert(dbg != NULL);
    294 
    295 	if (dbg->dbg_mode == DW_DLC_READ)
    296 		_dwarf_consumer_deinit(dbg);
    297 	else if (dbg->dbg_mode == DW_DLC_WRITE)
    298 		_dwarf_producer_deinit(dbg);
    299 }
    300 
    301 int
    302 _dwarf_alloc(Dwarf_Debug *ret_dbg, int mode, Dwarf_Error *error)
    303 {
    304 	Dwarf_Debug dbg;
    305 
    306 	if ((dbg = calloc(sizeof(struct _Dwarf_Debug), 1)) == NULL) {
    307 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
    308 		return (DW_DLE_MEMORY);
    309 	}
    310 
    311 	dbg->dbg_mode = mode;
    312 
    313 	*ret_dbg = dbg;
    314 
    315 	return (DW_DLE_NONE);
    316 }
    317