1 /*- 2 * Copyright (c) 2007 John Birrell (jb@freebsd.org) 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 ELFTC_VCSID("$Id: libdwarf_attr.c 3748 2019-06-28 01:11:13Z emaste $"); 31 32 int 33 _dwarf_attr_alloc(Dwarf_Die die, Dwarf_Attribute *atp, Dwarf_Error *error) 34 { 35 Dwarf_Attribute at; 36 37 assert(die != NULL); 38 assert(atp != NULL); 39 40 if ((at = calloc(1, sizeof(struct _Dwarf_Attribute))) == NULL) { 41 DWARF_SET_ERROR(die->die_dbg, error, DW_DLE_MEMORY); 42 return (DW_DLE_MEMORY); 43 } 44 45 *atp = at; 46 47 return (DW_DLE_NONE); 48 } 49 50 static int 51 _dwarf_attr_add(Dwarf_Die die, Dwarf_Attribute atref, Dwarf_Attribute *atp, 52 Dwarf_Error *error) 53 { 54 Dwarf_Attribute at; 55 int ret; 56 57 if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE) 58 return (ret); 59 60 memcpy(at, atref, sizeof(struct _Dwarf_Attribute)); 61 62 STAILQ_INSERT_TAIL(&die->die_attr, at, at_next); 63 64 /* Save a pointer to the attribute name if this is one. */ 65 if (at->at_attrib == DW_AT_name) { 66 switch (at->at_form) { 67 case DW_FORM_strp: 68 die->die_name = at->u[1].s; 69 break; 70 case DW_FORM_string: 71 die->die_name = at->u[0].s; 72 break; 73 default: 74 break; 75 } 76 } 77 78 if (atp != NULL) 79 *atp = at; 80 81 return (DW_DLE_NONE); 82 } 83 84 Dwarf_Attribute 85 _dwarf_attr_find(Dwarf_Die die, Dwarf_Half attr) 86 { 87 Dwarf_Attribute at; 88 89 STAILQ_FOREACH(at, &die->die_attr, at_next) { 90 if (at->at_attrib == attr) 91 break; 92 } 93 94 return (at); 95 } 96 97 int 98 _dwarf_attr_init(Dwarf_Debug dbg, Dwarf_Section *ds, uint64_t *offsetp, 99 int dwarf_size, Dwarf_CU cu, Dwarf_Die die, Dwarf_AttrDef ad, 100 uint64_t form, int indirect, Dwarf_Error *error) 101 { 102 struct _Dwarf_Attribute atref; 103 int ret; 104 105 ret = DW_DLE_NONE; 106 memset(&atref, 0, sizeof(atref)); 107 atref.at_die = die; 108 atref.at_offset = *offsetp; 109 atref.at_attrib = ad->ad_attrib; 110 atref.at_form = indirect ? form : ad->ad_form; 111 atref.at_indirect = indirect; 112 atref.at_ld = NULL; 113 114 switch (form) { 115 case DW_FORM_addr: 116 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 117 cu->cu_pointer_size); 118 break; 119 case DW_FORM_block: 120 case DW_FORM_exprloc: 121 atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp); 122 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp, 123 atref.u[0].u64); 124 break; 125 case DW_FORM_block1: 126 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1); 127 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp, 128 atref.u[0].u64); 129 break; 130 case DW_FORM_block2: 131 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2); 132 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp, 133 atref.u[0].u64); 134 break; 135 case DW_FORM_block4: 136 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4); 137 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp, 138 atref.u[0].u64); 139 break; 140 case DW_FORM_data1: 141 case DW_FORM_flag: 142 case DW_FORM_ref1: 143 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1); 144 break; 145 case DW_FORM_data2: 146 case DW_FORM_ref2: 147 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2); 148 break; 149 case DW_FORM_data4: 150 case DW_FORM_ref4: 151 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4); 152 break; 153 case DW_FORM_data8: 154 case DW_FORM_ref8: 155 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 8); 156 break; 157 case DW_FORM_indirect: 158 form = _dwarf_read_uleb128(ds->ds_data, offsetp); 159 return (_dwarf_attr_init(dbg, ds, offsetp, dwarf_size, cu, die, 160 ad, form, 1, error)); 161 case DW_FORM_ref_addr: 162 if (cu->cu_version == 2) 163 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 164 cu->cu_pointer_size); 165 else 166 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 167 dwarf_size); 168 break; 169 case DW_FORM_ref_udata: 170 case DW_FORM_udata: 171 atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp); 172 break; 173 case DW_FORM_sdata: 174 atref.u[0].s64 = _dwarf_read_sleb128(ds->ds_data, offsetp); 175 break; 176 case DW_FORM_sec_offset: 177 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size); 178 break; 179 case DW_FORM_string: 180 atref.u[0].s = _dwarf_read_string(ds->ds_data, ds->ds_size, 181 offsetp); 182 break; 183 case DW_FORM_strp: 184 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size); 185 atref.u[1].s = _dwarf_strtab_get_table(dbg) + atref.u[0].u64; 186 break; 187 case DW_FORM_ref_sig8: 188 atref.u[0].u64 = 8; 189 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp, 190 atref.u[0].u64); 191 break; 192 case DW_FORM_flag_present: 193 /* This form has no value encoded in the DIE. */ 194 atref.u[0].u64 = 1; 195 break; 196 default: 197 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD); 198 ret = DW_DLE_ATTR_FORM_BAD; 199 break; 200 } 201 202 if (ret == DW_DLE_NONE) { 203 if (form == DW_FORM_block || form == DW_FORM_block1 || 204 form == DW_FORM_block2 || form == DW_FORM_block4) { 205 atref.at_block.bl_len = atref.u[0].u64; 206 atref.at_block.bl_data = atref.u[1].u8p; 207 } 208 ret = _dwarf_attr_add(die, &atref, NULL, error); 209 } 210 211 return (ret); 212 } 213 214 static int 215 _dwarf_attr_write(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs, 216 Dwarf_CU cu, Dwarf_Attribute at, int pass2, Dwarf_Error *error) 217 { 218 struct _Dwarf_P_Expr_Entry *ee; 219 uint64_t value, offset, bs; 220 int ret; 221 222 assert(dbg != NULL && ds != NULL && cu != NULL && at != NULL); 223 224 /* Fill in reference to other DIE in the second pass. */ 225 if (pass2) { 226 if (at->at_form != DW_FORM_ref4 && at->at_form != DW_FORM_ref8) 227 return (DW_DLE_NONE); 228 if (at->at_refdie == NULL || at->at_offset == 0) 229 return (DW_DLE_NONE); 230 offset = at->at_offset; 231 dbg->write(ds->ds_data, &offset, at->at_refdie->die_offset, 232 at->at_form == DW_FORM_ref4 ? 4 : 8); 233 return (DW_DLE_NONE); 234 } 235 236 switch (at->at_form) { 237 case DW_FORM_addr: 238 if (at->at_relsym) 239 ret = _dwarf_reloc_entry_add(dbg, drs, ds, 240 dwarf_drt_data_reloc, cu->cu_pointer_size, 241 ds->ds_size, at->at_relsym, at->u[0].u64, NULL, 242 error); 243 else 244 ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size); 245 break; 246 case DW_FORM_block: 247 case DW_FORM_block1: 248 case DW_FORM_block2: 249 case DW_FORM_block4: 250 /* Write block size. */ 251 if (at->at_form == DW_FORM_block) { 252 ret = _dwarf_write_uleb128_alloc(&ds->ds_data, 253 &ds->ds_cap, &ds->ds_size, at->u[0].u64, error); 254 if (ret != DW_DLE_NONE) 255 break; 256 } else { 257 if (at->at_form == DW_FORM_block1) 258 bs = 1; 259 else if (at->at_form == DW_FORM_block2) 260 bs = 2; 261 else 262 bs = 4; 263 ret = WRITE_VALUE(at->u[0].u64, bs); 264 if (ret != DW_DLE_NONE) 265 break; 266 } 267 268 /* Keep block data offset for later use. */ 269 offset = ds->ds_size; 270 271 /* Write block data. */ 272 ret = WRITE_BLOCK(at->u[1].u8p, at->u[0].u64); 273 if (ret != DW_DLE_NONE) 274 break; 275 if (at->at_expr == NULL) 276 break; 277 278 /* Generate relocation entry for DW_OP_addr expressions. */ 279 STAILQ_FOREACH(ee, &at->at_expr->pe_eelist, ee_next) { 280 if (ee->ee_loc.lr_atom != DW_OP_addr || ee->ee_sym == 0) 281 continue; 282 ret = _dwarf_reloc_entry_add(dbg, drs, ds, 283 dwarf_drt_data_reloc, dbg->dbg_pointer_size, 284 offset + ee->ee_loc.lr_offset + 1, ee->ee_sym, 285 ee->ee_loc.lr_number, NULL, error); 286 if (ret != DW_DLE_NONE) 287 break; 288 } 289 break; 290 case DW_FORM_data1: 291 case DW_FORM_flag: 292 case DW_FORM_ref1: 293 ret = WRITE_VALUE(at->u[0].u64, 1); 294 break; 295 case DW_FORM_data2: 296 case DW_FORM_ref2: 297 ret = WRITE_VALUE(at->u[0].u64, 2); 298 break; 299 case DW_FORM_data4: 300 if (at->at_relsym || at->at_relsec != NULL) 301 ret = _dwarf_reloc_entry_add(dbg, drs, ds, 302 dwarf_drt_data_reloc, 4, ds->ds_size, at->at_relsym, 303 at->u[0].u64, at->at_relsec, error); 304 else 305 ret = WRITE_VALUE(at->u[0].u64, 4); 306 break; 307 case DW_FORM_data8: 308 if (at->at_relsym || at->at_relsec != NULL) 309 ret = _dwarf_reloc_entry_add(dbg, drs, ds, 310 dwarf_drt_data_reloc, 8, ds->ds_size, at->at_relsym, 311 at->u[0].u64, at->at_relsec, error); 312 else 313 ret = WRITE_VALUE(at->u[0].u64, 8); 314 break; 315 case DW_FORM_ref4: 316 case DW_FORM_ref8: 317 /* 318 * The value of ref4 and ref8 could be a reference to another 319 * DIE within the CU. And if we don't know the ref DIE's 320 * offset at the moement, then we remember at_offset and fill 321 * it in the second pass. 322 */ 323 if (at->at_refdie) { 324 value = at->at_refdie->die_offset; 325 if (value == 0) { 326 cu->cu_pass2 = 1; 327 at->at_offset = ds->ds_size; 328 } 329 } else 330 value = at->u[0].u64; 331 ret = WRITE_VALUE(value, at->at_form == DW_FORM_ref4 ? 4 : 8); 332 break; 333 case DW_FORM_indirect: 334 /* TODO. */ 335 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD); 336 ret = DW_DLE_ATTR_FORM_BAD; 337 break; 338 case DW_FORM_ref_addr: 339 /* DWARF2 format. */ 340 if (at->at_relsym) 341 ret = _dwarf_reloc_entry_add(dbg, drs, ds, 342 dwarf_drt_data_reloc, cu->cu_pointer_size, 343 ds->ds_size, at->at_relsym, at->u[0].u64, NULL, 344 error); 345 else 346 ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size); 347 break; 348 case DW_FORM_ref_udata: 349 case DW_FORM_udata: 350 ret = WRITE_ULEB128(at->u[0].u64); 351 break; 352 case DW_FORM_sdata: 353 ret = WRITE_SLEB128(at->u[0].s64); 354 break; 355 case DW_FORM_string: 356 assert(at->u[0].s != NULL); 357 ret = WRITE_STRING(at->u[0].s); 358 break; 359 case DW_FORM_strp: 360 ret = _dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc, 361 4, ds->ds_size, 0, at->u[0].u64, ".debug_str", error); 362 break; 363 default: 364 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD); 365 ret = DW_DLE_ATTR_FORM_BAD; 366 break; 367 } 368 369 return (ret); 370 } 371 372 int 373 _dwarf_add_AT_dataref(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr, 374 Dwarf_Unsigned pc_value, Dwarf_Unsigned sym_index, const char *secname, 375 Dwarf_P_Attribute *atp, Dwarf_Error *error) 376 { 377 Dwarf_Attribute at; 378 int ret; 379 380 assert(dbg != NULL && die != NULL); 381 382 if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE) 383 return (ret); 384 385 at->at_die = die; 386 at->at_attrib = attr; 387 if (dbg->dbg_pointer_size == 4) 388 at->at_form = DW_FORM_data4; 389 else 390 at->at_form = DW_FORM_data8; 391 at->at_relsym = sym_index; 392 at->at_relsec = secname; 393 at->u[0].u64 = pc_value; 394 395 STAILQ_INSERT_TAIL(&die->die_attr, at, at_next); 396 397 if (atp) 398 *atp = at; 399 400 return (DW_DLE_NONE); 401 } 402 403 int 404 _dwarf_add_string_attr(Dwarf_P_Die die, Dwarf_P_Attribute *atp, Dwarf_Half attr, 405 char *string, Dwarf_Error *error) 406 { 407 Dwarf_Attribute at; 408 Dwarf_Debug dbg; 409 int ret; 410 411 dbg = die != NULL ? die->die_dbg : NULL; 412 413 assert(atp != NULL); 414 415 if (die == NULL || string == NULL) { 416 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 417 return (DW_DLE_ARGUMENT); 418 } 419 420 if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE) 421 return (ret); 422 423 at->at_die = die; 424 at->at_attrib = attr; 425 at->at_form = DW_FORM_strp; 426 if ((ret = _dwarf_strtab_add(dbg, string, &at->u[0].u64, 427 error)) != DW_DLE_NONE) { 428 free(at); 429 return (ret); 430 } 431 at->u[1].s = _dwarf_strtab_get_table(dbg) + at->u[0].u64; 432 433 *atp = at; 434 435 STAILQ_INSERT_TAIL(&die->die_attr, at, at_next); 436 437 return (DW_DLE_NONE); 438 } 439 440 int 441 _dwarf_attr_gen(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs, 442 Dwarf_CU cu, Dwarf_Die die, int pass2, Dwarf_Error *error) 443 { 444 Dwarf_Attribute at; 445 int ret; 446 447 assert(dbg != NULL && ds != NULL && cu != NULL && die != NULL); 448 449 STAILQ_FOREACH(at, &die->die_attr, at_next) { 450 ret = _dwarf_attr_write(dbg, ds, drs, cu, at, pass2, error); 451 if (ret != DW_DLE_NONE) 452 return (ret); 453 } 454 455 return (DW_DLE_NONE); 456 } 457