1/*
2
3  Copyright (C) 2000,2004 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., 1500 Crittenden Lane,
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 */
50void _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-----------------------------------------------------------------------------*/
58Dwarf_P_Die
59dwarf_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-----------------------------------------------------------------------------*/
88Dwarf_P_Die
89dwarf_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-----------------------------------------------------------------------------*/
159Dwarf_Unsigned
160dwarf_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
173int
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------------------------------------------------------------------------------*/
213Dwarf_P_Attribute
214dwarf_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------------------------------------------------------------------------------*/
255Dwarf_P_Attribute
256dwarf_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
295int
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
336int
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
379void
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