xref: /illumos-gate/usr/src/lib/libdwarf/common/pro_init.c (revision 4d9fdb46b215739778ebc12079842c9905586999)
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 2008-2017 David Anderson, Inc. All rights reserved.
5   Portions Copyright 2012 SN Systems Ltd. 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 #include <string.h>
36 #include <stddef.h>
37 #ifdef HAVE_STDINT_H
38 #include <stdint.h> /* For uintptr_t */
39 #endif /* HAVE_STDINT_H */
40 #include "pro_incl.h"
41 #include "dwarf.h"
42 #include "libdwarf.h"
43 #include "pro_opaque.h"
44 #include "pro_error.h"
45 #include "pro_encode_nm.h"
46 #include "pro_alloc.h"
47 #include "pro_line.h"
48 #include "memcpy_swap.h"
49 #include "pro_section.h"        /* for MAGIC_SECT_NO */
50 #include "pro_reloc_symbolic.h"
51 #include "pro_reloc_stream.h"
52 #include "dwarf_tsearch.h"
53 #include "dwarfstring.h"
54 
55 #define IS_64BITPTR(dbg) ((dbg)->de_flags & DW_DLC_POINTER64 ? 1 : 0)
56 #define ISA_IA64(dbg) ((dbg)->de_flags & DW_DLC_ISA_IA64 ? 1 : 0)
57 
58 struct isa_relocs_s {
59    const char *name_;
60    int         reloc32_;
61    int         reloc64_;
62    int         segrel_; /* only used if IRIX */
63 };
64 
65 #ifndef TRUE
66 #define TRUE 1
67 #endif /*TRUE*/
68 #ifndef FALSE
69 #define FALSE 0
70 #endif /*FALSE*/
71 
72 /*  Some of these may be the wrong relocation for DWARF
73     relocations. FIXME. Most will be unusable without
74     additional effort as they have not been tested.
75 */
76 #ifndef	R_MIPS_32
77 #define R_MIPS_32		2
78 #endif
79 #ifndef	R_MIPS_64
80 #define R_MIPS_64		18
81 #endif
82 #ifndef R_MIPS_SCN_DISP
83 #define R_MIPS_SCN_DISP		32
84 #endif
85 #ifndef	R_386_32
86 #define R_386_32                 1
87 #endif
88 #ifndef	R_386_64
89 #define R_386_64                 0  /* impossible */
90 #endif
91 #ifndef	R_X86_64_32
92 #define R_X86_64_32             10
93 #endif
94 #ifndef R_X86_64_64
95 #define R_X86_64_64              1
96 #endif
97 #ifndef	R_SPARC_UA32
98 #define R_SPARC_UA32            23
99 #endif
100 #ifndef	R_SPARC_UA64
101 #define R_SPARC_UA64            54
102 #endif
103 #ifndef	R_ARM_ABS32
104 #define R_ARM_ABS32              2
105 #endif
106 #ifndef	R_ARM_ABS64
107 #define R_ARM_ABS64              0 /* impossible */
108 #endif
109 #ifndef	R_AARCH64_ABS32
110 #define R_AARCH64_ABS32        258
111 #endif
112 #ifndef	R_AARCH64_ABS64
113 #define R_AARCH64_ABS64        257
114 #endif
115 #ifndef	R_IA64_DIR32LSB
116 #define R_IA64_DIR32LSB       0x25
117 #endif
118 #ifndef	R_IA64_DIR64LSB
119 #define R_IA64_DIR64LSB       0x27
120 #endif
121 #ifndef	R_PPC_REL32
122 #define R_PPC_REL32             26
123 #endif
124 #ifndef	R_PPC_REL64
125 #define R_PPC_REL64             44
126 #endif
127 #ifndef	R_PPC64_REL32
128 #define R_PPC64_REL32         R_PPC_REL32
129 #endif
130 #ifndef	R_PPC64_REL64
131 #define R_PPC64_REL64           44
132 #endif
133 
134 static struct isa_relocs_s isa_relocs[] = {
135 {"irix",  R_MIPS_32,R_MIPS_64,R_MIPS_SCN_DISP},
136 {"mips",  R_MIPS_32,R_MIPS_64,0},
137 {"x86",   R_386_32, R_386_64,0},
138 {"x86_64",R_X86_64_32,R_X86_64_64,0},
139 {"ia64",  R_IA64_DIR32LSB,R_IA64_DIR64LSB,0},
140 {"arm64", R_AARCH64_ABS32,R_AARCH64_ABS64,0},
141 {"arm",   R_ARM_ABS32,R_ARM_ABS64,0},
142 {"ppc",   R_PPC_REL32,R_PPC_REL64,0},
143 {"ppc64", R_PPC64_REL32,R_PPC64_REL64,0},
144 {"sparc", R_SPARC_UA32,R_SPARC_UA64,0},
145 /*  The last entry MUST be all zeros. */
146 {0,0,0,0}
147 };
148 
149 
150 static int common_init(Dwarf_P_Debug dbg, Dwarf_Unsigned flags,
151     const char *abiname, const char *dwarf_version,
152     const char *extrainfo,
153     int *error_ret);
154 
155 /*  This function sets up a new dwarf producing region.
156     flags: Indicates type of access method, one of DW_DLC* macros
157     func(): Used to create a new object file, a call back function
158     errhand(): Error Handler provided by user
159     errarg: Argument to errhand()
160     error: returned error value */
161     /*  We want the following to have an elf section number that matches
162         'nothing' */
163 static struct Dwarf_P_Section_Data_s init_sect = {
164     MAGIC_SECT_NO, 0, 0, 0, 0
165 };
166 static struct Dwarf_P_Section_Data_s init_sect_debug_str = {
167     MAGIC_SECT_NO, 0, 0, 0, 0
168 };
169 static struct Dwarf_P_Section_Data_s init_sect_debug_line_str = {
170     MAGIC_SECT_NO, 0, 0, 0, 0
171 };
172 
173 /*  New April 2014.
174     Replaces all previous producer init functions.
175     It adds a string to select the relevant ABI/ISA and
176     a string defining the selected DWARF version to
177     output.
178     There are some overlaps between the flags and the ISA/ABI
179     string choices. ( it is neither strictly ABI nor strictly
180     ISA name, but a useful name for both.)
181     Generally, the function inteprets these
182     in a tolerant fashion, so inconsistencies in the
183     selections are not noticed...but they may have a surprising
184     effect.
185 
186     The extra string is a way to allow new options without
187     changing the interface. The idea is the caller might
188     supply a list of such things as one string, comma-separated.
189     The interface is not intended to allow spaces or tabs in the
190     names, so don't do that  :-)
191     If no extra strings are needed (none are defined initially)
192     then pass a NULL pointer or an empty string as the 'extra'
193     parameter.
194     */
195 int
dwarf_producer_init(Dwarf_Unsigned flags,Dwarf_Callback_Func func,Dwarf_Handler errhand,Dwarf_Ptr errarg,void * user_data,const char * isa_name,const char * dwarf_version,const char * extra,Dwarf_P_Debug * dbg_returned,Dwarf_Error * error)196 dwarf_producer_init(Dwarf_Unsigned flags,
197     Dwarf_Callback_Func func,
198     Dwarf_Handler errhand,
199     Dwarf_Ptr errarg,
200     void * user_data,
201     const char *isa_name, /* See isa_reloc_s. */
202     const char *dwarf_version, /* V2 V3 V4 or V5. */
203     const char *extra, /* Extra input strings, comma separated. */
204     Dwarf_P_Debug *dbg_returned,
205     Dwarf_Error * error)
206 {
207     Dwarf_P_Debug dbg = 0;
208     int res = 0;
209     int err_ret = 0;
210     dbg = (Dwarf_P_Debug) _dwarf_p_get_alloc(NULL,
211         sizeof(struct Dwarf_P_Debug_s));
212     if (dbg == NULL) {
213         DWARF_P_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC,
214             DW_DLV_ERROR);
215     }
216     memset((void *) dbg, 0, sizeof(struct Dwarf_P_Debug_s));
217     /* For the time being */
218     if (func == NULL) {
219         DWARF_P_DBG_ERROR(dbg, DW_DLE_NO_CALLBACK_FUNC,
220             DW_DLV_ERROR);
221     }
222     dbg->de_callback_func = func;
223     dbg->de_errhand = errhand;
224     dbg->de_errarg = errarg;
225     dbg->de_user_data = user_data;
226     res = common_init(dbg, flags,isa_name,dwarf_version,
227         extra,&err_ret);
228     if (res != DW_DLV_OK) {
229         DWARF_P_DBG_ERROR(dbg, err_ret, DW_DLV_ERROR);
230     }
231     *dbg_returned = dbg;
232     return DW_DLV_OK;
233 }
234 
235 int
dwarf_pro_set_default_string_form(Dwarf_P_Debug dbg,int form,UNUSEDARG Dwarf_Error * error)236 dwarf_pro_set_default_string_form(Dwarf_P_Debug dbg,
237    int form,
238    UNUSEDARG Dwarf_Error * error)
239 {
240     if (form != DW_FORM_string &&
241         form != DW_FORM_strp) {
242         _dwarf_p_error(dbg, error, DW_DLE_BAD_STRING_FORM);
243         return DW_DLV_ERROR;
244     }
245     dbg->de_debug_default_str_form = form;
246     return DW_DLV_OK;
247 }
248 
249 static int
set_reloc_numbers(Dwarf_P_Debug dbg,UNUSEDARG Dwarf_Unsigned flags,const char * abiname)250 set_reloc_numbers(Dwarf_P_Debug dbg,
251     UNUSEDARG Dwarf_Unsigned flags,
252     const char *abiname)
253 {
254     struct isa_relocs_s *isap = 0;
255     if (!abiname) {
256         return DW_DLV_NO_ENTRY;
257     }
258     for(isap = &isa_relocs[0];  ;isap++) {
259         if (!isap->name_) {
260             /* No more names known. Never found the one we wanted. */
261             return DW_DLV_NO_ENTRY;
262         }
263         if (!strcmp(abiname,isap->name_)) {
264             if (dbg->de_pointer_size == 4) {
265                 dbg->de_ptr_reloc = isap->reloc32_;
266             } else {
267                 dbg->de_ptr_reloc = isap->reloc64_;
268             }
269             if (dbg->de_dwarf_offset_size == 4) {
270                 dbg->de_offset_reloc = isap->reloc32_;
271             } else {
272                 dbg->de_offset_reloc = isap->reloc64_;
273             }
274             /*  segrel only meaningful for IRIX, otherwise
275                 harmless, unused. */
276             dbg->de_exc_reloc = isap->segrel_;
277             return DW_DLV_OK;
278         }
279     }
280     /* UNREACHED */
281 }
282 
283 /*  This is the Daniel J Bernstein hash function
284     originally posted to Usenet news.
285     http://en.wikipedia.org/wiki/List_of_hash_functions or
286     http://stackoverflow.com/questions/10696223/reason-for-5381-number-in-djb-hash-function).
287     See Also DWARF5 Section 7.33
288 */
289 static DW_TSHASHTYPE
_dwarf_string_hashfunc(const char * str)290 _dwarf_string_hashfunc(const char *str)
291 {
292     DW_TSHASHTYPE up = 0;
293     DW_TSHASHTYPE hash = 5381;
294     int c  = 0;
295 
296     /*  Extra parens suppress warning about assign in test. */
297     while ((c = *str++)) {
298         hash = hash * 33 + c ;
299     }
300     up = hash;
301     return up;
302 }
303 static DW_TSHASHTYPE
key_simple_string_hashfunc(const void * keyp)304 key_simple_string_hashfunc(const void *keyp)
305 {
306     struct Dwarf_P_debug_str_entry_s* mt =
307         (struct Dwarf_P_debug_str_entry_s*) keyp;
308     const char *str = 0;
309 
310     if (mt->dse_has_table_offset) {
311         /*  ASSERT: mt->dse_dbg->de_debug_str->ds_data not zero. */
312         str = (const char *)mt->dse_dbg->de_debug_str->ds_data +
313             mt->dse_table_offset;
314     } else {
315         /*  ASSERT: dse_name != 0 */
316         str = (const char *)mt->dse_name;
317     }
318     return _dwarf_string_hashfunc(str);
319 }
320 
321 
322 static int
common_init(Dwarf_P_Debug dbg,Dwarf_Unsigned flags,const char * abiname,const char * dwarf_version,const char * extra,int * err_ret)323 common_init(Dwarf_P_Debug dbg,
324     Dwarf_Unsigned flags,
325     const char *abiname,
326     const char *dwarf_version,
327     const char *extra,
328     int *err_ret)
329 {
330     unsigned int k = 0;
331     int res = 0;
332 
333     dbg->de_version_magic_number = PRO_VERSION_MAGIC;
334     dbg->de_n_debug_sect = 0;
335     dbg->de_debug_sects = &init_sect;
336     dbg->de_debug_str = &init_sect_debug_str;
337     dbg->de_debug_line_str = &init_sect_debug_line_str;
338     dbg->de_current_active_section = &init_sect;
339     dbg->de_flags = flags;
340 
341 
342     /* DW_DLC_POINTER32 assumed. */
343     dbg->de_pointer_size = 4;
344     /* Standard DWARF 64bit offset, length field 12 bytes */
345     dbg->de_dwarf_offset_size = 4;
346     dbg->de_elf_offset_size = 4;
347     dbg->de_64bit_extension = 0;
348 
349     dbg->de_big_endian = (dbg->de_flags&DW_DLC_TARGET_BIGENDIAN)?
350         TRUE:FALSE;
351     /*  DW_DLC_POINTER64 is identical to DW_DLC_SIZE_64 */
352     if(dbg->de_flags & DW_DLC_POINTER64) {
353         dbg->de_pointer_size = 8;
354     }
355     if(dbg->de_flags & DW_DLC_OFFSET64) {
356         dbg->de_pointer_size = 8;
357         dbg->de_dwarf_offset_size = 4;
358         dbg->de_64bit_extension = 0;
359         /*  When dwarf_offset_size == 8 then for
360             standard dwarf set
361             de_64bit_extension to 1. */
362         dbg->de_elf_offset_size = 8;
363     } else {
364         if(dbg->de_flags & DW_DLC_IRIX_OFFSET64) {
365             dbg->de_pointer_size = 8;
366             dbg->de_big_endian = TRUE;
367             dbg->de_dwarf_offset_size = 8;
368             dbg->de_64bit_extension = 0;
369             dbg->de_elf_offset_size = 8;
370         }
371     }
372 
373     if(abiname && (!strcmp(abiname,"irix"))) {
374         dbg->de_irix_exc_augmentation = 1;
375     } else {
376         dbg->de_irix_exc_augmentation = 0;
377     }
378     /*  We must set reloc numbers even if doing symbolic
379         relocations because we use the numbers up until
380         we are generating debug.  A zero is interpreted
381         as no relocations.  So ensure we have real
382         relocations. */
383     res = set_reloc_numbers(dbg,flags,abiname);
384     if (res != DW_DLV_OK) {
385         *err_ret = DW_DLE_BAD_ABINAME;
386         return DW_DLV_ERROR;
387     }
388     dbg->de_output_version = 2;
389     if(dwarf_version) {
390         if (!strcmp(dwarf_version,"V2")) {
391             dbg->de_output_version = 2;
392         } else if (!strcmp(dwarf_version,"V3")) {
393             dbg->de_output_version = 3;
394         } else if (!strcmp(dwarf_version,"V4")) {
395             dbg->de_output_version = 4;
396         } else if (!strcmp(dwarf_version,"V5")) {
397             dbg->de_output_version = 5;
398         } else {
399             *err_ret = DW_DLE_VERSION_STAMP_ERROR;
400             return DW_DLV_ERROR;
401         }
402     }
403     _dwarf_init_default_line_header_vals(dbg);
404     res = _dwarf_log_extra_flagstrings(dbg,extra,err_ret);
405     if (res == DW_DLV_ERROR) {
406         return res;
407     }
408 
409     if (flags & DW_DLC_SYMBOLIC_RELOCATIONS) {
410         dbg->de_relocation_record_size =
411             sizeof(struct Dwarf_Relocation_Data_s);
412     } else {
413         /*  This is only going to work when the HOST == TARGET,
414             surely? */
415 #ifdef DWARF_WITH_LIBELF
416 #if HAVE_ELF64_GETEHDR
417         dbg->de_relocation_record_size =
418             ((dbg->de_pointer_size == 8)?
419             sizeof(REL64) : sizeof(REL32));
420 #else
421         dbg->de_relocation_record_size = sizeof(REL32);
422 #endif
423 #else /* DWARF_WITH_LIBELF */
424         *err_ret = DW_DLE_NO_STREAM_RELOC_SUPPORT;
425         return DW_DLV_ERROR;
426 #endif /* DWARF_WITH_LIBELF */
427     }
428 
429     /* For .debug_str creation. */
430     dwarf_initialize_search_hash(&dbg->de_debug_str_hashtab,
431         key_simple_string_hashfunc,0);
432     dbg->de_debug_default_str_form = DW_FORM_string;
433     dwarf_initialize_search_hash(&dbg->de_debug_line_str_hashtab,
434         key_simple_string_hashfunc,0);
435 
436     if (dbg->de_dwarf_offset_size == 8) {
437         if (dbg->de_output_version <= 3) {
438             dbg->de_ar_data_attribute_form = DW_FORM_data8;
439         } else {
440             dbg->de_ar_data_attribute_form = DW_FORM_sec_offset;
441         }
442         dbg->de_ar_ref_attr_form = DW_FORM_ref8;
443     } else {
444         if (dbg->de_output_version <= 3) {
445             dbg->de_ar_data_attribute_form = DW_FORM_data4;
446         } else {
447             dbg->de_ar_data_attribute_form = DW_FORM_sec_offset;
448         }
449         dbg->de_ar_ref_attr_form = DW_FORM_ref4;
450     }
451 
452     if (flags & DW_DLC_SYMBOLIC_RELOCATIONS) {
453         dbg->de_relocate_by_name_symbol =
454             _dwarf_pro_reloc_name_symbolic;
455         dbg->de_relocate_pair_by_symbol =
456             _dwarf_pro_reloc_length_symbolic;
457         dbg->de_transform_relocs_to_disk =
458             _dwarf_symbolic_relocs_to_disk;
459     } else {
460 #ifdef DWARF_WITH_LIBELF
461         if (IS_64BITPTR(dbg)) {
462             dbg->de_relocate_by_name_symbol =
463                 _dwarf_pro_reloc_name_stream64;
464         } else {
465             dbg->de_relocate_by_name_symbol =
466                 _dwarf_pro_reloc_name_stream32;
467         }
468         dbg->de_relocate_pair_by_symbol = 0;
469         dbg->de_transform_relocs_to_disk = _dwarf_stream_relocs_to_disk;
470 #else /* DWARF_WITH_LIBELF */
471         *err_ret = DW_DLE_NO_STREAM_RELOC_SUPPORT;
472         return DW_DLV_ERROR;
473 #endif /* DWARF_WITH_LIBELF */
474     }
475     for (k = 0; k < NUM_DEBUG_SECTIONS; ++k) {
476 
477         Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[k];
478 
479         prel->pr_slots_per_block_to_alloc = DEFAULT_SLOTS_PER_BLOCK;
480     }
481     /* First assume host, target same endianness  FIXME */
482     dbg->de_same_endian = 1;
483     dbg->de_copy_word =  _dwarf_memcpy_noswap_bytes;
484 #ifdef WORDS_BIGENDIAN
485     /* host is big endian, so what endian is target? */
486     if (flags & DW_DLC_TARGET_LITTLEENDIAN) {
487         dbg->de_same_endian = 0;
488         dbg->de_copy_word = _dwarf_memcpy_swap_bytes;
489     }
490 #else /* little endian */
491     /* host is little endian, so what endian is target? */
492     if (flags & DW_DLC_TARGET_BIGENDIAN) {
493         dbg->de_same_endian = 0;
494         dbg->de_copy_word = _dwarf_memcpy_swap_bytes;
495     }
496 #endif /* !WORDS_BIGENDIAN */
497     return DW_DLV_OK;
498 }
499