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