Home | History | Annotate | Line # | Download | only in libdwarf
      1 /*	$NetBSD: libdwarf_nametbl.c,v 1.5 2024/03/03 17:37:32 christos Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2009,2010 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_nametbl.c,v 1.5 2024/03/03 17:37:32 christos Exp $");
     32 ELFTC_VCSID("Id: libdwarf_nametbl.c 3029 2014-04-21 23:26:02Z kaiwang27");
     33 
     34 void
     35 _dwarf_nametbl_cleanup(Dwarf_NameSec *nsp)
     36 {
     37 	Dwarf_NameSec ns;
     38 	Dwarf_NameTbl nt, tnt;
     39 	Dwarf_NamePair np, tnp;
     40 
     41 	assert(nsp != NULL);
     42 	if ((ns = *nsp) == NULL)
     43 		return;
     44 
     45 	STAILQ_FOREACH_SAFE(nt, &ns->ns_ntlist, nt_next, tnt) {
     46 		STAILQ_FOREACH_SAFE(np, &nt->nt_nplist, np_next, tnp) {
     47 			STAILQ_REMOVE(&nt->nt_nplist, np, _Dwarf_NamePair,
     48 			    np_next);
     49 			free(np);
     50 		}
     51 		STAILQ_REMOVE(&ns->ns_ntlist, nt, _Dwarf_NameTbl, nt_next);
     52 		free(nt);
     53 	}
     54 	if (ns->ns_array)
     55 		free(ns->ns_array);
     56 	free(ns);
     57 	*nsp = NULL;
     58 }
     59 
     60 int
     61 _dwarf_nametbl_init(Dwarf_Debug dbg, Dwarf_NameSec *namesec, Dwarf_Section *ds,
     62     Dwarf_Error *error)
     63 {
     64 	Dwarf_CU cu;
     65 	Dwarf_NameSec ns;
     66 	Dwarf_NameTbl nt;
     67 	Dwarf_NamePair np;
     68 	uint64_t offset, dwarf_size, length, cuoff;
     69 	char *p;
     70 	int i, ret;
     71 
     72 	assert(*namesec == NULL);
     73 
     74 	if ((ns = malloc(sizeof(struct _Dwarf_NameSec))) == NULL) {
     75 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
     76 		return (DW_DLE_MEMORY);
     77 	}
     78 	STAILQ_INIT(&ns->ns_ntlist);
     79 	ns->ns_array = NULL;
     80 	ns->ns_len = 0;
     81 
     82 	offset = 0;
     83 	while (offset < ds->ds_size) {
     84 
     85 		/* Allocate a new name table. */
     86 		if ((nt = malloc(sizeof(struct _Dwarf_NameTbl))) == NULL) {
     87 			ret = DW_DLE_MEMORY;
     88 			DWARF_SET_ERROR(dbg, error, ret);
     89 			goto fail_cleanup;
     90 		}
     91 		STAILQ_INIT(&nt->nt_nplist);
     92 		STAILQ_INSERT_TAIL(&ns->ns_ntlist, nt, nt_next);
     93 
     94 		/* Read in the table header. */
     95 		length = dbg->read(ds->ds_data, &offset, 4);
     96 		if (length == 0xffffffff) {
     97 			dwarf_size = 8;
     98 			length = dbg->read(ds->ds_data, &offset, 8);
     99 		} else
    100 			dwarf_size = 4;
    101 
    102 		nt->nt_length = length;
    103 		/* FIXME: verify version */
    104 		nt->nt_version = dbg->read(ds->ds_data, &offset, 2);
    105 		nt->nt_cu_offset = dbg->read(ds->ds_data, &offset, dwarf_size);
    106 		nt->nt_cu_length = dbg->read(ds->ds_data, &offset, dwarf_size);
    107 
    108 		if (!dbg->dbg_info_loaded) {
    109 			ret = _dwarf_info_load(dbg, 1, 1, error);
    110 			if (ret != DW_DLE_NONE)
    111 				goto fail_cleanup;
    112 		}
    113 
    114 		/* Find the referenced CU. */
    115 		STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
    116 			if (cu->cu_offset == nt->nt_cu_offset)
    117 				break;
    118 		}
    119 		nt->nt_cu = cu;	/* FIXME: Check if NULL here */
    120 
    121 		/* Add name pairs. */
    122 		while (offset < ds->ds_size) {
    123 			cuoff = dbg->read(ds->ds_data, &offset, dwarf_size);
    124 			if (cuoff == 0)
    125 				break;
    126 			if ((np = malloc(sizeof(struct _Dwarf_NamePair))) ==
    127 			    NULL) {
    128 				ret = DW_DLE_MEMORY;
    129 				DWARF_SET_ERROR(dbg, error, ret);
    130 				goto fail_cleanup;
    131 			}
    132 			np->np_nt = nt;
    133 			np->np_offset = cuoff;
    134 			p = (char *) ds->ds_data;
    135 			np->np_name = &p[offset];
    136 			while (p[offset++] != '\0')
    137 				;
    138 			STAILQ_INSERT_TAIL(&nt->nt_nplist, np, np_next);
    139 			ns->ns_len++;
    140 		}
    141 	}
    142 
    143 	/* Build array of name pairs from all tables. */
    144 	if (ns->ns_len > 0) {
    145 		if ((ns->ns_array = malloc(sizeof(Dwarf_NamePair) *
    146 		    ns->ns_len)) == NULL) {
    147 			ret = DW_DLE_MEMORY;
    148 			DWARF_SET_ERROR(dbg, error, ret);
    149 			goto fail_cleanup;
    150 		}
    151 
    152 		i = 0;
    153 		STAILQ_FOREACH(nt, &ns->ns_ntlist, nt_next) {
    154 			STAILQ_FOREACH(np, &nt->nt_nplist, np_next)
    155 				ns->ns_array[i++] = np;
    156 		}
    157 		assert((Dwarf_Unsigned)i == ns->ns_len);
    158 	}
    159 
    160 	*namesec = ns;
    161 
    162 	return (DW_DLE_NONE);
    163 
    164 fail_cleanup:
    165 
    166 	_dwarf_nametbl_cleanup(&ns);
    167 
    168 	return (ret);
    169 }
    170 
    171 int
    172 _dwarf_nametbl_gen(Dwarf_P_Debug dbg, const char *name, Dwarf_NameTbl nt,
    173     Dwarf_Error *error)
    174 {
    175 	Dwarf_P_Section ds;
    176 	Dwarf_Rel_Section drs;
    177 	Dwarf_NamePair np;
    178 	uint64_t offset;
    179 	int ret;
    180 
    181 	assert(dbg != NULL && name != NULL);
    182 	if (nt == NULL || STAILQ_EMPTY(&nt->nt_nplist))
    183 		return (DW_DLE_NONE);
    184 
    185 	nt->nt_length = 0;
    186 	nt->nt_version = 2;
    187 	nt->nt_cu = STAILQ_FIRST(&dbg->dbg_cu);
    188 	assert(nt->nt_cu != NULL);
    189 	nt->nt_cu_offset = nt->nt_cu->cu_offset;
    190 	nt->nt_cu_length = nt->nt_cu->cu_length;
    191 
    192 	/* Create name lookup section. */
    193 	if ((ret = _dwarf_section_init(dbg, &ds, name, 0, error)) !=
    194 	    DW_DLE_NONE)
    195 		goto gen_fail0;
    196 
    197 	/* Create relocation section for the name lookup section. */
    198 	RCHECK(_dwarf_reloc_section_init(dbg, &drs, ds, error));
    199 
    200 	/* Write table header. */
    201 	RCHECK(WRITE_VALUE(nt->nt_length, 4));
    202 	RCHECK(WRITE_VALUE(nt->nt_version, 2));
    203 	RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc, 4,
    204 	    ds->ds_size, 0, nt->nt_cu_offset, ".debug_info", error));
    205 	RCHECK(WRITE_VALUE(nt->nt_cu_length, 4));
    206 
    207 	/* Write tuples. */
    208 	STAILQ_FOREACH(np, &nt->nt_nplist, np_next) {
    209 		assert(np->np_die != NULL);
    210 		np->np_offset = np->np_die->die_offset;
    211 		RCHECK(WRITE_VALUE(np->np_offset, 4));
    212 		RCHECK(WRITE_STRING(np->np_name));
    213 	}
    214 	RCHECK(WRITE_VALUE(0, 4));
    215 
    216 	/* Fill in the length field. */
    217 	nt->nt_length = ds->ds_size - 4;
    218 	offset = 0;
    219 	dbg->write(ds->ds_data, &offset, nt->nt_length, 4);
    220 
    221 	/* Inform application the creation of name lookup ELF section. */
    222 	RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
    223 
    224 	/* Finalize relocation section for the name lookup section. */
    225 	RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error));
    226 
    227 	return (DW_DLE_NONE);
    228 
    229 gen_fail:
    230 	_dwarf_reloc_section_free(dbg, &drs);
    231 
    232 gen_fail0:
    233 	_dwarf_section_free(dbg, &ds);
    234 
    235 	return (ret);
    236 }
    237 
    238 void
    239 _dwarf_nametbl_pro_cleanup(Dwarf_NameTbl *ntp)
    240 {
    241 	Dwarf_NameTbl nt;
    242 	Dwarf_NamePair np, tnp;
    243 
    244 	assert(ntp != NULL);
    245 	if ((nt = *ntp) == NULL)
    246 		return;
    247 
    248 	STAILQ_FOREACH_SAFE(np, &nt->nt_nplist, np_next, tnp) {
    249 		STAILQ_REMOVE(&nt->nt_nplist, np, _Dwarf_NamePair, np_next);
    250 		if (np->np_name)
    251 			free(np->np_name);
    252 		free(np);
    253 	}
    254 	free(nt);
    255 	*ntp = NULL;
    256 }
    257