xref: /illumos-gate/usr/src/lib/libdwarf/common/pro_die.c (revision bde334a8dbd66dfa70ce4d7fc9dcad6e1ae45fe4)
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