xref: /titanic_44/usr/src/tools/ctf/dwarf/common/pro_die.c (revision 430b4c467020edf2445feb0c21db01c88b86243a)
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