Home | History | Annotate | Line # | Download | only in libdwarf
      1 /*	$NetBSD: dwarf_form.c,v 1.6 2026/05/17 21:40:48 jkoshy Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2007 John Birrell (jb (at) freebsd.org)
      5  * Copyright (c) 2009,2010,2023 Kai Wang
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  * SUCH DAMAGE.
     28  */
     29 
     30 #include "_libdwarf.h"
     31 
     32 __RCSID("$NetBSD: dwarf_form.c,v 1.6 2026/05/17 21:40:48 jkoshy Exp $");
     33 ELFTC_VCSID("Id: dwarf_form.c 4039 2024-03-15 04:07:32Z kaiwang27");
     34 
     35 int
     36 dwarf_hasform(Dwarf_Attribute at, Dwarf_Half form, Dwarf_Bool *return_hasform,
     37     Dwarf_Error *error)
     38 {
     39 	Dwarf_Debug dbg;
     40 
     41 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
     42 
     43 	if (at == NULL || return_hasform == NULL) {
     44 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
     45 		return (DW_DLV_ERROR);
     46 	}
     47 
     48 	*return_hasform = (at->at_form == form);
     49 
     50 	return (DW_DLV_OK);
     51 }
     52 
     53 int
     54 dwarf_whatform(Dwarf_Attribute at, Dwarf_Half *return_form, Dwarf_Error *error)
     55 {
     56 	Dwarf_Debug dbg;
     57 
     58 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
     59 
     60 	if (at == NULL || return_form == NULL) {
     61 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
     62 		return (DW_DLV_ERROR);
     63 	}
     64 
     65 	*return_form = at->at_form;
     66 
     67 	return (DW_DLV_OK);
     68 }
     69 
     70 int
     71 dwarf_whatform_direct(Dwarf_Attribute at, Dwarf_Half *return_form,
     72     Dwarf_Error *error)
     73 {
     74 	Dwarf_Debug dbg;
     75 
     76 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
     77 
     78 	if (at == NULL || return_form == NULL) {
     79 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
     80 		return (DW_DLV_ERROR);
     81 	}
     82 
     83 	if (at->at_indirect)
     84 		*return_form = DW_FORM_indirect;
     85 	else
     86 		*return_form = (Dwarf_Half) at->at_form;
     87 
     88 	return (DW_DLV_OK);
     89 }
     90 
     91 int
     92 dwarf_whatattr(Dwarf_Attribute at, Dwarf_Half *return_attr, Dwarf_Error *error)
     93 {
     94 	Dwarf_Debug dbg;
     95 
     96 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
     97 
     98 	if (at == NULL || return_attr == NULL) {
     99 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
    100 		return (DW_DLV_ERROR);
    101 	}
    102 
    103 	*return_attr = (Dwarf_Half) at->at_attrib;
    104 
    105 	return (DW_DLV_OK);
    106 }
    107 
    108 int
    109 dwarf_formref(Dwarf_Attribute at, Dwarf_Off *return_offset, Dwarf_Error *error)
    110 {
    111 	int ret;
    112 	Dwarf_Debug dbg;
    113 
    114 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
    115 
    116 	if (at == NULL || return_offset == NULL) {
    117 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
    118 		return (DW_DLV_ERROR);
    119 	}
    120 
    121 	switch (at->at_form) {
    122 	case DW_FORM_ref1:
    123 	case DW_FORM_ref2:
    124 	case DW_FORM_ref4:
    125 	case DW_FORM_ref8:
    126 	case DW_FORM_ref_udata:
    127 		*return_offset = (Dwarf_Off) at->u[0].u64;
    128 		ret = DW_DLV_OK;
    129 		break;
    130 	default:
    131 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
    132 		ret = DW_DLV_ERROR;
    133 	}
    134 
    135 	return (ret);
    136 }
    137 
    138 int
    139 dwarf_global_formref(Dwarf_Attribute at, Dwarf_Off *return_offset,
    140     Dwarf_Error *error)
    141 {
    142 	int ret;
    143 	Dwarf_Debug dbg;
    144 
    145 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
    146 
    147 	if (at == NULL || return_offset == NULL) {
    148 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
    149 		return (DW_DLV_ERROR);
    150 	}
    151 
    152 	switch (at->at_form) {
    153 	case DW_FORM_ref_addr:
    154 	case DW_FORM_sec_offset:
    155 		*return_offset = (Dwarf_Off) at->u[0].u64;
    156 		ret = DW_DLV_OK;
    157 		break;
    158 	case DW_FORM_ref1:
    159 	case DW_FORM_ref2:
    160 	case DW_FORM_ref4:
    161 	case DW_FORM_ref8:
    162 	case DW_FORM_ref_udata:
    163 		*return_offset = (Dwarf_Off) at->u[0].u64 +
    164 			at->at_die->die_cu->cu_offset;
    165 		ret = DW_DLV_OK;
    166 		break;
    167 	default:
    168 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
    169 		ret = DW_DLV_ERROR;
    170 	}
    171 
    172 	return (ret);
    173 }
    174 
    175 int
    176 dwarf_formaddr(Dwarf_Attribute at, Dwarf_Addr *return_addr, Dwarf_Error *error)
    177 {
    178 	int ret;
    179 	Dwarf_Debug dbg;
    180 
    181 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
    182 
    183 	if (at == NULL || return_addr == NULL) {
    184 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
    185 		return (DW_DLV_ERROR);
    186 	}
    187 
    188 	if (at->at_form == DW_FORM_addr) {
    189 		*return_addr = at->u[0].u64;
    190 		ret = DW_DLV_OK;
    191 	} else {
    192 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
    193 		ret = DW_DLV_ERROR;
    194 	}
    195 
    196 	return (ret);
    197 }
    198 
    199 int
    200 dwarf_formflag(Dwarf_Attribute at, Dwarf_Bool *return_bool, Dwarf_Error *error)
    201 {
    202 	int ret;
    203 	Dwarf_Debug dbg;
    204 
    205 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
    206 
    207 	if (at == NULL || return_bool == NULL) {
    208 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
    209 		return (DW_DLV_ERROR);
    210 	}
    211 
    212 	if (at->at_form == DW_FORM_flag ||
    213 	    at->at_form == DW_FORM_flag_present) {
    214 		*return_bool = (Dwarf_Bool) (!!at->u[0].u64);
    215 		ret = DW_DLV_OK;
    216 	} else {
    217 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
    218 		ret = DW_DLV_ERROR;
    219 	}
    220 
    221 	return (ret);
    222 }
    223 
    224 int
    225 dwarf_formudata(Dwarf_Attribute at, Dwarf_Unsigned *return_uvalue,
    226     Dwarf_Error *error)
    227 {
    228 	int ret;
    229 	Dwarf_Debug dbg;
    230 
    231 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
    232 
    233 	if (at == NULL || return_uvalue == NULL) {
    234 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
    235 		return (DW_DLV_ERROR);
    236 	}
    237 
    238 	switch (at->at_form) {
    239 	case DW_FORM_data1:
    240 	case DW_FORM_data2:
    241 	case DW_FORM_data4:
    242 	case DW_FORM_data8:
    243 	case DW_FORM_udata:
    244 		*return_uvalue = at->u[0].u64;
    245 		ret = DW_DLV_OK;
    246 		break;
    247 	default:
    248 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
    249 		ret = DW_DLV_ERROR;
    250 	}
    251 
    252 	return (ret);
    253 }
    254 
    255 int
    256 dwarf_formsdata(Dwarf_Attribute at, Dwarf_Signed *return_svalue,
    257     Dwarf_Error *error)
    258 {
    259 	int ret;
    260 	Dwarf_Debug dbg;
    261 
    262 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
    263 
    264 	if (at == NULL || return_svalue == NULL) {
    265 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
    266 		return (DW_DLV_ERROR);
    267 	}
    268 
    269 	switch (at->at_form) {
    270 	case DW_FORM_data1:
    271 		*return_svalue = (int8_t) at->u[0].s64;
    272 		ret = DW_DLV_OK;
    273 		break;
    274 	case DW_FORM_data2:
    275 		*return_svalue = (int16_t) at->u[0].s64;
    276 		ret = DW_DLV_OK;
    277 		break;
    278 	case DW_FORM_data4:
    279 		*return_svalue = (int32_t) at->u[0].s64;
    280 		ret = DW_DLV_OK;
    281 		break;
    282 	case DW_FORM_data8:
    283 	case DW_FORM_sdata:
    284 		*return_svalue = at->u[0].s64;
    285 		ret = DW_DLV_OK;
    286 		break;
    287 	default:
    288 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
    289 		ret = DW_DLV_ERROR;
    290 	}
    291 
    292 	return (ret);
    293 }
    294 
    295 int
    296 dwarf_formblock(Dwarf_Attribute at, Dwarf_Block **return_block,
    297     Dwarf_Error *error)
    298 {
    299 	int ret;
    300 	Dwarf_Debug dbg;
    301 
    302 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
    303 
    304 	if (at == NULL || return_block == NULL) {
    305 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
    306 		return (DW_DLV_ERROR);
    307 	}
    308 
    309 	switch (at->at_form) {
    310 	case DW_FORM_block:
    311 	case DW_FORM_block1:
    312 	case DW_FORM_block2:
    313 	case DW_FORM_block4:
    314 		*return_block = &at->at_block;
    315 		ret = DW_DLV_OK;
    316 		break;
    317 	default:
    318 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
    319 		ret = DW_DLV_ERROR;
    320 	}
    321 
    322 	return (ret);
    323 }
    324 
    325 int
    326 dwarf_formsig8(Dwarf_Attribute at, Dwarf_Sig8 *return_sig8, Dwarf_Error *error)
    327 {
    328 	Dwarf_Debug dbg;
    329 
    330 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
    331 
    332 	if (at == NULL || return_sig8 == NULL) {
    333 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
    334 		return (DW_DLV_ERROR);
    335 	}
    336 
    337 	if (at->at_form != DW_FORM_ref_sig8) {
    338 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
    339 		return (DW_DLV_ERROR);
    340 	}
    341 
    342 	assert(at->u[0].u64 == 8);
    343 	memcpy(return_sig8->signature, at->u[1].u8p, at->u[0].u64);
    344 
    345 	return (DW_DLV_OK);
    346 }
    347 
    348 int
    349 dwarf_formexprloc(Dwarf_Attribute at, Dwarf_Unsigned *return_exprlen,
    350     Dwarf_Ptr *return_expr, Dwarf_Error *error)
    351 {
    352 
    353 	Dwarf_Debug dbg;
    354 
    355 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
    356 
    357 	if (at == NULL || return_exprlen == NULL || return_expr == NULL) {
    358 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
    359 		return (DW_DLV_ERROR);
    360 	}
    361 
    362 	if (at->at_form != DW_FORM_exprloc) {
    363 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
    364 		return (DW_DLV_ERROR);
    365 	}
    366 
    367 	*return_exprlen = at->u[0].u64;
    368 	*return_expr = (void *) at->u[1].u8p;
    369 
    370 	return (DW_DLV_OK);
    371 }
    372 
    373 int
    374 dwarf_formstring(Dwarf_Attribute at, char **return_string,
    375     Dwarf_Error *error)
    376 {
    377 	int ret;
    378 	Dwarf_Debug dbg;
    379 	Dwarf_CU cu;
    380 
    381 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
    382 
    383 	if (at == NULL || return_string == NULL) {
    384 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
    385 		return (DW_DLV_ERROR);
    386 	}
    387 
    388 	cu = at->at_die->die_cu;
    389 	assert(cu != NULL);
    390 
    391 	switch (at->at_form) {
    392 	case DW_FORM_string:
    393 		*return_string = (char *) at->u[0].s;
    394 		ret = DW_DLV_OK;
    395 		break;
    396 	case DW_FORM_strp:
    397 	case DW_FORM_line_strp:
    398 		*return_string = (char *) at->u[1].s;
    399 		ret = DW_DLV_OK;
    400 		break;
    401 	case DW_FORM_strx:
    402 	case DW_FORM_strx1:
    403 	case DW_FORM_strx2:
    404 	case DW_FORM_strx3:
    405 	case DW_FORM_strx4:
    406 		if (_dwarf_read_indexed_str(dbg, cu, at->u[0].u64,
    407 		    return_string, error) != DW_DLE_NONE)
    408 			ret = DW_DLV_ERROR;
    409 		else
    410 			ret = DW_DLV_OK;
    411 		break;
    412 	default:
    413 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
    414 		ret = DW_DLV_ERROR;
    415 	}
    416 
    417 	return (ret);
    418 }
    419 
    420 enum Dwarf_Form_Class
    421 dwarf_get_form_class(Dwarf_Half dwversion, Dwarf_Half attr,
    422     Dwarf_Half offset_size, Dwarf_Half form)
    423 {
    424 
    425 	switch (form) {
    426 	case DW_FORM_addr:
    427 		return (DW_FORM_CLASS_ADDRESS);
    428 	case DW_FORM_block:
    429 	case DW_FORM_block1:
    430 	case DW_FORM_block2:
    431 	case DW_FORM_block4:
    432 		return (DW_FORM_CLASS_BLOCK);
    433 	case DW_FORM_string:
    434 	case DW_FORM_strp:
    435 	case DW_FORM_line_strp:
    436 	case DW_FORM_strp_sup:
    437 	case DW_FORM_strx:
    438 	case DW_FORM_strx1:
    439 	case DW_FORM_strx2:
    440 	case DW_FORM_strx3:
    441 	case DW_FORM_strx4:
    442 		return (DW_FORM_CLASS_STRING);
    443 	case DW_FORM_flag:
    444 	case DW_FORM_flag_present:
    445 		return (DW_FORM_CLASS_FLAG);
    446 	case DW_FORM_ref_addr:
    447 	case DW_FORM_ref_sig8:
    448 	case DW_FORM_ref_udata:
    449 	case DW_FORM_ref1:
    450 	case DW_FORM_ref2:
    451 	case DW_FORM_ref4:
    452 	case DW_FORM_ref8:
    453 		return (DW_FORM_CLASS_REFERENCE);
    454 	case DW_FORM_exprloc:
    455 		return (DW_FORM_CLASS_EXPRLOC);
    456 	case DW_FORM_data1:
    457 	case DW_FORM_data2:
    458 	case DW_FORM_sdata:
    459 	case DW_FORM_udata:
    460 		return (DW_FORM_CLASS_CONSTANT);
    461 	case DW_FORM_data4:
    462 	case DW_FORM_data8:
    463 		if (dwversion > 3)
    464 			return (DW_FORM_CLASS_CONSTANT);
    465 		if (form == DW_FORM_data4 && offset_size != 4)
    466 			return (DW_FORM_CLASS_CONSTANT);
    467 		if (form == DW_FORM_data8 && offset_size != 8)
    468 			return (DW_FORM_CLASS_CONSTANT);
    469 		/* FALLTHROUGH */
    470 	case DW_FORM_sec_offset:
    471 		/*
    472 		 * DW_FORM_data4 and DW_FORM_data8 can be used as
    473 		 * offset/pointer before DWARF4. Newly added
    474 		 * DWARF4 form DW_FORM_sec_offset intents to replace
    475 		 * DW_FORM_data{4,8} for this purpose. Anyway, to
    476 		 * determine the actual class for these forms, we need
    477 		 * to also look at the attribute number.
    478 		 */
    479 		switch (attr) {
    480 		case DW_AT_location:
    481 		case DW_AT_string_length:
    482 		case DW_AT_return_addr:
    483 		case DW_AT_data_member_location:
    484 		case DW_AT_frame_base:
    485 		case DW_AT_segment:
    486 		case DW_AT_static_link:
    487 		case DW_AT_use_location:
    488 		case DW_AT_vtable_elem_location:
    489 			return (DW_FORM_CLASS_LOCLISTPTR);
    490 		case DW_AT_stmt_list:
    491 			return (DW_FORM_CLASS_LINEPTR);
    492 		case DW_AT_start_scope:
    493 		case DW_AT_ranges:
    494 			return (DW_FORM_CLASS_RANGELISTPTR);
    495 		case DW_AT_macro_info:
    496 			return (DW_FORM_CLASS_MACPTR);
    497 		default:
    498 			if (form == DW_FORM_data4 || form == DW_FORM_data8)
    499 				return (DW_FORM_CLASS_CONSTANT);
    500 			else
    501 				return (DW_FORM_CLASS_UNKNOWN);
    502 		}
    503 	default:
    504 		return (DW_FORM_CLASS_UNKNOWN);
    505 	}
    506 }
    507