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
dwarf_new_die(Dwarf_P_Debug dbg,Dwarf_Tag tag,Dwarf_P_Die parent,Dwarf_P_Die child,Dwarf_P_Die left,Dwarf_P_Die right,Dwarf_Error * error)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
dwarf_die_link(Dwarf_P_Die new_die,Dwarf_P_Die parent,Dwarf_P_Die child,Dwarf_P_Die left,Dwarf_P_Die right,Dwarf_Error * error)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
dwarf_add_die_marker(Dwarf_P_Debug dbg,Dwarf_P_Die die,Dwarf_Unsigned marker,Dwarf_Error * error)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
dwarf_get_die_marker(Dwarf_P_Debug dbg,Dwarf_P_Die die,Dwarf_Unsigned * marker,Dwarf_Error * error)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
dwarf_add_die_to_debug(Dwarf_P_Debug dbg,Dwarf_P_Die first_die,Dwarf_Error * error)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
_dwarf_pro_add_AT_stmt_list(Dwarf_P_Debug dbg,Dwarf_P_Die first_die,Dwarf_Error * error)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
dwarf_add_AT_name(Dwarf_P_Die die,char * name,Dwarf_Error * error)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
dwarf_add_AT_comp_dir(Dwarf_P_Die ownerdie,char * current_working_directory,Dwarf_Error * error)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
_dwarf_pro_add_AT_fde(Dwarf_P_Debug dbg,Dwarf_P_Die die,Dwarf_Unsigned offset,Dwarf_Error * error)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
_dwarf_pro_add_AT_macro_info(Dwarf_P_Debug dbg,Dwarf_P_Die die,Dwarf_Unsigned offset,Dwarf_Error * error)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
_dwarf_pro_add_at_to_die(Dwarf_P_Die die,Dwarf_P_Attribute attr)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