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