Home | History | Annotate | Line # | Download | only in libdwarf
libdwarf_macinfo.c revision 1.1.1.2
      1 /*	$NetBSD: libdwarf_macinfo.c,v 1.1.1.2 2016/02/20 02:42:00 christos Exp $	*/
      2 /*-
      3  * Copyright (c) 2009-2011 Kai Wang
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25  * SUCH DAMAGE.
     26  */
     27 
     28 #include "_libdwarf.h"
     29 
     30 __RCSID("$NetBSD: libdwarf_macinfo.c,v 1.1.1.2 2016/02/20 02:42:00 christos Exp $");
     31 ELFTC_VCSID("Id: libdwarf_macinfo.c 2974 2013-12-23 06:46:22Z kaiwang27 ");
     32 
     33 #define	_FILEINDEX_STACK_SIZE	16384
     34 
     35 static int
     36 _dwarf_macinfo_parse(Dwarf_Debug dbg, Dwarf_Section *ds, uint64_t *off,
     37     Dwarf_Macro_Details *dmd, Dwarf_Unsigned *cnt, Dwarf_Error *error)
     38 {
     39 	Dwarf_Unsigned lineno;
     40 	Dwarf_Signed fileindex[_FILEINDEX_STACK_SIZE];
     41 	char *p;
     42 	int i, type, sp;
     43 
     44 	i = 0;
     45 	sp = 0;
     46 	fileindex[sp] = -1;
     47 	while (*off < ds->ds_size) {
     48 
     49 		if (dmd != NULL)
     50 			dmd[i].dmd_offset = *off;
     51 
     52 		type = dbg->read(ds->ds_data, off, 1);
     53 
     54 		if (dmd != NULL) {
     55 			dmd[i].dmd_type = type;
     56 			dmd[i].dmd_fileindex = fileindex[sp];
     57 		}
     58 
     59 		switch (type) {
     60 		case 0:
     61 			break;
     62 		case DW_MACINFO_define:
     63 		case DW_MACINFO_undef:
     64 		case DW_MACINFO_vendor_ext:
     65 			lineno = _dwarf_read_uleb128(ds->ds_data, off);
     66 			p = (char *) ds->ds_data;
     67 			if (dmd != NULL) {
     68 				dmd[i].dmd_lineno = lineno;
     69 				dmd[i].dmd_macro = p + *off;
     70 
     71 			}
     72 			while (p[(*off)++] != '\0')
     73 				;
     74 			break;
     75 		case DW_MACINFO_start_file:
     76 			lineno = _dwarf_read_uleb128(ds->ds_data, off);
     77 			if (sp >= _FILEINDEX_STACK_SIZE - 1) {
     78 				assert(0);
     79 			}
     80 			fileindex[++sp] = _dwarf_read_uleb128(ds->ds_data, off);
     81 			if (dmd != NULL) {
     82 				dmd[i].dmd_lineno = lineno;
     83 				dmd[i].dmd_fileindex = fileindex[sp];
     84 			}
     85 			break;
     86 		case DW_MACINFO_end_file:
     87 			if (sp > 0) {
     88 				sp--;
     89 				break;
     90 			}
     91 			/* FALLTHROUGH */
     92 		default:
     93 			DWARF_SET_ERROR(dbg, error,
     94 			    DW_DLE_DEBUG_MACRO_INCONSISTENT);
     95 			return (DW_DLE_DEBUG_MACRO_INCONSISTENT);
     96 		}
     97 
     98 		i++;
     99 
    100 		if (type == 0)
    101 			break;
    102 	}
    103 
    104 	if (cnt != NULL)
    105 		*cnt = i;
    106 
    107 	return (DW_DLE_NONE);
    108 }
    109 
    110 void
    111 _dwarf_macinfo_cleanup(Dwarf_Debug dbg)
    112 {
    113 	Dwarf_MacroSet ms, tms;
    114 
    115 	if (STAILQ_EMPTY(&dbg->dbg_mslist))
    116 		return;
    117 
    118 	STAILQ_FOREACH_SAFE(ms, &dbg->dbg_mslist, ms_next, tms) {
    119 		STAILQ_REMOVE(&dbg->dbg_mslist, ms, _Dwarf_MacroSet, ms_next);
    120 		if (ms->ms_mdlist)
    121 			free(ms->ms_mdlist);
    122 		free(ms);
    123 	}
    124 }
    125 
    126 int
    127 _dwarf_macinfo_init(Dwarf_Debug dbg, Dwarf_Error *error)
    128 {
    129 	Dwarf_MacroSet ms;
    130 	Dwarf_Unsigned cnt;
    131 	Dwarf_Section *ds;
    132 	uint64_t offset, entry_off;
    133 	int ret;
    134 
    135 	if ((ds = _dwarf_find_section(dbg, ".debug_macinfo")) == NULL)
    136 		return (DW_DLE_NONE);
    137 
    138 	offset = 0;
    139 	while (offset < ds->ds_size) {
    140 
    141 		entry_off = offset;
    142 
    143 		ret = _dwarf_macinfo_parse(dbg, ds, &offset, NULL, &cnt, error);
    144 		if (ret != DW_DLE_NONE)
    145 			return (ret);
    146 
    147 		if (cnt == 0)
    148 			break;
    149 
    150 		if ((ms = calloc(1, sizeof(struct _Dwarf_MacroSet))) == NULL) {
    151 			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
    152 			ret = DW_DLE_MEMORY;
    153 			goto fail_cleanup;
    154 		}
    155 		STAILQ_INSERT_TAIL(&dbg->dbg_mslist, ms, ms_next);
    156 
    157 		if ((ms->ms_mdlist = calloc(cnt, sizeof(Dwarf_Macro_Details)))
    158 		    == NULL) {
    159 			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
    160 			ret = DW_DLE_MEMORY;
    161 			goto fail_cleanup;
    162 		}
    163 
    164 		ms->ms_cnt = cnt;
    165 
    166 		offset = entry_off;
    167 
    168 		ret = _dwarf_macinfo_parse(dbg, ds, &offset, ms->ms_mdlist,
    169 		    NULL, error);
    170 
    171 		if (ret != DW_DLE_NONE) {
    172 			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
    173 			ret = DW_DLE_MEMORY;
    174 			goto fail_cleanup;
    175 		}
    176 	}
    177 
    178 	return (DW_DLE_NONE);
    179 
    180 fail_cleanup:
    181 
    182 	_dwarf_macinfo_cleanup(dbg);
    183 
    184 	return (ret);
    185 }
    186 
    187 int
    188 _dwarf_macinfo_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
    189 {
    190 	Dwarf_P_Section ds;
    191 	Dwarf_Macro_Details *md;
    192 	int i, ret;
    193 
    194 	if (dbg->dbgp_mdcnt == 0)
    195 		return (DW_DLE_NONE);
    196 
    197 	/* Create .debug_frame section. */
    198 	RCHECK(_dwarf_section_init(dbg, &ds, ".debug_macinfo", 0, error));
    199 
    200 	/* Write the list of Dwarf_Macro_Details. */
    201 	for (i = 0; (Dwarf_Unsigned) i < dbg->dbgp_mdcnt; i++) {
    202 		md = &dbg->dbgp_mdlist[i];
    203 		md->dmd_offset = ds->ds_size;
    204 		RCHECK(WRITE_VALUE(md->dmd_type, 1));
    205 		switch (md->dmd_type) {
    206 		case DW_MACINFO_define:
    207 		case DW_MACINFO_undef:
    208 		case DW_MACINFO_vendor_ext:
    209 			RCHECK(WRITE_ULEB128(md->dmd_lineno));
    210 			assert(md->dmd_macro != NULL);
    211 			RCHECK(WRITE_STRING(md->dmd_macro));
    212 			break;
    213 		case DW_MACINFO_start_file:
    214 			RCHECK(WRITE_ULEB128(md->dmd_lineno));
    215 			RCHECK(WRITE_ULEB128(md->dmd_fileindex));
    216 			break;
    217 		case DW_MACINFO_end_file:
    218 			break;
    219 		default:
    220 			assert(0);
    221 			break;
    222 		}
    223 	}
    224 	RCHECK(WRITE_VALUE(0, 1));
    225 
    226 	/* Inform application the creation of .debug_macinfo ELF section. */
    227 	RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
    228 
    229 	return (DW_DLE_NONE);
    230 
    231 gen_fail:
    232 	_dwarf_section_free(dbg, &ds);
    233 
    234 	return (ret);
    235 }
    236 
    237 void
    238 _dwarf_macinfo_pro_cleanup(Dwarf_P_Debug dbg)
    239 {
    240 	Dwarf_Macro_Details *md;
    241 	int i;
    242 
    243 	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
    244 	if (dbg->dbgp_mdlist == NULL)
    245 		return;
    246 
    247 	assert(dbg->dbgp_mdcnt > 0);
    248 	for (i = 0; (Dwarf_Unsigned) i < dbg->dbgp_mdcnt; i++) {
    249 		md = &dbg->dbgp_mdlist[i];
    250 		if (md->dmd_macro)
    251 			free(md->dmd_macro);
    252 	}
    253 	free(dbg->dbgp_mdlist);
    254 	dbg->dbgp_mdlist = NULL;
    255 	dbg->dbgp_mdcnt = 0;
    256 }
    257