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