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