1 /* 2 3 Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. 4 Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. 5 6 This program is free software; you can redistribute it and/or modify it 7 under the terms of version 2.1 of the GNU Lesser General Public License 8 as published by the Free Software Foundation. 9 10 This program is distributed in the hope that it would be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13 14 Further, this software is distributed without any warranty that it is 15 free of the rightful claim of any third person regarding infringement 16 or the like. Any license provided herein, whether implied or 17 otherwise, applies only to this software file. Patent licenses, if 18 any, provided herein do not apply to combinations of this program with 19 other software, or any other product whatsoever. 20 21 You should have received a copy of the GNU Lesser General Public 22 License along with this program; if not, write the Free Software 23 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, 24 USA. 25 26 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, 27 Mountain View, CA 94043, or: 28 29 http://www.sgi.com 30 31 For further information regarding this notice, see: 32 33 http://oss.sgi.com/projects/GenInfo/NoticeExplan 34 35 */ 36 37 38 39 #include "config.h" 40 #include "libdwarfdefs.h" 41 #include <stdio.h> 42 #include <string.h> 43 #include "pro_incl.h" 44 #include "pro_die.h" 45 46 #ifndef R_MIPS_NONE 47 #define R_MIPS_NONE 0 48 #endif 49 50 /* adds an attribute to a die */ 51 void _dwarf_pro_add_at_to_die(Dwarf_P_Die die, Dwarf_P_Attribute attr); 52 53 /*---------------------------------------------------------------------------- 54 This function creates a new die. 55 tag: tag of the new die to be created 56 parent,child,left,right: specify neighbors of the new die. Only 57 one of these may be non-null 58 -----------------------------------------------------------------------------*/ 59 Dwarf_P_Die 60 dwarf_new_die(Dwarf_P_Debug dbg, 61 Dwarf_Tag tag, 62 Dwarf_P_Die parent, 63 Dwarf_P_Die child, 64 Dwarf_P_Die left, Dwarf_P_Die right, Dwarf_Error * error) 65 { 66 Dwarf_P_Die ret_die = 0; 67 68 Dwarf_P_Die new_die = (Dwarf_P_Die) 69 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Die_s)); 70 if (new_die == NULL) { 71 DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_ALLOC, 72 (Dwarf_P_Die) DW_DLV_BADADDR); 73 } 74 new_die->di_parent = NULL; 75 new_die->di_left = NULL; 76 new_die->di_right = NULL; 77 new_die->di_child = NULL; 78 new_die->di_last_child = NULL; 79 new_die->di_tag = tag; 80 new_die->di_dbg = dbg; 81 new_die->di_marker = 0; 82 ret_die = 83 dwarf_die_link(new_die, parent, child, left, right, error); 84 return ret_die; 85 } 86 87 /*---------------------------------------------------------------------------- 88 This function links up a die to specified neighbors 89 parent,child,left,right: specify neighbors of the new die. Only 90 one of these may be non-null 91 -----------------------------------------------------------------------------*/ 92 Dwarf_P_Die 93 dwarf_die_link(Dwarf_P_Die new_die, 94 Dwarf_P_Die parent, 95 Dwarf_P_Die child, 96 Dwarf_P_Die left, Dwarf_P_Die right, Dwarf_Error * error) 97 { 98 /* Count the # of non null neighbors. */ 99 int n_nulls = 0; 100 101 if (parent != NULL) { 102 n_nulls++; 103 if (new_die->di_parent != NULL) { 104 DWARF_P_DBG_ERROR(NULL, DW_DLE_LINK_LOOP, 105 (Dwarf_P_Die) DW_DLV_BADADDR); 106 } 107 new_die->di_parent = parent; 108 if (parent->di_child) { 109 110 /* di_last_child identifies the last sibling, the 111 die we want to attach new_die to. */ 112 /* ASSERT: if di_child is set so is di_last_child. */ 113 Dwarf_P_Die former_lastchild = parent->di_last_child; 114 parent->di_last_child = new_die; 115 /* Attach to the new die to end of the sibling list. */ 116 former_lastchild->di_right = new_die; 117 new_die->di_left = former_lastchild; 118 } else { 119 parent->di_child = new_die; 120 parent->di_last_child = new_die; 121 } 122 } 123 if (child != NULL) { 124 n_nulls++; 125 new_die->di_child = child; 126 new_die->di_last_child = child; 127 if (child->di_parent) { 128 DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS, 129 (Dwarf_P_Die) DW_DLV_BADADDR); 130 } else { 131 child->di_parent = new_die; 132 } 133 } 134 if (left != NULL) { 135 n_nulls++; 136 new_die->di_left = left; 137 if (left->di_right) { 138 /* There's already a right sibling of left, 139 insert the new die in the list. */ 140 new_die->di_right = left->di_right; 141 left->di_right->di_left = new_die; 142 } 143 left->di_right = new_die; 144 if (new_die->di_parent) { 145 DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS, 146 (Dwarf_P_Die) DW_DLV_BADADDR); 147 } else { 148 new_die->di_parent = left->di_parent; 149 } 150 } 151 if (right != NULL) { 152 n_nulls++; 153 new_die->di_right = right; 154 if (right->di_left) { 155 /* There is already a left sibling of the right die, 156 insert the new die in the list. */ 157 new_die->di_left = right->di_left; 158 right->di_left->di_right = new_die; 159 } 160 right->di_left = new_die; 161 if (new_die->di_parent) { 162 DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS, 163 (Dwarf_P_Die) DW_DLV_BADADDR); 164 } else { 165 new_die->di_parent = right->di_parent; 166 } 167 } 168 if (n_nulls > 1) { 169 /* Multiple neighbors! error! */ 170 DWARF_P_DBG_ERROR(NULL, DW_DLE_EXTRA_NEIGHBORS, 171 (Dwarf_P_Die) DW_DLV_BADADDR); 172 } 173 return new_die; 174 175 } 176 177 Dwarf_Unsigned 178 dwarf_add_die_marker(Dwarf_P_Debug dbg, 179 Dwarf_P_Die die, 180 Dwarf_Unsigned marker, 181 Dwarf_Error * error) 182 { 183 if (die == NULL) { 184 DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, DW_DLV_NOCOUNT); 185 } 186 die->di_marker = marker; 187 return 0; 188 } 189 190 191 Dwarf_Unsigned 192 dwarf_get_die_marker(Dwarf_P_Debug dbg, 193 Dwarf_P_Die die, 194 Dwarf_Unsigned * marker, 195 Dwarf_Error * error) 196 { 197 if (die == NULL) { 198 DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, DW_DLV_NOCOUNT); 199 } 200 *marker = die->di_marker; 201 return 0; 202 } 203 204 205 /*---------------------------------------------------------------------------- 206 This function adds a die to dbg struct. It should be called using 207 the root of all the dies. 208 -----------------------------------------------------------------------------*/ 209 Dwarf_Unsigned 210 dwarf_add_die_to_debug(Dwarf_P_Debug dbg, 211 Dwarf_P_Die first_die, Dwarf_Error * error) 212 { 213 if (first_die == NULL) { 214 DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, DW_DLV_NOCOUNT); 215 } 216 if (first_die->di_tag != DW_TAG_compile_unit) { 217 DWARF_P_DBG_ERROR(dbg, DW_DLE_WRONG_TAG, DW_DLV_NOCOUNT); 218 } 219 dbg->de_dies = first_die; 220 return 0; 221 } 222 223 int 224 _dwarf_pro_add_AT_stmt_list(Dwarf_P_Debug dbg, 225 Dwarf_P_Die first_die, Dwarf_Error * error) 226 { 227 Dwarf_P_Attribute new_attr; 228 int uwordb_size = dbg->de_offset_size; 229 230 /* Add AT_stmt_list attribute */ 231 new_attr = (Dwarf_P_Attribute) 232 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); 233 if (new_attr == NULL) { 234 DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, DW_DLV_NOCOUNT); 235 } 236 237 new_attr->ar_attribute = DW_AT_stmt_list; 238 new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form; 239 new_attr->ar_rel_type = dbg->de_offset_reloc; 240 241 new_attr->ar_nbytes = uwordb_size; 242 new_attr->ar_next = NULL; 243 new_attr->ar_reloc_len = uwordb_size; 244 new_attr->ar_data = (char *) 245 _dwarf_p_get_alloc(dbg, uwordb_size); 246 if (new_attr->ar_data == NULL) { 247 DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT); 248 } 249 { 250 Dwarf_Unsigned du = 0; 251 252 WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, 253 (const void *) &du, sizeof(du), uwordb_size); 254 } 255 256 _dwarf_pro_add_at_to_die(first_die, new_attr); 257 return 0; 258 } 259 260 /*----------------------------------------------------------------------------- 261 Add AT_name attribute to die 262 ------------------------------------------------------------------------------*/ 263 Dwarf_P_Attribute 264 dwarf_add_AT_name(Dwarf_P_Die die, char *name, Dwarf_Error * error) 265 { 266 Dwarf_P_Attribute new_attr; 267 268 if (die == NULL) { 269 DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, 270 (Dwarf_P_Attribute) DW_DLV_BADADDR); 271 } 272 new_attr = (Dwarf_P_Attribute) 273 _dwarf_p_get_alloc(die->di_dbg,sizeof(struct Dwarf_P_Attribute_s)); 274 if (new_attr == NULL) { 275 DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, 276 (Dwarf_P_Attribute) DW_DLV_BADADDR); 277 } 278 279 /* fill in the information */ 280 new_attr->ar_attribute = DW_AT_name; 281 /* assume that form is string, no debug_str yet */ 282 new_attr->ar_attribute_form = DW_FORM_string; 283 new_attr->ar_nbytes = strlen(name) + 1; 284 new_attr->ar_next = NULL; 285 new_attr->ar_reloc_len = 0; 286 new_attr->ar_data = (char *) 287 _dwarf_p_get_alloc(die->di_dbg, strlen(name)+1); 288 if (new_attr->ar_data == NULL) { 289 DWARF_P_DBG_ERROR(NULL, DW_DLE_STRING_ALLOC, 290 (Dwarf_P_Attribute) DW_DLV_BADADDR); 291 } 292 strcpy(new_attr->ar_data, name); 293 294 new_attr->ar_rel_type = R_MIPS_NONE; 295 296 /* add attribute to the die */ 297 _dwarf_pro_add_at_to_die(die, new_attr); 298 return new_attr; 299 } 300 301 302 /*----------------------------------------------------------------------------- 303 Add AT_comp_dir attribute to die 304 ------------------------------------------------------------------------------*/ 305 Dwarf_P_Attribute 306 dwarf_add_AT_comp_dir(Dwarf_P_Die ownerdie, 307 char *current_working_directory, 308 Dwarf_Error * error) 309 { 310 Dwarf_P_Attribute new_attr; 311 312 if (ownerdie == NULL) { 313 DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, 314 (Dwarf_P_Attribute) DW_DLV_BADADDR); 315 } 316 new_attr = (Dwarf_P_Attribute) 317 _dwarf_p_get_alloc(ownerdie->di_dbg, 318 sizeof(struct Dwarf_P_Attribute_s)); 319 if (new_attr == NULL) { 320 DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, 321 (Dwarf_P_Attribute) DW_DLV_BADADDR); 322 } 323 324 /* fill in the information */ 325 new_attr->ar_attribute = DW_AT_comp_dir; 326 /* assume that form is string, no debug_str yet */ 327 new_attr->ar_attribute_form = DW_FORM_string; 328 new_attr->ar_nbytes = strlen(current_working_directory) + 1; 329 new_attr->ar_next = NULL; 330 new_attr->ar_reloc_len = 0; 331 new_attr->ar_data = (char *) 332 _dwarf_p_get_alloc(ownerdie->di_dbg, 333 strlen(current_working_directory)+1); 334 if (new_attr->ar_data == NULL) { 335 DWARF_P_DBG_ERROR(NULL, DW_DLE_STRING_ALLOC, 336 (Dwarf_P_Attribute) DW_DLV_BADADDR); 337 } 338 strcpy(new_attr->ar_data, current_working_directory); 339 340 new_attr->ar_rel_type = R_MIPS_NONE; 341 342 /* add attribute to the die */ 343 _dwarf_pro_add_at_to_die(ownerdie, new_attr); 344 return new_attr; 345 } 346 347 int 348 _dwarf_pro_add_AT_fde(Dwarf_P_Debug dbg, 349 Dwarf_P_Die die, 350 Dwarf_Unsigned offset, Dwarf_Error * error) 351 { 352 Dwarf_P_Attribute new_attr; 353 int uwordb_size = dbg->de_offset_size; 354 355 if (die == NULL) { 356 DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, -1); 357 } 358 new_attr = (Dwarf_P_Attribute) 359 _dwarf_p_get_alloc(dbg,sizeof(struct Dwarf_P_Attribute_s)); 360 if (new_attr == NULL) { 361 DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, -1); 362 } 363 364 /* fill in the information */ 365 new_attr->ar_attribute = DW_AT_MIPS_fde; 366 new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form;; 367 new_attr->ar_rel_type = dbg->de_offset_reloc; 368 new_attr->ar_nbytes = uwordb_size; 369 new_attr->ar_next = NULL; 370 new_attr->ar_reloc_len = uwordb_size; 371 new_attr->ar_data = (char *) 372 _dwarf_p_get_alloc(dbg, uwordb_size); 373 if (new_attr->ar_data == NULL) { 374 DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT); 375 } 376 { 377 Dwarf_Unsigned du = offset; 378 379 WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, 380 (const void *) &du, sizeof(du), uwordb_size); 381 } 382 383 _dwarf_pro_add_at_to_die(die, new_attr); 384 385 return 0; 386 } 387 388 int 389 _dwarf_pro_add_AT_macro_info(Dwarf_P_Debug dbg, 390 Dwarf_P_Die die, 391 Dwarf_Unsigned offset, Dwarf_Error * error) 392 { 393 Dwarf_P_Attribute new_attr; 394 int uwordb_size = dbg->de_offset_size; 395 396 if (die == NULL) { 397 DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, -1); 398 } 399 new_attr = (Dwarf_P_Attribute) 400 _dwarf_p_get_alloc(dbg,sizeof(struct Dwarf_P_Attribute_s)); 401 if (new_attr == NULL) { 402 DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, -1); 403 } 404 405 /* fill in the information */ 406 new_attr->ar_attribute = DW_AT_macro_info; 407 new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form; 408 new_attr->ar_rel_type = dbg->de_offset_reloc; 409 410 new_attr->ar_nbytes = uwordb_size; 411 new_attr->ar_next = NULL; 412 new_attr->ar_reloc_len = uwordb_size; 413 new_attr->ar_data = (char *) 414 _dwarf_p_get_alloc(dbg, uwordb_size); 415 if (new_attr->ar_data == NULL) { 416 DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT); 417 } 418 { 419 Dwarf_Unsigned du = offset; 420 421 WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, 422 (const void *) &du, sizeof(du), uwordb_size); 423 } 424 425 _dwarf_pro_add_at_to_die(die, new_attr); 426 427 return 0; 428 } 429 430 431 void 432 _dwarf_pro_add_at_to_die(Dwarf_P_Die die, Dwarf_P_Attribute attr) 433 { 434 if (die->di_last_attr) { 435 die->di_last_attr->ar_next = attr; 436 die->di_last_attr = attr; 437 die->di_n_attr++; 438 } else { 439 die->di_n_attr = 1; 440 die->di_attrs = die->di_last_attr = attr; 441 } 442 } 443