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