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   Portions Copyright 2011-2017 David Anderson.  All Rights Reserved.
6 
7   This program is free software; you can redistribute it
8   and/or modify it under the terms of version 2.1 of the
9   GNU Lesser General Public License as published by the Free
10   Software Foundation.
11 
12   This program is distributed in the hope that it would be
13   useful, but WITHOUT ANY WARRANTY; without even the implied
14   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15   PURPOSE.
16 
17   Further, this software is distributed without any warranty
18   that it is free of the rightful claim of any third person
19   regarding infringement or the like.  Any license provided
20   herein, whether implied or otherwise, applies only to this
21   software file.  Patent licenses, if any, provided herein
22   do not apply to combinations of this program with other
23   software, or any other product whatsoever.
24 
25   You should have received a copy of the GNU Lesser General
26   Public License along with this program; if not, write the
27   Free Software Foundation, Inc., 51 Franklin Street - Fifth
28   Floor, Boston MA 02110-1301, USA.
29 
30 */
31 
32 #include "config.h"
33 #include "libdwarfdefs.h"
34 #include <stdio.h>
35 #ifdef HAVE_STDLIB_H
36 #include <stdlib.h> /* for exit(), C89 malloc */
37 #endif /* HAVE_STDLIB_H */
38 #ifdef HAVE_MALLOC_H
39 /* Useful include for some Windows compilers. */
40 #include <malloc.h>
41 #endif /* HAVE_MALLOC_H */
42 #ifdef HAVE_STDINT_H
43 #include <stdint.h> /* For uintptr_t */
44 #endif /* HAVE_STDINT_H */
45 #include <string.h>
46 #include <stddef.h>
47 #include "pro_incl.h"
48 #include "dwarf.h"
49 #include "libdwarf.h"
50 #include "pro_opaque.h"
51 #include "pro_error.h"
52 #include "pro_util.h"
53 #include "pro_alloc.h"
54 #include "pro_die.h"
55 #include "pro_section.h"
56 #include "dwarf_tsearch.h"
57 
58 #ifndef R_MIPS_NONE
59 #define R_MIPS_NONE 0
60 #endif
61 
62 #define TRUE 1
63 #define FALSE 0
64 
65 /*  This function creates a new die.
66     tag: tag of the new die to be created
67     parent,child,left,right: specify neighbors of the new die. Only
68     one of these may be non-null */
69 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)70 dwarf_new_die(Dwarf_P_Debug dbg,
71     Dwarf_Tag tag,
72     Dwarf_P_Die parent,
73     Dwarf_P_Die child,
74     Dwarf_P_Die left, Dwarf_P_Die right,
75     Dwarf_Error * error)
76 {
77     Dwarf_P_Die created = 0;
78     int res = 0;
79 
80     res = dwarf_new_die_a(dbg,tag,parent,child,
81         left,right,&created,error);
82     if (res != DW_DLV_OK) {
83         return (Dwarf_P_Die)DW_DLV_BADADDR;
84     }
85     return created;
86 }
87 
88 /* New September 2016. Preferred as error checking
89    is easier, no need for ugly cast. */
90 int
dwarf_new_die_a(Dwarf_P_Debug dbg,Dwarf_Tag tag,Dwarf_P_Die parent,Dwarf_P_Die child,Dwarf_P_Die left,Dwarf_P_Die right,Dwarf_P_Die * die_out,Dwarf_Error * error)91 dwarf_new_die_a(Dwarf_P_Debug dbg,
92     Dwarf_Tag tag,
93     Dwarf_P_Die parent,
94     Dwarf_P_Die child,
95     Dwarf_P_Die left, Dwarf_P_Die right,
96     Dwarf_P_Die *die_out,
97     Dwarf_Error *error)
98 {
99     Dwarf_P_Die ret_die = 0;
100     int res = 0;
101 
102     ret_die = (Dwarf_P_Die)
103         _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Die_s));
104     if (ret_die == NULL) {
105         DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_ALLOC,
106             DW_DLV_ERROR);
107     }
108     ret_die->di_parent = NULL;
109     ret_die->di_left = NULL;
110     ret_die->di_right = NULL;
111     ret_die->di_child = NULL;
112     ret_die->di_last_child = NULL;
113     ret_die->di_tag = tag;
114     ret_die->di_dbg = dbg;
115     ret_die->di_marker = 0;
116     res = dwarf_die_link_a(ret_die, parent, child, left, right,
117         error);
118     if (res != DW_DLV_OK) {
119         _dwarf_p_dealloc(dbg,(Dwarf_Small *)ret_die);
120         ret_die = 0;
121     } else {
122         *die_out = ret_die;
123     }
124     return res;
125 }
126 
127 /*  This function links up a die to specified neighbors
128     parent,child,left,right: specify neighbors of the new die. Only
129     one of these may be non-null
130     This is the original version. Use dwarf_die_link_a()
131     instead as that function is easier to use (in checking for error).
132     */
133 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)134 dwarf_die_link(Dwarf_P_Die new_die,
135     Dwarf_P_Die parent,
136     Dwarf_P_Die child,
137     Dwarf_P_Die left, Dwarf_P_Die right, Dwarf_Error * error)
138 {
139     int res = 0;
140 
141     res = dwarf_die_link_a(new_die,parent,child,left,right,error);
142     if (res != DW_DLV_OK) {
143         return (Dwarf_P_Die)DW_DLV_BADADDR;
144     }
145     return new_die;
146 }
147 
148 /*  New September 2016.
149     Error return easier to deal with
150     than dwarf_die_link(). */
151 int
dwarf_die_link_a(Dwarf_P_Die new_die,Dwarf_P_Die parent,Dwarf_P_Die child,Dwarf_P_Die left,Dwarf_P_Die right,Dwarf_Error * error)152 dwarf_die_link_a(Dwarf_P_Die new_die,
153     Dwarf_P_Die parent,
154     Dwarf_P_Die child,
155     Dwarf_P_Die left, Dwarf_P_Die right, Dwarf_Error * error)
156 {
157     /* Count the # of non null neighbors. */
158     int n_nulls = 0;
159 
160     if (parent != NULL) {
161         n_nulls++;
162         if (new_die->di_parent != NULL) {
163             DWARF_P_DBG_ERROR(NULL, DW_DLE_LINK_LOOP,
164                 DW_DLV_ERROR);
165         }
166         new_die->di_parent = parent;
167         if (parent->di_child) {
168 
169             /*  di_last_child identifies the last sibling, the
170                 die we want to attach new_die to. */
171             /*  ASSERT: if di_child is set so is di_last_child. */
172             Dwarf_P_Die former_lastchild = parent->di_last_child;
173             parent->di_last_child = new_die;
174             /* Attach to  the new die to end of the sibling list. */
175             former_lastchild->di_right = new_die;
176             new_die->di_left = former_lastchild;
177         } else {
178             parent->di_child = new_die;
179             parent->di_last_child = new_die;
180         }
181     }
182     if (child != NULL) {
183         n_nulls++;
184         new_die->di_child = child;
185         new_die->di_last_child = child;
186         if (child->di_parent) {
187             DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS,
188                 DW_DLV_ERROR);
189         } else {
190             child->di_parent = new_die;
191         }
192     }
193     if (left != NULL) {
194         n_nulls++;
195         new_die->di_left = left;
196         if (left->di_right) {
197             /*  There's already a right sibling of left,
198                 insert the new die in the list. */
199             new_die->di_right = left->di_right;
200             left->di_right->di_left = new_die;
201         }
202         left->di_right = new_die;
203         if (new_die->di_parent) {
204             DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS,
205                 DW_DLV_ERROR);
206         } else {
207             new_die->di_parent = left->di_parent;
208         }
209     }
210     if (right != NULL) {
211         n_nulls++;
212         new_die->di_right = right;
213         if (right->di_left) {
214             /*  There is already a left sibling of the right die,
215                 insert the new die in the list.  */
216             new_die->di_left = right->di_left;
217             right->di_left->di_right = new_die;
218         }
219         right->di_left = new_die;
220         if (new_die->di_parent) {
221             DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS,
222                 DW_DLV_ERROR);
223         } else {
224             new_die->di_parent = right->di_parent;
225         }
226     }
227     if (n_nulls > 1) {
228         /* Multiple neighbors! error! */
229         DWARF_P_DBG_ERROR(NULL, DW_DLE_EXTRA_NEIGHBORS,
230             DW_DLV_ERROR);
231     }
232     return DW_DLV_OK;
233 }
234 
235 Dwarf_Unsigned
dwarf_add_die_marker(Dwarf_P_Debug dbg,Dwarf_P_Die die,Dwarf_Unsigned marker,Dwarf_Error * error)236 dwarf_add_die_marker(Dwarf_P_Debug dbg,
237     Dwarf_P_Die die,
238     Dwarf_Unsigned marker,
239     Dwarf_Error * error) {
240     if (die == NULL) {
241         DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, DW_DLV_NOCOUNT);
242     }
243     die->di_marker = marker;
244     return 0;
245 }
246 int
dwarf_add_die_marker_a(Dwarf_P_Debug dbg,Dwarf_P_Die die,Dwarf_Unsigned marker,Dwarf_Error * error)247 dwarf_add_die_marker_a(Dwarf_P_Debug dbg,
248     Dwarf_P_Die die,
249     Dwarf_Unsigned marker,
250     Dwarf_Error * error)
251 {
252     if (die == NULL) {
253         DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL,
254             DW_DLV_ERROR);
255     }
256     die->di_marker = marker;
257     return DW_DLV_OK;
258 }
259 
260 
261 Dwarf_Unsigned
dwarf_get_die_marker(Dwarf_P_Debug dbg,Dwarf_P_Die die,Dwarf_Unsigned * marker,Dwarf_Error * error)262 dwarf_get_die_marker(Dwarf_P_Debug dbg,
263     Dwarf_P_Die die,
264     Dwarf_Unsigned * marker,
265     Dwarf_Error * error)
266 {
267     if (die == NULL) {
268         DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL,
269             DW_DLV_NOCOUNT);
270     }
271     *marker = die->di_marker;
272     return 0;
273 }
274 int
dwarf_get_die_marker_a(Dwarf_P_Debug dbg,Dwarf_P_Die die,Dwarf_Unsigned * marker,Dwarf_Error * error)275 dwarf_get_die_marker_a(Dwarf_P_Debug dbg,
276     Dwarf_P_Die die,
277     Dwarf_Unsigned * marker,
278     Dwarf_Error * error)
279 {
280     if (die == NULL) {
281         DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL,
282             DW_DLV_ERROR);
283     }
284     *marker = die->di_marker;
285     return DW_DLV_ERROR;
286 }
287 
288 
289 /*---------------------------------------------------------
290     This function adds a die to dbg struct. It should
291     be called using the root of all the dies.
292 ---------------------------------------------------------*/
293 /*  Original form of this call..
294     dwarf_add_die_to_debug_a() is preferred now. */
295 Dwarf_Unsigned
dwarf_add_die_to_debug(Dwarf_P_Debug dbg,Dwarf_P_Die first_die,Dwarf_Error * error)296 dwarf_add_die_to_debug(Dwarf_P_Debug dbg,
297     Dwarf_P_Die first_die, Dwarf_Error * error)
298 {
299     int res = dwarf_add_die_to_debug_a(dbg,first_die,error);
300     if (res == DW_DLV_ERROR) {
301         return DW_DLV_NOCOUNT;
302     }
303     return 0;
304 }
305 
306 /*  New September 2016. The new and preferred form. */
307 int
dwarf_add_die_to_debug_a(Dwarf_P_Debug dbg,Dwarf_P_Die first_die,Dwarf_Error * error)308 dwarf_add_die_to_debug_a(Dwarf_P_Debug dbg,
309     Dwarf_P_Die first_die, Dwarf_Error * error)
310 {
311     if (first_die == NULL) {
312         DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL,
313             DW_DLV_ERROR);
314     }
315     if (first_die->di_tag != DW_TAG_compile_unit) {
316         DWARF_P_DBG_ERROR(dbg, DW_DLE_WRONG_TAG,
317             DW_DLV_ERROR);
318     }
319     dbg->de_dies = first_die;
320     return DW_DLV_OK;
321 }
322 
323 int
_dwarf_pro_add_AT_stmt_list(Dwarf_P_Debug dbg,Dwarf_P_Die first_die,Dwarf_Error * error)324 _dwarf_pro_add_AT_stmt_list(Dwarf_P_Debug dbg,
325     Dwarf_P_Die first_die, Dwarf_Error * error)
326 {
327     Dwarf_P_Attribute new_attr;
328     int uwordb_size = dbg->de_dwarf_offset_size;
329 
330     /* Add AT_stmt_list attribute */
331     new_attr = (Dwarf_P_Attribute)
332         _dwarf_p_get_alloc(dbg,
333             sizeof(struct Dwarf_P_Attribute_s));
334     if (new_attr == NULL) {
335         DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC,
336             DW_DLV_ERROR);
337     }
338 
339     new_attr->ar_attribute = DW_AT_stmt_list;
340     new_attr->ar_attribute_form =
341         dbg->de_ar_data_attribute_form;
342     new_attr->ar_rel_type = dbg->de_offset_reloc;
343 
344     new_attr->ar_nbytes = uwordb_size;
345     new_attr->ar_next = NULL;
346     new_attr->ar_reloc_len = uwordb_size;
347     new_attr->ar_data = (char *)
348         _dwarf_p_get_alloc(dbg, uwordb_size);
349     if (new_attr->ar_data == NULL) {
350         DWARF_P_DBG_ERROR(NULL,DW_DLE_ADDR_ALLOC,
351             DW_DLV_ERROR);
352     }
353     {
354         Dwarf_Unsigned du = 0;
355 
356         WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data,
357             (const void *) &du, sizeof(du), uwordb_size);
358     }
359 
360     _dwarf_pro_add_at_to_die(first_die, new_attr);
361     return DW_DLV_OK;
362 }
363 
364 static int
_dwarf_debug_str_compare_func(const void * l,const void * r)365 _dwarf_debug_str_compare_func(const void *l,const void *r)
366 {
367     const struct Dwarf_P_debug_str_entry_s*el = l;
368     const struct Dwarf_P_debug_str_entry_s*er = r;
369     char *lname =  0;
370     char *rname =  0;
371     int ir = 0;
372 
373     if (el->dse_has_table_offset) {
374         /*  When set the name is in the debug_str table. */
375         /*  ASSERT: dse_dbg->de_debug_str->ds_data
376             is non-zero.
377             ASSERT: dse_name NULL. */
378         lname = el->dse_dbg->de_debug_str->ds_data +
379             el->dse_table_offset;
380     } else {
381         /*  ASSERT: dse_name non-null */
382         lname = el->dse_name;
383     }
384     if (er->dse_has_table_offset) {
385         /*  When set the name is in the debug_str table. */
386         /*  ASSERT: dse_dbg->de_debug_str->ds_data
387             is non-zero.
388             ASSERT: dse_name NULL. */
389         rname = er->dse_dbg->de_debug_str->ds_data +
390             er->dse_table_offset;
391     } else {
392         /*  ASSERT: dse_name non-null */
393         rname = er->dse_name;
394     }
395     ir = strcmp(lname,rname);
396     return ir;
397 }
398 
399 static  void
debug_str_entry_free_func(void * m)400 debug_str_entry_free_func(void *m)
401 {
402     free(m);
403 }
404 
405 static int
make_debug_str_entry(Dwarf_P_Debug dbg,struct Dwarf_P_debug_str_entry_s ** mt_out,char * name,unsigned slen,unsigned char has_offset,Dwarf_Unsigned offset_in_table,Dwarf_Error * error)406 make_debug_str_entry(Dwarf_P_Debug dbg,
407     struct Dwarf_P_debug_str_entry_s **mt_out,
408     char *name,
409     unsigned slen,
410     unsigned char has_offset,
411     Dwarf_Unsigned offset_in_table,
412     Dwarf_Error *error)
413 {
414     struct Dwarf_P_debug_str_entry_s *mt =
415         (struct  Dwarf_P_debug_str_entry_s *)calloc(
416         sizeof(struct Dwarf_P_debug_str_entry_s),1);
417     if (!mt) {
418         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
419         return DW_DLV_ERROR;
420     }
421 
422     mt->dse_slen = slen;
423     mt->dse_table_offset = 0;
424     mt->dse_dbg = dbg;
425     if (has_offset) {
426         mt->dse_has_table_offset = TRUE;
427         mt->dse_table_offset = offset_in_table;
428         mt->dse_name = 0;
429     } else {
430         /* ASSERT: name != NULL */
431         mt->dse_has_table_offset = FALSE;
432         /* We just set dse_table_offset so it has
433             a known value, though nothing should refer
434             to dse_table_offset because
435             dse_has_table_offset is FALSE.*/
436         mt->dse_table_offset = 0;
437         mt->dse_name = name;
438     }
439     *mt_out = mt;
440     return DW_DLV_OK;
441 }
442 #define STRTAB_BASE_ALLOC_SIZE 2048
443 static int
insert_debug_str_data_string(Dwarf_P_Debug dbg,char * name,unsigned slen,Dwarf_P_Section_Data sd,Dwarf_Unsigned * adding_at_offset,Dwarf_Error * error)444 insert_debug_str_data_string(Dwarf_P_Debug dbg,
445     char *name,
446     unsigned slen,
447     Dwarf_P_Section_Data sd,
448     Dwarf_Unsigned*adding_at_offset,
449     Dwarf_Error *  error)
450 {
451     Dwarf_Unsigned current_offset = 0;
452 
453     if (!sd->ds_data) {
454         Dwarf_Unsigned initial_alloc = STRTAB_BASE_ALLOC_SIZE;
455         Dwarf_Unsigned base_insert_offset = 0;
456 
457         /*  Inserting our first string.
458             The GNU linker refuses to commonize strings
459             if the section starts with a NUL byte,
460             so start with real string, using a
461             base_insert_offset of 0. */
462         if ( (slen + base_insert_offset) >= STRTAB_BASE_ALLOC_SIZE) {
463             initial_alloc = slen *2+ base_insert_offset;
464         }
465         if (initial_alloc < slen) {
466             _dwarf_p_error(dbg, error, DW_DLE_SIZE_WRAPAROUND);
467             return DW_DLV_ERROR;
468         }
469         sd->ds_data = calloc(1,initial_alloc);
470         if (!sd->ds_data) {
471             _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
472             return DW_DLV_ERROR;
473         }
474         sd->ds_orig_alloc = initial_alloc;
475         *adding_at_offset = base_insert_offset;
476         sd->ds_nbytes = slen + base_insert_offset;
477         strcpy(sd->ds_data+base_insert_offset,name);
478         return DW_DLV_OK;
479     }
480     current_offset = sd->ds_nbytes;
481     if ( (current_offset + slen) >= sd->ds_orig_alloc) {
482         unsigned updated_length = sd->ds_orig_alloc;
483         char *newbuf = 0;
484         if (slen > updated_length) {
485             /*  Very long string passed in. */
486             updated_length = slen *2;
487         } else {
488             updated_length = updated_length *2;
489         }
490         if (updated_length < sd->ds_orig_alloc) {
491             _dwarf_p_error(dbg, error, DW_DLE_SIZE_WRAPAROUND);
492             return DW_DLV_ERROR;
493         }
494         newbuf = calloc(1,updated_length);
495         if (!newbuf) {
496             _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
497             return DW_DLV_ERROR;
498         }
499         memcpy(newbuf,sd->ds_data,sd->ds_nbytes);
500         free(sd->ds_data);
501         sd->ds_data = newbuf;
502         sd->ds_orig_alloc = updated_length;
503         newbuf = 0;
504     }
505     strcpy(sd->ds_data + current_offset,name);
506     sd->ds_nbytes += slen;
507     *adding_at_offset = current_offset;
508     return DW_DLV_OK;
509 }
510 
511 /*  Find the string offset using the hash table,
512     and if not known, insert the new string. */
513 int
_dwarf_insert_or_find_in_debug_str(Dwarf_P_Debug dbg,char * name,enum dwarf_which_hash whash,unsigned slen,Dwarf_Unsigned * offset_in_debug_str,Dwarf_Error * error)514 _dwarf_insert_or_find_in_debug_str(Dwarf_P_Debug dbg,
515     char *name,
516     enum dwarf_which_hash whash,
517     unsigned slen, /* includes space for trailing NUL */
518     Dwarf_Unsigned *offset_in_debug_str,
519     Dwarf_Error *error)
520 {
521     struct Dwarf_P_debug_str_entry_s *mt = 0;
522     struct Dwarf_P_debug_str_entry_s *mt2 = 0;
523     struct Dwarf_P_debug_str_entry_s *retval = 0;
524     struct Dwarf_P_debug_str_entry_s *re = 0;
525     int res = 0;
526     Dwarf_Unsigned adding_at_offset = 0;
527     void **hashtab = 0;
528     Dwarf_P_Section_Data sd = 0;
529     struct Dwarf_P_Str_stats_s * stats =  0;
530 
531     switch (whash) {
532     case _dwarf_hash_debug_str:
533         hashtab =  &dbg->de_debug_str_hashtab;
534         sd =  dbg->de_debug_str;
535         stats = &dbg->de_stats.ps_strp;
536         break;
537     case _dwarf_hash_debug_line_str:
538         hashtab =  &dbg->de_debug_line_str_hashtab;
539         sd =  dbg->de_debug_line_str;
540         stats = &dbg->de_stats.ps_line_strp;
541         break;
542     case _dwarf_hash_debug_str_sup:
543     default:
544         /* Not supported or unknown. */
545         _dwarf_p_error(dbg, error, DW_DLE_STRING_HASHTAB_IDENTITY_ERROR);
546         return DW_DLV_ERROR;
547     }
548     res = make_debug_str_entry(dbg,&mt,name,
549         slen,FALSE, 0, error);
550     if (res != DW_DLV_OK) {
551         return res;
552     }
553     /*  We do a find as we do not want the string pointer passed in
554         to be in the hash table, we want a pointer into the
555         debug_str table in the hash table. */
556     retval = dwarf_tfind(mt,(void *const*)hashtab,
557         _dwarf_debug_str_compare_func);
558     if (retval) {
559 
560         stats->ps_strp_reused_count++;
561         stats->ps_strp_reused_len += slen;
562 
563         re = *(struct Dwarf_P_debug_str_entry_s **)retval;
564         *offset_in_debug_str = re->dse_table_offset;
565         debug_str_entry_free_func(mt);
566         return DW_DLV_OK;
567     }
568 
569     /*  We know the string is not in .debug_str data yet.
570         Insert it into the big string table and get that
571         offset. */
572 
573     debug_str_entry_free_func(mt);
574     mt = 0;
575     res = insert_debug_str_data_string(dbg,name,slen,sd,
576         &adding_at_offset, error);
577     if (res != DW_DLV_OK) {
578         return res;
579     }
580 
581     /*  The name is in the string table itself, so use that pointer
582         and offset for the string. */
583     res = make_debug_str_entry(dbg,&mt2, 0,
584         slen,TRUE,adding_at_offset,error);
585     if (res != DW_DLV_OK) {
586         return res;
587     }
588     retval = dwarf_tsearch(mt2,
589         (void *)hashtab,
590         _dwarf_debug_str_compare_func);
591     if (!retval) {
592         debug_str_entry_free_func(mt2);
593         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
594         return DW_DLV_ERROR;
595     }
596 
597     /* This indirection is one of the surprises in using tsearch... */
598     re = *(struct Dwarf_P_debug_str_entry_s **)retval;
599     if (re != mt2) {
600         debug_str_entry_free_func(mt2);
601         /*  Found it in hash tab: illogical as the tsearch_find should
602             have found it. */
603         _dwarf_p_error(dbg, error, DW_DLE_ILLOGICAL_TSEARCH);
604         return DW_DLV_ERROR;
605     }
606     stats->ps_strp_count_debug_str++;
607     stats->ps_strp_len_debug_str += slen;
608     /* we added it to hash, do not free mt2 (which == re). */
609     *offset_in_debug_str = re->dse_table_offset;
610     return DW_DLV_OK;
611 }
612 
613 /*  Returns DW_DLV_OK or DW_DLV_ERROR. */
_dwarf_pro_set_string_attr(Dwarf_P_Attribute new_attr,Dwarf_P_Debug dbg,char * name,Dwarf_Error * error)614 int _dwarf_pro_set_string_attr(Dwarf_P_Attribute new_attr,
615     Dwarf_P_Debug dbg,
616     char *name,
617     Dwarf_Error *error)
618 {
619     int form = dbg->de_debug_default_str_form;
620     unsigned slen = strlen(name)+1;
621 
622     if (form == DW_FORM_string ||
623         slen <= dbg->de_dwarf_offset_size) {
624         new_attr->ar_nbytes = slen;
625         new_attr->ar_next = 0;
626 
627         new_attr->ar_data =
628             (char *) _dwarf_p_get_alloc(dbg, slen);
629         if (new_attr->ar_data == NULL) {
630             _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
631             return DW_DLV_ERROR;
632         }
633         dbg->de_stats.ps_str_count++;
634         dbg->de_stats.ps_str_total_length += slen;
635 
636         strcpy(new_attr->ar_data, name);
637         new_attr->ar_attribute_form = DW_FORM_string;
638         new_attr->ar_rel_type = R_MIPS_NONE;
639         new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */
640         return DW_DLV_OK;
641     }
642     if (form == DW_FORM_strp) {
643         int uwordb_size = dbg->de_dwarf_offset_size;
644         Dwarf_Unsigned offset_in_debug_str = 0;
645         int res = 0;
646 
647         res = _dwarf_insert_or_find_in_debug_str(dbg,name,
648             _dwarf_hash_debug_str,slen,
649             &offset_in_debug_str,error);
650         if(res != DW_DLV_OK) {
651             return res;
652         }
653         new_attr->ar_attribute_form = form;
654         new_attr->ar_rel_type = dbg->de_offset_reloc;
655         new_attr->ar_nbytes = uwordb_size;
656         new_attr->ar_next = NULL;
657         new_attr->ar_reloc_len = uwordb_size;
658         /*  During transform to disk
659             a symbol index will be applied. */
660         new_attr->ar_data = (char *)
661             _dwarf_p_get_alloc(dbg, uwordb_size);
662         if (new_attr->ar_data == NULL) {
663             _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
664             return DW_DLV_ERROR;
665         }
666         {
667             Dwarf_Unsigned du = offset_in_debug_str;
668 
669             WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data,
670                 (const void *) &du, sizeof(du), uwordb_size);
671         }
672 
673         return DW_DLV_OK;
674     }
675     _dwarf_p_error(dbg, error, DW_DLE_BAD_STRING_FORM);
676     return DW_DLV_ERROR;
677 
678 }
679 
680 
681 /*-------------------------------------------------------------------
682     Add AT_name attribute to die
683 ---------------------------------------------------------------------*/
684 /*  Original function. dwarf_add_AT_name_a() is the
685     suggested alternative. */
686 Dwarf_P_Attribute
dwarf_add_AT_name(Dwarf_P_Die die,char * name,Dwarf_Error * error)687 dwarf_add_AT_name(Dwarf_P_Die die,
688     char *name,
689     Dwarf_Error * error)
690 {
691     Dwarf_P_Attribute a = 0;
692     int res = 0;
693 
694     res = dwarf_add_AT_name_a(die, name,
695         &a, error);
696     if (res == DW_DLV_ERROR) {
697         return (Dwarf_P_Attribute)(DW_DLV_BADADDR);
698     }
699     return a;
700 }
701 
702 /*   New December 2018.  */
703 int
dwarf_add_AT_name_a(Dwarf_P_Die die,char * name,Dwarf_P_Attribute * newattr_out,Dwarf_Error * error)704 dwarf_add_AT_name_a(Dwarf_P_Die die, char *name,
705     Dwarf_P_Attribute *newattr_out,
706     Dwarf_Error * error)
707 {
708     Dwarf_P_Attribute new_attr = 0;
709     int res = 0;
710 
711     if (die == NULL) {
712         DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL,
713             DW_DLV_ERROR);
714     }
715     new_attr = (Dwarf_P_Attribute)
716         _dwarf_p_get_alloc(die->di_dbg,
717             sizeof(struct Dwarf_P_Attribute_s));
718     if (new_attr == NULL) {
719         DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC,
720             DW_DLV_ERROR);
721     }
722 
723     /* fill in the information */
724     new_attr->ar_attribute = DW_AT_name;
725     res = _dwarf_pro_set_string_attr(new_attr,die->di_dbg,name,error);
726     if (res != DW_DLV_OK) {
727         return DW_DLV_ERROR;
728     }
729 
730     /* add attribute to the die */
731     _dwarf_pro_add_at_to_die(die, new_attr);
732     *newattr_out = new_attr;
733     return DW_DLV_OK;
734 }
735 
736 
737 /*--------------------------------------------------------------------
738     Add AT_comp_dir attribute to die
739 --------------------------------------------------------------------*/
740 Dwarf_P_Attribute
dwarf_add_AT_comp_dir(Dwarf_P_Die ownerdie,char * current_working_directory,Dwarf_Error * error)741 dwarf_add_AT_comp_dir(Dwarf_P_Die ownerdie,
742     char *current_working_directory,
743     Dwarf_Error * error)
744 {
745     Dwarf_P_Attribute a = 0;
746     int res = 0;
747 
748     res = dwarf_add_AT_comp_dir_a(ownerdie,
749         current_working_directory,
750         &a, error);
751     if (res != DW_DLV_OK) {
752         return (Dwarf_P_Attribute)(DW_DLV_BADADDR);
753     }
754     return a;
755 }
756 
757 int
dwarf_add_AT_comp_dir_a(Dwarf_P_Die ownerdie,char * current_working_directory,Dwarf_P_Attribute * attr_out,Dwarf_Error * error)758 dwarf_add_AT_comp_dir_a(Dwarf_P_Die ownerdie,
759     char *current_working_directory,
760     Dwarf_P_Attribute *attr_out,
761     Dwarf_Error * error)
762 {
763     Dwarf_P_Attribute new_attr = 0;
764     int res = 0;
765 
766     if (ownerdie == NULL) {
767         DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL,
768             DW_DLV_ERROR);
769     }
770     new_attr = (Dwarf_P_Attribute)
771         _dwarf_p_get_alloc(ownerdie->di_dbg,
772         sizeof(struct Dwarf_P_Attribute_s));
773     if (new_attr == NULL) {
774         DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC,
775             DW_DLV_ERROR);
776     }
777 
778     /* fill in the information */
779     new_attr->ar_attribute = DW_AT_comp_dir;
780     res = _dwarf_pro_set_string_attr(new_attr,ownerdie->di_dbg,
781         current_working_directory,error);
782     if (res != DW_DLV_OK) {
783         return res;
784     }
785 
786     /* add attribute to the die */
787     _dwarf_pro_add_at_to_die(ownerdie, new_attr);
788     *attr_out = new_attr;
789     return DW_DLV_OK;
790 }
791 
792 
793 int
_dwarf_pro_add_AT_fde(Dwarf_P_Debug dbg,Dwarf_P_Die die,Dwarf_Unsigned offset,Dwarf_Error * error)794 _dwarf_pro_add_AT_fde(Dwarf_P_Debug dbg,
795     Dwarf_P_Die die,
796     Dwarf_Unsigned offset, Dwarf_Error * error)
797 {
798     Dwarf_P_Attribute new_attr;
799     int uwordb_size = dbg->de_dwarf_offset_size;
800 
801     if (die == NULL) {
802         DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, DW_DLV_ERROR);
803     }
804     new_attr = (Dwarf_P_Attribute)
805         _dwarf_p_get_alloc(dbg,sizeof(struct Dwarf_P_Attribute_s));
806     if (new_attr == NULL) {
807         DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, DW_DLV_ERROR);
808     }
809 
810     /* fill in the information */
811     new_attr->ar_attribute = DW_AT_MIPS_fde;
812     new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form;
813     new_attr->ar_rel_type = dbg->de_offset_reloc;
814     new_attr->ar_nbytes = uwordb_size;
815     new_attr->ar_next = NULL;
816     new_attr->ar_reloc_len = uwordb_size;
817     new_attr->ar_data = (char *)
818         _dwarf_p_get_alloc(dbg, uwordb_size);
819     if (new_attr->ar_data == NULL) {
820         DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_ERROR);
821     }
822     {
823         Dwarf_Unsigned du = offset;
824 
825         WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data,
826             (const void *) &du, sizeof(du), uwordb_size);
827     }
828     _dwarf_pro_add_at_to_die(die, new_attr);
829     return DW_DLV_OK;
830 }
831 
832 /* Sept 2016: returns DW_DLV_OK or DW_DLV_ERROR */
833 int
_dwarf_pro_add_AT_macro_info(Dwarf_P_Debug dbg,Dwarf_P_Die die,Dwarf_Unsigned offset,Dwarf_Error * error)834 _dwarf_pro_add_AT_macro_info(Dwarf_P_Debug dbg,
835     Dwarf_P_Die die,
836     Dwarf_Unsigned offset, Dwarf_Error * error)
837 {
838     Dwarf_P_Attribute new_attr;
839     int uwordb_size = dbg->de_dwarf_offset_size;
840 
841     if (die == NULL) {
842         DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, DW_DLV_ERROR);
843     }
844     new_attr = (Dwarf_P_Attribute)
845         _dwarf_p_get_alloc(dbg,sizeof(struct Dwarf_P_Attribute_s));
846     if (new_attr == NULL) {
847         DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, DW_DLV_ERROR);
848     }
849 
850     /* fill in the information */
851     new_attr->ar_attribute = DW_AT_macro_info;
852     new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form;
853     new_attr->ar_rel_type = dbg->de_offset_reloc;
854 
855     new_attr->ar_nbytes = uwordb_size;
856     new_attr->ar_next = NULL;
857     new_attr->ar_reloc_len = uwordb_size;
858     new_attr->ar_data = (char *)
859         _dwarf_p_get_alloc(dbg, uwordb_size);
860     if (new_attr->ar_data == NULL) {
861         DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_ERROR);
862     }
863     {
864         Dwarf_Unsigned du = offset;
865 
866         WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data,
867             (const void *) &du, sizeof(du), uwordb_size);
868     }
869 
870     _dwarf_pro_add_at_to_die(die, new_attr);
871 
872     return DW_DLV_OK;
873 }
874 
875 
876 /*  Updates the list of attributes on this Dwarf_P_Die
877 */
878 void
_dwarf_pro_add_at_to_die(Dwarf_P_Die die,Dwarf_P_Attribute attr)879 _dwarf_pro_add_at_to_die(Dwarf_P_Die die, Dwarf_P_Attribute attr)
880 {
881     if (die->di_last_attr) {
882         /* Inserts new attr at the end */
883         die->di_last_attr->ar_next = attr;
884         die->di_last_attr = attr;
885         die->di_n_attr++;
886     } else {
887         die->di_n_attr = 1;
888         die->di_attrs = die->di_last_attr = attr;
889     }
890 }
891