xref: /illumos-gate/usr/src/lib/libdwarf/common/pro_forms.c (revision bc1f688b4872ace323eaddbb1a6365d054e7bf56)
1 /*
2   Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
3   Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
4   Portions Copyright 2007-2010 David Anderson. 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 <limits.h>
44 #include "pro_incl.h"
45 #include "pro_expr.h"
46 
47 #ifndef R_MIPS_NONE
48 #define R_MIPS_NONE 0
49 #endif
50 
51 
52     /* Indicates no relocation needed. */
53 #define NO_ELF_SYM_INDEX        0
54 
55 
56 /* adds an attribute to a die */
57 extern void _dwarf_pro_add_at_to_die(Dwarf_P_Die die,
58                                      Dwarf_P_Attribute attr);
59 
60 /*
61     This function adds an attribute whose value is
62     a target address to the given die.  The attribute
63     is given the name provided by attr.  The address
64     is given in pc_value.
65 */
66 
67 static Dwarf_P_Attribute
68 local_add_AT_address(Dwarf_P_Debug dbg,
69                      Dwarf_P_Die ownerdie,
70                      Dwarf_Half attr,
71                      Dwarf_Signed form,
72                      Dwarf_Unsigned pc_value,
73                      Dwarf_Unsigned sym_index,
74                      Dwarf_Error * error);
75 
76 /* old interface */
77 Dwarf_P_Attribute
78 dwarf_add_AT_targ_address(Dwarf_P_Debug dbg,
79                           Dwarf_P_Die ownerdie,
80                           Dwarf_Half attr,
81                           Dwarf_Unsigned pc_value,
82                           Dwarf_Signed sym_index, Dwarf_Error * error)
83 {
84     return
85         dwarf_add_AT_targ_address_b(dbg,
86                                     ownerdie,
87                                     attr,
88                                     pc_value,
89                                     (Dwarf_Unsigned) sym_index, error);
90 }
91 
92 /* New interface, replacing dwarf_add_AT_targ_address.
93    Essentially just makes sym_index a Dwarf_Unsigned
94    so for symbolic relocations it can be a full address.
95 */
96 Dwarf_P_Attribute
97 dwarf_add_AT_targ_address_b(Dwarf_P_Debug dbg,
98                             Dwarf_P_Die ownerdie,
99                             Dwarf_Half attr,
100                             Dwarf_Unsigned pc_value,
101                             Dwarf_Unsigned sym_index,
102                             Dwarf_Error * error)
103 {
104     switch (attr) {
105     case DW_AT_low_pc:
106     case DW_AT_high_pc:
107 
108     /* added to support location lists */
109     /* no way to check that this is a loclist-style address though */
110     case DW_AT_location:
111     case DW_AT_string_length:
112     case DW_AT_return_addr:
113     case DW_AT_frame_base:
114     case DW_AT_segment:
115     case DW_AT_static_link:
116     case DW_AT_use_location:
117     case DW_AT_vtable_elem_location:
118     case DW_AT_const_value: /* Gcc can generate this as address. */
119     case DW_AT_entry_pc:
120         break;
121     default:
122         if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
123             _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
124             return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
125         }
126         break;
127     }
128 
129     return local_add_AT_address(dbg, ownerdie, attr, DW_FORM_addr,
130                                 pc_value, sym_index, error);
131 }
132 
133 Dwarf_P_Attribute
134 dwarf_add_AT_ref_address(Dwarf_P_Debug dbg,
135                          Dwarf_P_Die ownerdie,
136                          Dwarf_Half attr,
137                          Dwarf_Unsigned pc_value,
138                          Dwarf_Unsigned sym_index,
139                          Dwarf_Error * error)
140 {
141     switch (attr) {
142     case DW_AT_type:
143     case DW_AT_import:
144         break;
145 
146     default:
147         if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
148             _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
149             return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
150         }
151         break;
152     }
153 
154     return local_add_AT_address(dbg, ownerdie, attr, DW_FORM_ref_addr,
155                                 pc_value, sym_index, error);
156 }
157 
158 
159 /* Make sure attribute types are checked before entering here. */
160 static Dwarf_P_Attribute
161 local_add_AT_address(Dwarf_P_Debug dbg,
162                      Dwarf_P_Die ownerdie,
163                      Dwarf_Half attr,
164                      Dwarf_Signed form,
165                      Dwarf_Unsigned pc_value,
166                      Dwarf_Unsigned sym_index,
167                      Dwarf_Error * error)
168 {
169     Dwarf_P_Attribute new_attr;
170     int upointer_size = dbg->de_pointer_size;
171 
172     if (dbg == NULL) {
173         _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
174         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
175     }
176 
177     if (ownerdie == NULL) {
178         _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
179         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
180     }
181 
182     /* attribute types have already been checked */
183     /* switch (attr) { ... } */
184 
185     new_attr = (Dwarf_P_Attribute)
186         _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
187     if (new_attr == NULL) {
188         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
189         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
190     }
191 
192     new_attr->ar_attribute = attr;
193     new_attr->ar_attribute_form = form;
194     new_attr->ar_nbytes = upointer_size;
195     new_attr->ar_rel_symidx = sym_index;
196     new_attr->ar_reloc_len = upointer_size;
197     new_attr->ar_next = 0;
198     if (sym_index != NO_ELF_SYM_INDEX)
199         new_attr->ar_rel_type = dbg->de_ptr_reloc;
200     else
201         new_attr->ar_rel_type = R_MIPS_NONE;
202 
203     new_attr->ar_data = (char *)
204         _dwarf_p_get_alloc(dbg, upointer_size);
205     if (new_attr->ar_data == NULL) {
206         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
207         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
208     }
209     WRITE_UNALIGNED(dbg, new_attr->ar_data,
210                     (const void *) &pc_value,
211                     sizeof(pc_value), upointer_size);
212 
213     /* add attribute to the die */
214     _dwarf_pro_add_at_to_die(ownerdie, new_attr);
215     return new_attr;
216 }
217 
218 /*
219  * Functions to compress and uncompress data from normal
220  * arrays of integral types into arrays of LEB128 numbers.
221  * Extend these functions as needed to handle wider input
222  * variety.  Return values should be freed with _dwarf_p_dealloc
223  * after they aren't needed any more.
224  */
225 
226 /* return value points to an array of LEB number */
227 
228 void *
229 dwarf_compress_integer_block(
230     Dwarf_P_Debug    dbg,
231     Dwarf_Bool       unit_is_signed,
232     Dwarf_Small      unit_length_in_bits,
233     void*            input_block,
234     Dwarf_Unsigned   input_length_in_units,
235     Dwarf_Unsigned*  output_length_in_bytes_ptr,
236     Dwarf_Error*     error
237 )
238 {
239     Dwarf_Unsigned output_length_in_bytes = 0;
240     char * output_block = 0;
241     char encode_buffer[ENCODE_SPACE_NEEDED];
242     int i = 0;
243     char * ptr = 0;
244     int remain = 0;
245     int result = 0;
246 
247     if (dbg == NULL) {
248         _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
249         return((void *)DW_DLV_BADADDR);
250     }
251 
252     if (unit_is_signed == false ||
253         unit_length_in_bits != 32 ||
254         input_block == NULL ||
255         input_length_in_units == 0 ||
256         output_length_in_bytes_ptr == NULL) {
257 
258         _dwarf_p_error(NULL, error, DW_DLE_BADBITC);
259         return ((void *) DW_DLV_BADADDR);
260     }
261 
262     /* At this point we assume the format is: signed 32 bit */
263 
264     /* first compress everything to find the total size. */
265 
266     output_length_in_bytes = 0;
267     for (i=0; i<input_length_in_units; i++) {
268         int unit_encoded_size;
269         Dwarf_sfixed unit; /* this is fixed at signed-32-bits */
270 
271         unit = ((Dwarf_sfixed*)input_block)[i];
272 
273         result = _dwarf_pro_encode_signed_leb128_nm(unit, &unit_encoded_size,
274                                              encode_buffer,sizeof(encode_buffer));
275         if (result !=  DW_DLV_OK) {
276             _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
277             return((Dwarf_P_Attribute)DW_DLV_BADADDR);
278         }
279         output_length_in_bytes += unit_encoded_size;
280     }
281 
282 
283     /* then alloc */
284 
285     output_block = (void *)
286         _dwarf_p_get_alloc(dbg, output_length_in_bytes);
287     if (output_block == NULL) {
288         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
289         return((void*)DW_DLV_BADADDR);
290     }
291 
292     /* then compress again and copy into new buffer */
293 
294     ptr = output_block;
295     remain = output_length_in_bytes;
296     for (i=0; i<input_length_in_units; i++) {
297         int unit_encoded_size;
298         Dwarf_sfixed unit; /* this is fixed at signed-32-bits */
299 
300         unit = ((Dwarf_sfixed*)input_block)[i];
301 
302         result = _dwarf_pro_encode_signed_leb128_nm(unit, &unit_encoded_size,
303                                              ptr, remain);
304         if (result !=  DW_DLV_OK) {
305             _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
306             return((Dwarf_P_Attribute)DW_DLV_BADADDR);
307         }
308         remain -= unit_encoded_size;
309         ptr += unit_encoded_size;
310     }
311 
312     if (remain != 0) {
313         _dwarf_p_dealloc(dbg, (unsigned char *)output_block);
314         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
315         return((Dwarf_P_Attribute)DW_DLV_BADADDR);
316     }
317 
318     *output_length_in_bytes_ptr = output_length_in_bytes;
319     return (void*) output_block;
320 
321 }
322 
323 void
324 dwarf_dealloc_compressed_block(Dwarf_P_Debug dbg, void * space)
325 {
326     _dwarf_p_dealloc(dbg, space);
327 }
328 
329 /* This is very similar to targ_address but results in a different FORM */
330 /* dbg->de_ar_data_attribute_form is data4 or data8
331    and dwarf4 changes the definition for such on DW_AT_high_pc.
332    DWARF 3: the FORM here has no defined meaning for dwarf3.
333    DWARF 4: the FORM here means that for DW_AT_high_pc the value
334             is not a high address but is instead an offset
335             from a (separate) DW_AT_low_pc.
336    The intent for DWARF4 is that this is not a relocated
337    address at all.  Instead a simple offset.
338    But this should NOT be called for a simple non-relocated offset.
339    So do not call this with an attr of DW_AT_high_pc.
340    Use dwarf_add_AT_unsigned_const() (for example) instead of
341    dwarf_add_AT_dataref when the value is a simple offset .
342 */
343 Dwarf_P_Attribute
344 dwarf_add_AT_dataref(
345     Dwarf_P_Debug dbg,
346     Dwarf_P_Die ownerdie,
347     Dwarf_Half attr,
348     Dwarf_Unsigned pc_value,
349     Dwarf_Unsigned sym_index,
350     Dwarf_Error * error)
351 {
352     /* TODO: Add checking here */
353     return local_add_AT_address(dbg, ownerdie, attr,
354                                 dbg->de_ar_data_attribute_form,
355                                 pc_value,
356                                 sym_index,
357                                 error);
358 }
359 
360 
361 
362 Dwarf_P_Attribute
363 dwarf_add_AT_block(
364     Dwarf_P_Debug       dbg,
365     Dwarf_P_Die         ownerdie,
366     Dwarf_Half          attr,
367     Dwarf_Small         *block_data,
368     Dwarf_Unsigned      block_size,
369     Dwarf_Error         *error
370 )
371 {
372     Dwarf_P_Attribute   new_attr;
373     int result;
374     char encode_buffer[ENCODE_SPACE_NEEDED];
375     int len_size;
376     char * attrdata;
377 
378     if (dbg == NULL) {
379         _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
380         return((Dwarf_P_Attribute)DW_DLV_BADADDR);
381     }
382 
383     if (ownerdie == NULL) {
384         _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
385         return((Dwarf_P_Attribute)DW_DLV_BADADDR);
386     }
387 
388     /* I don't mess with block1, block2, block4, not worth the effort */
389 
390     /* So, encode the length into LEB128 */
391     result = _dwarf_pro_encode_leb128_nm(block_size, &len_size,
392                                          encode_buffer,sizeof(encode_buffer));
393     if (result !=  DW_DLV_OK) {
394         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
395         return((Dwarf_P_Attribute)DW_DLV_BADADDR);
396     }
397 
398     /* Allocate the new attribute */
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_error(dbg, error, DW_DLE_ALLOC_FAIL);
403         return((Dwarf_P_Attribute)DW_DLV_BADADDR);
404     }
405 
406     /* Fill in the attribute */
407     new_attr->ar_attribute = attr;
408     new_attr->ar_attribute_form = DW_FORM_block;
409     new_attr->ar_nbytes = len_size + block_size;
410     new_attr->ar_next = 0;
411 
412     new_attr->ar_data = attrdata = (char *)
413         _dwarf_p_get_alloc(dbg, len_size + block_size);
414     if (new_attr->ar_data == NULL) {
415         /* free the block we got earlier */
416         _dwarf_p_dealloc(dbg, (unsigned char *) new_attr);
417         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
418         return((Dwarf_P_Attribute)DW_DLV_BADADDR);
419     }
420 
421     /* write length and data to attribute data buffer */
422     memcpy(attrdata, encode_buffer, len_size);
423     attrdata += len_size;
424     memcpy(attrdata, block_data, block_size);
425 
426     /* add attribute to the die */
427     _dwarf_pro_add_at_to_die(ownerdie, new_attr);
428 
429     return new_attr;
430 }
431 
432 
433 /*
434     This function adds attributes whose value
435     is an unsigned constant.  It determines the
436     size of the value field from the value of
437     the constant.
438 */
439 Dwarf_P_Attribute
440 dwarf_add_AT_unsigned_const(Dwarf_P_Debug dbg,
441                             Dwarf_P_Die ownerdie,
442                             Dwarf_Half attr,
443                             Dwarf_Unsigned value, Dwarf_Error * error)
444 {
445     Dwarf_P_Attribute new_attr;
446     Dwarf_Half attr_form;
447     Dwarf_Small size;
448 
449     if (dbg == NULL) {
450         _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
451         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
452     }
453 
454     if (ownerdie == NULL) {
455         _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
456         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
457     }
458 
459     switch (attr) {
460     case DW_AT_ordering:
461     case DW_AT_byte_size:
462     case DW_AT_bit_offset:
463     case DW_AT_bit_size:
464     case DW_AT_inline:
465     case DW_AT_language:
466     case DW_AT_visibility:
467     case DW_AT_virtuality:
468     case DW_AT_accessibility:
469     case DW_AT_address_class:
470     case DW_AT_calling_convention:
471     case DW_AT_encoding:
472     case DW_AT_identifier_case:
473     case DW_AT_MIPS_loop_unroll_factor:
474     case DW_AT_MIPS_software_pipeline_depth:
475         break;
476 
477     case DW_AT_decl_column:
478     case DW_AT_decl_file:
479     case DW_AT_decl_line:
480     case DW_AT_const_value:
481     case DW_AT_start_scope:
482     case DW_AT_stride_size:
483     case DW_AT_count:
484     case DW_AT_associated:
485     case DW_AT_allocated:
486     case DW_AT_upper_bound:
487     case DW_AT_lower_bound:
488     case DW_AT_call_file:
489     case DW_AT_call_line:
490         break;
491 
492         default: {
493                  if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
494                      _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
495                      return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
496                }
497                break;
498             }
499         }
500 
501     /*
502        Compute the number of bytes needed to hold constant. */
503     if (value <= UCHAR_MAX) {
504         attr_form = DW_FORM_data1;
505         size = 1;
506     } else if (value <= USHRT_MAX) {
507         attr_form = DW_FORM_data2;
508         size = 2;
509     } else if (value <= UINT_MAX) {
510         attr_form = DW_FORM_data4;
511         size = 4;
512     } else {
513         attr_form = DW_FORM_data8;
514         size = 8;
515     }
516 
517     new_attr = (Dwarf_P_Attribute)
518         _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
519     if (new_attr == NULL) {
520         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
521         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
522     }
523 
524     new_attr->ar_attribute = attr;
525     new_attr->ar_attribute_form = attr_form;
526     new_attr->ar_rel_type = R_MIPS_NONE;
527     new_attr->ar_reloc_len = 0; /* irrelevant: unused with R_MIPS_NONE */
528     new_attr->ar_nbytes = size;
529     new_attr->ar_next = 0;
530 
531     new_attr->ar_data = (char *)
532         _dwarf_p_get_alloc(dbg, size);
533     if (new_attr->ar_data == NULL) {
534         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
535         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
536     }
537     WRITE_UNALIGNED(dbg, new_attr->ar_data,
538                     (const void *) &value, sizeof(value), size);
539 
540     /* add attribute to the die */
541     _dwarf_pro_add_at_to_die(ownerdie, new_attr);
542     return new_attr;
543 }
544 
545 
546 /*
547     This function adds attributes whose value
548     is an signed constant.  It determines the
549     size of the value field from the value of
550     the constant.
551 */
552 Dwarf_P_Attribute
553 dwarf_add_AT_signed_const(Dwarf_P_Debug dbg,
554                           Dwarf_P_Die ownerdie,
555                           Dwarf_Half attr,
556                           Dwarf_Signed value, Dwarf_Error * error)
557 {
558     Dwarf_P_Attribute new_attr;
559     Dwarf_Half attr_form;
560     Dwarf_Small size;
561 
562     if (dbg == NULL) {
563         _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
564         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
565     }
566 
567     if (ownerdie == NULL) {
568         _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
569         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
570     }
571 
572     switch (attr) {
573     case DW_AT_lower_bound:
574     case DW_AT_upper_bound:
575     case DW_AT_const_value:
576     case DW_AT_bit_offset:
577     case DW_AT_bit_size:
578     case DW_AT_byte_size:
579     case DW_AT_count:
580     case DW_AT_byte_stride:
581     case DW_AT_bit_stride:
582     case DW_AT_allocated:
583     case DW_AT_associated:
584         break;
585 
586     default:{
587                 if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
588                      _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
589                      return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
590                 }
591         }
592         break;
593     }
594 
595     /*
596        Compute the number of bytes needed to hold constant. */
597     if (value >= SCHAR_MIN && value <= SCHAR_MAX) {
598         attr_form = DW_FORM_data1;
599         size = 1;
600     } else if (value >= SHRT_MIN && value <= SHRT_MAX) {
601         attr_form = DW_FORM_data2;
602         size = 2;
603     } else if (value >= INT_MIN && value <= INT_MAX) {
604         attr_form = DW_FORM_data4;
605         size = 4;
606     } else {
607         attr_form = DW_FORM_data8;
608         size = 8;
609     }
610 
611     new_attr = (Dwarf_P_Attribute)
612         _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
613     if (new_attr == NULL) {
614         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
615         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
616     }
617 
618     new_attr->ar_attribute = attr;
619     new_attr->ar_attribute_form = attr_form;
620     new_attr->ar_rel_type = R_MIPS_NONE;
621     new_attr->ar_reloc_len = 0; /* irrelevant: unused with R_MIPS_NONE */
622     new_attr->ar_nbytes = size;
623     new_attr->ar_next = 0;
624 
625     new_attr->ar_data = (char *)
626         _dwarf_p_get_alloc(dbg, size);
627     if (new_attr->ar_data == NULL) {
628         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
629         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
630     }
631     WRITE_UNALIGNED(dbg, new_attr->ar_data,
632                     (const void *) &value, sizeof(value), size);
633 
634     /* add attribute to the die */
635     _dwarf_pro_add_at_to_die(ownerdie, new_attr);
636     return new_attr;
637 }
638 
639 
640 /*
641     This function adds attributes whose value
642     is a location expression.
643 */
644 Dwarf_P_Attribute
645 dwarf_add_AT_location_expr(Dwarf_P_Debug dbg,
646                            Dwarf_P_Die ownerdie,
647                            Dwarf_Half attr,
648                            Dwarf_P_Expr loc_expr, Dwarf_Error * error)
649 {
650     char encode_buffer[ENCODE_SPACE_NEEDED];
651     int res;
652     Dwarf_P_Attribute new_attr;
653     Dwarf_Half attr_form;
654     char *len_str = 0;
655     int len_size;
656     int block_size;
657     char *block_dest_ptr;
658     int do_len_as_int = 0;
659 
660     if (dbg == NULL) {
661         _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
662         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
663     }
664 
665     if (ownerdie == NULL) {
666         _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
667         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
668     }
669 
670     if (loc_expr == NULL) {
671         _dwarf_p_error(dbg, error, DW_DLE_EXPR_NULL);
672         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
673     }
674 
675     if (loc_expr->ex_dbg != dbg) {
676         _dwarf_p_error(dbg, error, DW_DLE_LOC_EXPR_BAD);
677         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
678     }
679     block_size = loc_expr->ex_next_byte_offset;
680 
681     switch (attr) {
682     case DW_AT_location:
683     case DW_AT_string_length:
684     case DW_AT_const_value:
685     case DW_AT_use_location:
686     case DW_AT_return_addr:
687     case DW_AT_data_member_location:
688     case DW_AT_frame_base:
689     case DW_AT_static_link:
690     case DW_AT_vtable_elem_location:
691     case DW_AT_lower_bound:
692     case DW_AT_upper_bound:
693     case DW_AT_count:
694     case DW_AT_associated:
695     case DW_AT_allocated:
696     case DW_AT_data_location:
697     case DW_AT_byte_stride:
698     case DW_AT_bit_stride:
699     case DW_AT_byte_size:
700     case DW_AT_bit_size:
701     break;
702 
703     default:
704         if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
705             _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
706             return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
707         }
708     break;
709     }
710 
711     /*
712        Compute the number of bytes needed to hold constant. */
713     if (block_size <= UCHAR_MAX) {
714         attr_form = DW_FORM_block1;
715         len_size = 1;
716         do_len_as_int = 1;
717     } else if (block_size <= USHRT_MAX) {
718         attr_form = DW_FORM_block2;
719         len_size = 2;
720         do_len_as_int = 1;
721     } else if (block_size <= UINT_MAX) {
722         attr_form = DW_FORM_block4;
723         len_size = 4;
724         do_len_as_int = 1;
725     } else {
726         attr_form = DW_FORM_block;
727         res = _dwarf_pro_encode_leb128_nm(block_size, &len_size,
728                                           encode_buffer,
729                                           sizeof(encode_buffer));
730         if (res != DW_DLV_OK) {
731             _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
732             return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
733         }
734         len_str = (char *) encode_buffer;
735     }
736 
737     new_attr = (Dwarf_P_Attribute)
738         _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
739     if (new_attr == NULL) {
740         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
741         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
742     }
743 
744     new_attr->ar_attribute = attr;
745     new_attr->ar_attribute_form = attr_form;
746     new_attr->ar_reloc_len = dbg->de_pointer_size;
747     if (loc_expr->ex_reloc_sym_index != NO_ELF_SYM_INDEX) {
748         new_attr->ar_rel_type = dbg->de_ptr_reloc;
749     } else {
750         new_attr->ar_rel_type = R_MIPS_NONE;
751     }
752     new_attr->ar_rel_symidx = loc_expr->ex_reloc_sym_index;
753     new_attr->ar_rel_offset =
754         (Dwarf_Word) loc_expr->ex_reloc_offset + len_size;
755 
756     new_attr->ar_nbytes = block_size + len_size;
757 
758     new_attr->ar_next = 0;
759     new_attr->ar_data = block_dest_ptr =
760         (char *) _dwarf_p_get_alloc(dbg, block_size + len_size);
761     if (new_attr->ar_data == NULL) {
762         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
763         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
764     }
765 
766     if (do_len_as_int) {
767         WRITE_UNALIGNED(dbg, block_dest_ptr, (const void *) &block_size,
768                         sizeof(block_size), len_size);
769     } else {
770         /* Is uleb number form, DW_FORM_block. See above. */
771         memcpy(block_dest_ptr, len_str, len_size);
772     }
773     block_dest_ptr += len_size;
774     memcpy(block_dest_ptr, &(loc_expr->ex_byte_stream[0]), block_size);
775 
776     /* add attribute to the die */
777     _dwarf_pro_add_at_to_die(ownerdie, new_attr);
778     return new_attr;
779 }
780 
781 
782 /*
783     This function adds attributes of reference class.
784     The references here are local CU references,
785     not DW_FORM_ref_addr.
786     The offset field is 4 bytes for 32-bit objects,
787     and 8-bytes for 64-bit objects.  Otherdie is the
788     that is referenced by ownerdie.
789 
790     For reference attributes, the ar_data and ar_nbytes
791     are not needed.  Instead, the ar_ref_die points to
792     the other die, and its di_offset value is used as
793     the reference value.
794 */
795 Dwarf_P_Attribute
796 dwarf_add_AT_reference(Dwarf_P_Debug dbg,
797                        Dwarf_P_Die ownerdie,
798                        Dwarf_Half attr,
799                        Dwarf_P_Die otherdie, Dwarf_Error * error)
800 {
801     Dwarf_P_Attribute new_attr;
802 
803     if (dbg == NULL) {
804         _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
805         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
806     }
807 
808     if (ownerdie == NULL) {
809         _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
810         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
811     }
812 
813     if (otherdie == NULL) {
814         _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
815         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
816     }
817 
818     switch (attr) {
819     case DW_AT_specification:
820     case DW_AT_discr:
821     case DW_AT_common_reference:
822     case DW_AT_import:
823     case DW_AT_containing_type:
824     case DW_AT_default_value:
825     case DW_AT_abstract_origin:
826     case DW_AT_friend:
827     case DW_AT_priority:
828     case DW_AT_type:
829     case DW_AT_lower_bound:
830     case DW_AT_upper_bound:
831     case DW_AT_count:
832     case DW_AT_associated:
833     case DW_AT_allocated:
834     case DW_AT_bit_offset:
835     case DW_AT_bit_size:
836     case DW_AT_byte_size:
837     case DW_AT_sibling:
838     case DW_AT_bit_stride:
839     case DW_AT_byte_stride:
840     case DW_AT_namelist_item:
841         break;
842 
843     default:
844         if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
845             _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
846             return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
847         }
848         break;
849     }
850 
851     new_attr = (Dwarf_P_Attribute)
852         _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
853     if (new_attr == NULL) {
854         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
855         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
856     }
857 
858     new_attr->ar_attribute = attr;
859     new_attr->ar_attribute_form = dbg->de_ar_ref_attr_form;
860     new_attr->ar_nbytes = dbg->de_offset_size;
861     new_attr->ar_reloc_len = dbg->de_offset_size;
862     new_attr->ar_ref_die = otherdie;
863     new_attr->ar_rel_type = R_MIPS_NONE;
864     new_attr->ar_next = 0;
865 
866     /* add attribute to the die */
867     _dwarf_pro_add_at_to_die(ownerdie, new_attr);
868     return new_attr;
869 }
870 
871 
872 /*
873     This function adds attributes of the flag class.
874 */
875 Dwarf_P_Attribute
876 dwarf_add_AT_flag(Dwarf_P_Debug dbg,
877                   Dwarf_P_Die ownerdie,
878                   Dwarf_Half attr,
879                   Dwarf_Small flag, Dwarf_Error * error)
880 {
881     Dwarf_P_Attribute new_attr;
882 
883     if (dbg == NULL) {
884         _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
885         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
886     }
887 
888     if (ownerdie == NULL) {
889         _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
890         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
891     }
892 
893 #if 0
894     switch (attr) {
895     case DW_AT_is_optional:
896     case DW_AT_artificial:
897     case DW_AT_declaration:
898     case DW_AT_external:
899     case DW_AT_prototyped:
900     case DW_AT_variable_parameter:
901         break;
902 
903         default:
904             if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
905             _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
906             return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
907         }
908             break;
909     }
910 #endif
911 
912     new_attr = (Dwarf_P_Attribute)
913         _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
914     if (new_attr == NULL) {
915         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
916         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
917     }
918 
919     new_attr->ar_attribute = attr;
920     new_attr->ar_attribute_form = DW_FORM_flag;
921     new_attr->ar_nbytes = 1;
922     new_attr->ar_reloc_len = 0; /* not used */
923     new_attr->ar_rel_type = R_MIPS_NONE;
924     new_attr->ar_next = 0;
925 
926     new_attr->ar_data = (char *)
927         _dwarf_p_get_alloc(dbg, 1);
928     if (new_attr->ar_data == NULL) {
929         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
930         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
931     }
932     memcpy(new_attr->ar_data, &flag, 1);
933 
934     /* add attribute to the die */
935     _dwarf_pro_add_at_to_die(ownerdie, new_attr);
936     return new_attr;
937 }
938 
939 
940 /*
941     This function adds values of attributes
942     belonging to the string class.
943 */
944 Dwarf_P_Attribute
945 dwarf_add_AT_string(Dwarf_P_Debug dbg,
946                     Dwarf_P_Die ownerdie,
947                     Dwarf_Half attr, char *string, Dwarf_Error * error)
948 {
949     Dwarf_P_Attribute new_attr;
950 
951     if (dbg == NULL) {
952         _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
953         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
954     }
955 
956     if (ownerdie == NULL) {
957         _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
958         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
959     }
960 
961     new_attr = (Dwarf_P_Attribute)
962         _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
963     if (new_attr == NULL) {
964         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
965         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
966     }
967 
968     switch (attr) {
969     case DW_AT_name:
970     case DW_AT_comp_dir:
971     case DW_AT_const_value:
972     case DW_AT_producer:
973         break;
974 
975         default:
976             if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
977             _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
978             return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
979         }
980             break;
981     }
982 
983     new_attr->ar_attribute = attr;
984     new_attr->ar_attribute_form = DW_FORM_string;
985     new_attr->ar_nbytes = strlen(string) + 1;
986     new_attr->ar_next = 0;
987 
988     new_attr->ar_data =
989         (char *) _dwarf_p_get_alloc(dbg, strlen(string)+1);
990     if (new_attr->ar_data == NULL) {
991         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
992         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
993     }
994 
995     strcpy(new_attr->ar_data, string);
996     new_attr->ar_rel_type = R_MIPS_NONE;
997     new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */
998 
999     /* add attribute to the die */
1000     _dwarf_pro_add_at_to_die(ownerdie, new_attr);
1001     return new_attr;
1002 }
1003 
1004 
1005 Dwarf_P_Attribute
1006 dwarf_add_AT_const_value_string(Dwarf_P_Die ownerdie,
1007                                 char *string_value, Dwarf_Error * error)
1008 {
1009     Dwarf_P_Attribute new_attr;
1010 
1011     if (ownerdie == NULL) {
1012         _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL);
1013         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
1014     }
1015 
1016     new_attr = (Dwarf_P_Attribute)
1017         _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s));
1018     if (new_attr == NULL) {
1019         _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
1020         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
1021     }
1022 
1023     new_attr->ar_attribute = DW_AT_const_value;
1024     new_attr->ar_attribute_form = DW_FORM_string;
1025     new_attr->ar_nbytes = strlen(string_value) + 1;
1026     new_attr->ar_next = 0;
1027 
1028     new_attr->ar_data =
1029         (char *) _dwarf_p_get_alloc(ownerdie->di_dbg, strlen(string_value)+1);
1030     if (new_attr->ar_data == NULL) {
1031         _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
1032         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
1033     }
1034 
1035     strcpy(new_attr->ar_data, string_value);
1036     new_attr->ar_rel_type = R_MIPS_NONE;
1037     new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */
1038 
1039     /* add attribute to the die */
1040     _dwarf_pro_add_at_to_die(ownerdie, new_attr);
1041     return new_attr;
1042 }
1043 
1044 
1045 Dwarf_P_Attribute
1046 dwarf_add_AT_producer(Dwarf_P_Die ownerdie,
1047                       char *producer_string, Dwarf_Error * error)
1048 {
1049     Dwarf_P_Attribute new_attr;
1050 
1051     if (ownerdie == NULL) {
1052         _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL);
1053         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
1054     }
1055 
1056     new_attr = (Dwarf_P_Attribute)
1057         _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s));
1058     if (new_attr == NULL) {
1059         _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
1060         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
1061     }
1062 
1063     new_attr->ar_attribute = DW_AT_producer;
1064     new_attr->ar_attribute_form = DW_FORM_string;
1065     new_attr->ar_nbytes = strlen(producer_string) + 1;
1066     new_attr->ar_next = 0;
1067 
1068     new_attr->ar_data =
1069         (char *) _dwarf_p_get_alloc(ownerdie->di_dbg, strlen(producer_string)+1);
1070     if (new_attr->ar_data == NULL) {
1071         _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
1072         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
1073     }
1074 
1075     strcpy(new_attr->ar_data, producer_string);
1076     new_attr->ar_rel_type = R_MIPS_NONE;
1077     new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */
1078 
1079     /* add attribute to the die */
1080     _dwarf_pro_add_at_to_die(ownerdie, new_attr);
1081     return new_attr;
1082 }
1083 
1084 
1085 Dwarf_P_Attribute
1086 dwarf_add_AT_const_value_signedint(Dwarf_P_Die ownerdie,
1087                                    Dwarf_Signed signed_value,
1088                                    Dwarf_Error * error)
1089 {
1090     Dwarf_P_Attribute new_attr;
1091     int leb_size;
1092     char encode_buffer[ENCODE_SPACE_NEEDED];
1093     int res;
1094 
1095     if (ownerdie == NULL) {
1096         _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL);
1097         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
1098     }
1099 
1100     new_attr = (Dwarf_P_Attribute)
1101         _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s));
1102     if (new_attr == NULL) {
1103         _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
1104         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
1105     }
1106 
1107     new_attr->ar_attribute = DW_AT_const_value;
1108     new_attr->ar_attribute_form = DW_FORM_sdata;
1109     new_attr->ar_rel_type = R_MIPS_NONE;
1110     new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */
1111     new_attr->ar_next = 0;
1112 
1113     res = _dwarf_pro_encode_signed_leb128_nm(signed_value, &leb_size,
1114                                              encode_buffer,
1115                                              sizeof(encode_buffer));
1116     if (res != DW_DLV_OK) {
1117         _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
1118         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
1119     }
1120     new_attr->ar_data = (char *)
1121         _dwarf_p_get_alloc(ownerdie->di_dbg, leb_size);
1122     if (new_attr->ar_data == NULL) {
1123         _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
1124         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
1125     }
1126     memcpy(new_attr->ar_data, encode_buffer, leb_size);
1127     new_attr->ar_nbytes = leb_size;
1128 
1129     /* add attribute to the die */
1130     _dwarf_pro_add_at_to_die(ownerdie, new_attr);
1131     return new_attr;
1132 }
1133 
1134 
1135 Dwarf_P_Attribute
1136 dwarf_add_AT_const_value_unsignedint(Dwarf_P_Die ownerdie,
1137                                      Dwarf_Unsigned unsigned_value,
1138                                      Dwarf_Error * error)
1139 {
1140     Dwarf_P_Attribute new_attr;
1141     int leb_size;
1142     char encode_buffer[ENCODE_SPACE_NEEDED];
1143     int res;
1144 
1145     if (ownerdie == NULL) {
1146         _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL);
1147         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
1148     }
1149 
1150     new_attr = (Dwarf_P_Attribute)
1151         _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s));
1152     if (new_attr == NULL) {
1153         _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
1154         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
1155     }
1156 
1157     new_attr->ar_attribute = DW_AT_const_value;
1158     new_attr->ar_attribute_form = DW_FORM_udata;
1159     new_attr->ar_rel_type = R_MIPS_NONE;
1160     new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */
1161     new_attr->ar_next = 0;
1162 
1163     res = _dwarf_pro_encode_leb128_nm(unsigned_value, &leb_size,
1164                                       encode_buffer,
1165                                       sizeof(encode_buffer));
1166     if (res != DW_DLV_OK) {
1167         _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
1168         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
1169     }
1170     new_attr->ar_data = (char *)
1171         _dwarf_p_get_alloc(ownerdie->di_dbg, leb_size);
1172     if (new_attr->ar_data == NULL) {
1173         _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
1174         return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
1175     }
1176     memcpy(new_attr->ar_data, encode_buffer, leb_size);
1177     new_attr->ar_nbytes = leb_size;
1178 
1179     /* add attribute to the die */
1180     _dwarf_pro_add_at_to_die(ownerdie, new_attr);
1181     return new_attr;
1182 }
1183