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