xref: /illumos-gate/usr/src/lib/libdwarf/common/dwarf_init_finish.c (revision 069e6b7e31ba5dcbc5441b98af272714d9a5455c)
1 /*
2 
3   Copyright (C) 2000,2002,2003,2004,2005 Silicon Graphics, Inc. All Rights Reserved.
4   Portions Copyright (C) 2008-2010 Arxan Technologies, Inc. All Rights Reserved.
5   Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved.
6 
7   This program is free software; you can redistribute it and/or modify it
8   under the terms of version 2.1 of the GNU Lesser General Public License
9   as published by the Free Software Foundation.
10 
11   This program is distributed in the hope that it would be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 
15   Further, this software is distributed without any warranty that it is
16   free of the rightful claim of any third person regarding infringement
17   or the like.  Any license provided herein, whether implied or
18   otherwise, applies only to this software file.  Patent licenses, if
19   any, provided herein do not apply to combinations of this program with
20   other software, or any other product whatsoever.
21 
22   You should have received a copy of the GNU Lesser General Public
23   License along with this program; if not, write the Free Software
24   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
25   USA.
26 
27   Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
28   Mountain View, CA 94043, or:
29 
30   http://www.sgi.com
31 
32   For further information regarding this notice, see:
33 
34   http://oss.sgi.com/projects/GenInfo/NoticeExplan
35 
36 */
37 
38 #include "config.h"
39 #include "dwarf_incl.h"
40 
41 #include <stdio.h>
42 #include <sys/stat.h>
43 #include <sys/types.h>
44 #include <string.h>
45 #include <stdlib.h>
46 
47 #include "dwarf_incl.h"
48 #include "malloc_check.h"
49 
50 #define DWARF_DBG_ERROR(dbg,errval,retval) \
51      _dwarf_error(dbg, error, errval); return(retval);
52 
53 #define FALSE 0
54 #define TRUE  1
55 
56 
57 
58 /* This static is copied to the dbg on dbg init
59    so that the static need not be referenced at
60    run time, preserving better locality of
61    reference.
62    Value is 0 means do the string check.
63    Value non-zero means do not do the check.
64 */
65 static Dwarf_Small _dwarf_assume_string_bad;
66 static Dwarf_Small _dwarf_apply_relocs = 1;
67 
68 /* Call this after calling dwarf_init but before doing anything else.
69  * It applies to all objects, not just the current object.
70  */
71 int
72 dwarf_set_reloc_application(int apply)
73 {
74     int oldval = _dwarf_apply_relocs;
75     _dwarf_apply_relocs = apply;
76     return oldval;
77 }
78 
79 int
80 dwarf_set_stringcheck(int newval)
81 {
82     int oldval = _dwarf_assume_string_bad;
83 
84     _dwarf_assume_string_bad = newval;
85     return oldval;
86 }
87 
88 /* Unifies the basic duplicate/empty testing and section
89  * data setting to one place. */
90 static int
91 get_basic_section_data(Dwarf_Debug dbg,
92     struct Dwarf_Section_s *secdata,
93     struct Dwarf_Obj_Access_Section_s *doas,
94     Dwarf_Half section_index,
95     Dwarf_Error* error,
96     int duperr, int emptyerr )
97 {
98     if (secdata->dss_index != 0) {
99         DWARF_DBG_ERROR(dbg, duperr, DW_DLV_ERROR);
100     }
101     if (doas->size == 0) {
102         if (emptyerr == 0 ) {
103             /* Allow empty section. */
104             return DW_DLV_OK;
105         }
106         /* Know no reason to allow section */
107         DWARF_DBG_ERROR(dbg, emptyerr, DW_DLV_ERROR);
108     }
109     secdata->dss_index = section_index;
110     secdata->dss_size = doas->size;
111     secdata->dss_addr = doas->addr;
112     secdata->dss_link = doas->link;
113     return DW_DLV_OK;
114 }
115 
116 
117 static void
118 add_rela_data( struct Dwarf_Section_s *secdata,
119     struct Dwarf_Obj_Access_Section_s *doas,
120     Dwarf_Half section_index)
121 {
122     secdata->dss_reloc_index = section_index;
123     secdata->dss_reloc_size = doas->size;
124     secdata->dss_reloc_addr = doas->addr;
125     secdata->dss_reloc_symtab = doas->link;
126     secdata->dss_reloc_link = doas->link;
127 }
128 
129 /*
130     Given an Elf ptr, set up dbg with pointers
131     to all the Dwarf data sections.
132     Return NULL on error.
133 
134     This function is also responsible for determining
135     whether the given object contains Dwarf information
136     or not.  The test currently used is that it contains
137     either a .debug_info or a .debug_frame section.  If
138     not, it returns DW_DLV_NO_ENTRY causing dwarf_init() also to
139     return DW_DLV_NO_ENTRY.  Earlier, we had thought of using only
140     the presence/absence of .debug_info to test, but we
141     added .debug_frame since there could be stripped objects
142     that have only a .debug_frame section for exception
143     processing.
144     DW_DLV_NO_ENTRY or DW_DLV_OK or DW_DLV_ERROR
145 */
146 static int
147 _dwarf_setup(Dwarf_Debug dbg, Dwarf_Error * error)
148 {
149     const char *scn_name = 0;
150     int foundDwarf = 0;
151     struct Dwarf_Obj_Access_Interface_s * obj = 0;
152 
153     Dwarf_Endianness endianness;
154 
155     Dwarf_Unsigned section_size = 0;
156     Dwarf_Unsigned section_count = 0;
157     Dwarf_Half section_index = 0;
158     Dwarf_Addr section_addr = 0;
159 
160     foundDwarf = FALSE;
161 
162     dbg->de_assume_string_in_bounds = _dwarf_assume_string_bad;
163 
164     dbg->de_same_endian = 1;
165     dbg->de_copy_word = memcpy;
166     obj = dbg->de_obj_file;
167     endianness = obj->methods->get_byte_order(obj->object);
168 #ifdef WORDS_BIGENDIAN
169     dbg->de_big_endian_object = 1;
170     if (endianness == DW_OBJECT_LSB ) {
171         dbg->de_same_endian = 0;
172         dbg->de_big_endian_object = 0;
173         dbg->de_copy_word = _dwarf_memcpy_swap_bytes;
174     }
175 #else /* little endian */
176     dbg->de_big_endian_object = 0;
177     if (endianness == DW_OBJECT_MSB ) {
178         dbg->de_same_endian = 0;
179         dbg->de_big_endian_object = 1;
180         dbg->de_copy_word = _dwarf_memcpy_swap_bytes;
181     }
182 #endif /* !WORDS_BIGENDIAN */
183 
184 
185     /* The following de_length_size is Not Too Significant. Only used
186        one calculation, and an approximate one at that. */
187     dbg->de_length_size = obj->methods->get_length_size(obj->object);
188     dbg->de_pointer_size = obj->methods->get_pointer_size(obj->object);
189 
190     section_count = obj->methods->get_section_count(obj->object);
191 
192     /* We can skip index 0 when considering ELF files, but not other
193        object types. */
194     for (section_index = 0; section_index < section_count;
195          ++section_index) {
196 
197         struct Dwarf_Obj_Access_Section_s doas;
198         int res = DW_DLV_ERROR;
199         int err;
200 
201         res = obj->methods->get_section_info(obj->object,
202                                              section_index,
203                                              &doas, &err);
204         if(res == DW_DLV_ERROR){
205           DWARF_DBG_ERROR(dbg, err, DW_DLV_ERROR);
206         }
207 
208         section_addr = doas.addr;
209         section_size = doas.size;
210         scn_name = doas.name;
211 
212         if (strncmp(scn_name, ".debug_", 7)
213             && strcmp(scn_name, ".eh_frame")
214             && strcmp(scn_name, ".symtab")
215             && strcmp(scn_name, ".strtab")
216             && strncmp(scn_name, ".rela.",6))  {
217             continue;
218         }
219         else if (strcmp(scn_name, ".debug_info") == 0) {
220             res = get_basic_section_data(dbg,&dbg->de_debug_info, &doas,
221                   section_index,error,
222                   DW_DLE_DEBUG_INFO_DUPLICATE,DW_DLE_DEBUG_INFO_NULL);
223             if(res != DW_DLV_OK) {
224                   return res;
225             }
226             foundDwarf = TRUE;
227         }
228         else if (strcmp(scn_name, ".debug_abbrev") == 0) {
229             res = get_basic_section_data(dbg,&dbg->de_debug_abbrev, &doas,
230                   section_index,error,
231                   DW_DLE_DEBUG_ABBREV_DUPLICATE,DW_DLE_DEBUG_ABBREV_NULL);
232             if(res != DW_DLV_OK) {
233                   return res;
234             }
235         }
236         else if (strcmp(scn_name, ".debug_aranges") == 0) {
237             res = get_basic_section_data(dbg,&dbg->de_debug_aranges, &doas,
238                   section_index,error,
239                   DW_DLE_DEBUG_ARANGES_DUPLICATE,0);
240             if(res != DW_DLV_OK) {
241                   return res;
242             }
243         }
244 
245         else if (strcmp(scn_name, ".debug_line") == 0) {
246             res = get_basic_section_data(dbg,&dbg->de_debug_line, &doas,
247                   section_index,error,
248                   DW_DLE_DEBUG_LINE_DUPLICATE,0);
249             if(res != DW_DLV_OK) {
250                   return res;
251             }
252         }
253         else if (strcmp(scn_name, ".debug_frame") == 0) {
254             res = get_basic_section_data(dbg,&dbg->de_debug_frame, &doas,
255                   section_index,error,
256                   DW_DLE_DEBUG_FRAME_DUPLICATE,0);
257             if(res != DW_DLV_OK) {
258                   return res;
259             }
260             foundDwarf = TRUE;
261         } else if (strcmp(scn_name, ".eh_frame") == 0) {
262             /* gnu egcs-1.1.2 data */
263             res = get_basic_section_data(dbg,&dbg->de_debug_frame_eh_gnu, &doas,
264                   section_index,error,
265                   DW_DLE_DEBUG_FRAME_DUPLICATE,0);
266             if(res != DW_DLV_OK) {
267                   return res;
268             }
269             foundDwarf = TRUE;
270         }
271         else if (strcmp(scn_name, ".debug_loc") == 0) {
272             res = get_basic_section_data(dbg,&dbg->de_debug_loc, &doas,
273                   section_index,error,
274                   DW_DLE_DEBUG_LOC_DUPLICATE,0);
275             if(res != DW_DLV_OK) {
276                   return res;
277             }
278         }
279         else if (strcmp(scn_name, ".debug_pubnames") == 0) {
280             res = get_basic_section_data(dbg,&dbg->de_debug_pubnames, &doas,
281                   section_index,error,
282                   DW_DLE_DEBUG_PUBNAMES_DUPLICATE,0);
283             if(res != DW_DLV_OK) {
284                   return res;
285             }
286         }
287 
288         else if (strcmp(scn_name, ".debug_str") == 0) {
289             res = get_basic_section_data(dbg,&dbg->de_debug_str, &doas,
290                   section_index,error,
291                   DW_DLE_DEBUG_STR_DUPLICATE,0);
292             if(res != DW_DLV_OK) {
293                   return res;
294             }
295         }
296         else if (strcmp(scn_name, ".debug_funcnames") == 0) {
297             /* SGI IRIX-only. */
298             res = get_basic_section_data(dbg,&dbg->de_debug_funcnames, &doas,
299                   section_index,error,
300                   DW_DLE_DEBUG_FUNCNAMES_DUPLICATE,0);
301             if(res != DW_DLV_OK) {
302                   return res;
303             }
304         }
305         else if (strcmp(scn_name, ".debug_typenames") == 0) {
306             /* SGI IRIX-only, created years before DWARF3. Content
307                essentially identical to .debug_pubtypes.  */
308             res = get_basic_section_data(dbg,&dbg->de_debug_typenames, &doas,
309                   section_index,error,
310                   DW_DLE_DEBUG_TYPENAMES_DUPLICATE,0);
311             if(res != DW_DLV_OK) {
312                   return res;
313             }
314         } else if (strcmp(scn_name, ".debug_pubtypes") == 0) {
315             /* Section new in DWARF3.  */
316             res = get_basic_section_data(dbg,&dbg->de_debug_pubtypes, &doas,
317                   section_index,error,
318                   DW_DLE_DEBUG_PUBTYPES_DUPLICATE,0);
319             if(res != DW_DLV_OK) {
320                   return res;
321             }
322         }
323         else if (strcmp(scn_name, ".debug_varnames") == 0) {
324             /* SGI IRIX-only.  */
325             res = get_basic_section_data(dbg,&dbg->de_debug_varnames, &doas,
326                   section_index,error,
327                   DW_DLE_DEBUG_VARNAMES_DUPLICATE,0);
328             if(res != DW_DLV_OK) {
329                   return res;
330             }
331         }
332         else if (strcmp(scn_name, ".debug_weaknames") == 0) {
333             /* SGI IRIX-only. */
334             res = get_basic_section_data(dbg,&dbg->de_debug_weaknames, &doas,
335                   section_index,error,
336                   DW_DLE_DEBUG_WEAKNAMES_DUPLICATE,0);
337             if(res != DW_DLV_OK) {
338                   return res;
339             }
340         } else if (strcmp(scn_name, ".debug_macinfo") == 0) {
341             res = get_basic_section_data(dbg,&dbg->de_debug_macinfo, &doas,
342                   section_index,error,
343                   DW_DLE_DEBUG_MACINFO_DUPLICATE,0);
344             if(res != DW_DLV_OK) {
345                   return res;
346             }
347         }
348         else if (strcmp(scn_name, ".debug_ranges") == 0) {
349             res = get_basic_section_data(dbg,&dbg->de_debug_ranges, &doas,
350                   section_index,error,
351                   DW_DLE_DEBUG_RANGES_DUPLICATE,0);
352             if(res != DW_DLV_OK) {
353                   return res;
354             }
355             foundDwarf = TRUE;
356         }
357         else if (strcmp(scn_name, ".symtab") == 0) {
358             res = get_basic_section_data(dbg,&dbg->de_elf_symtab, &doas,
359                   section_index,error,
360                   DW_DLE_DEBUG_SYMTAB_ERR,0);
361             if(res != DW_DLV_OK) {
362                   return res;
363             }
364         }
365         else if (strcmp(scn_name, ".strtab")  == 0) {
366             res = get_basic_section_data(dbg,&dbg->de_elf_strtab, &doas,
367                   section_index,error,
368                   DW_DLE_DEBUG_STRTAB_ERR,0);
369             if(res != DW_DLV_OK) {
370                   return res;
371             }
372         }
373         else if (strncmp(scn_name, ".rela.debug_",12) == 0) {
374             const char *rcn_name = scn_name + 5;
375             if (strcmp(rcn_name, ".debug_info") == 0) {
376                 add_rela_data(&dbg->de_debug_info,&doas,section_index);
377             } else if (strcmp(rcn_name, ".debug_abbrev") == 0) {
378                 add_rela_data(&dbg->de_debug_abbrev,&doas,section_index);
379             } else if (strcmp(rcn_name, ".debug_aranges") == 0) {
380                 add_rela_data(&dbg->de_debug_aranges,&doas,section_index);
381             } else if (strcmp(rcn_name, ".debug_line") == 0) {
382                 add_rela_data(&dbg->de_debug_line,&doas,section_index);
383             } else if (strcmp(rcn_name, ".debug_frame") == 0) {
384                 add_rela_data(&dbg->de_debug_frame,&doas,section_index);
385             } else if (strcmp(rcn_name, ".eh_frame") == 0) {
386                 add_rela_data(&dbg->de_debug_frame_eh_gnu,&doas,section_index);
387             } else if (strcmp(rcn_name, ".debug_loc") == 0) {
388                 add_rela_data(&dbg->de_debug_loc,&doas,section_index);
389             } else if (strcmp(rcn_name, ".debug_pubnames") == 0) {
390                 add_rela_data(&dbg->de_debug_pubnames,&doas,section_index);
391             } else if (strcmp(rcn_name, ".debug_str") == 0) {
392                 add_rela_data(&dbg->de_debug_str,&doas,section_index);
393             } else if (strcmp(rcn_name, ".debug_funcnames") == 0) {
394                 add_rela_data(&dbg->de_debug_funcnames,&doas,section_index);
395             } else if (strcmp(rcn_name, ".debug_typenames") == 0) {
396                 add_rela_data(&dbg->de_debug_typenames,&doas,section_index);
397             } else if (strcmp(rcn_name, ".debug_pubtypes") == 0) {
398                 add_rela_data(&dbg->de_debug_pubtypes,&doas,section_index);
399             } else if (strcmp(rcn_name, ".debug_varnames") == 0) {
400                 add_rela_data(&dbg->de_debug_varnames,&doas,section_index);
401             } else if (strcmp(rcn_name, ".debug_weaknames") == 0) {
402                 add_rela_data(&dbg->de_debug_weaknames,&doas,section_index);
403             } else if (strcmp(rcn_name, ".debug_macinfo") == 0) {
404                 add_rela_data(&dbg->de_debug_macinfo,&doas,section_index);
405             }
406         }
407     }
408     if (foundDwarf) {
409         return DW_DLV_OK;
410     }
411     return DW_DLV_NO_ENTRY;
412 }
413 
414 
415 /*
416     Use a Dwarf_Obj_Access_Interface to kick things off. All other
417     init routines eventually use this one.
418     The returned Dwarf_Debug contains a copy of *obj
419     the callers copy of *obj may be freed whenever the caller
420     wishes.
421 */
422 int
423 dwarf_object_init(Dwarf_Obj_Access_Interface* obj, Dwarf_Handler errhand,
424                Dwarf_Ptr errarg, Dwarf_Debug* ret_dbg,
425                Dwarf_Error* error)
426 {
427     Dwarf_Debug dbg = 0;
428     int setup_result = DW_DLV_OK;
429 
430     dbg = _dwarf_get_debug();
431     if (dbg == NULL) {
432         DWARF_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, DW_DLV_ERROR);
433     }
434     dbg->de_errhand = errhand;
435     dbg->de_errarg = errarg;
436     dbg->de_frame_rule_initial_value = DW_FRAME_REG_INITIAL_VALUE;
437     dbg->de_frame_reg_rules_entry_count = DW_FRAME_LAST_REG_NUM;
438 #ifdef HAVE_OLD_FRAME_CFA_COL
439     /* DW_FRAME_CFA_COL is really only suitable for old libdwarf frame
440        interfaces and its value of 0 there is only usable where
441        (as in MIPS) register 0 has no value other than 0 so
442        we can use the frame table column 0 for the CFA value
443        (and rely on client software to know when 'register 0'
444        is the cfa and when to just use a value 0 for register 0).
445     */
446     dbg->de_frame_cfa_col_number = DW_FRAME_CFA_COL;
447 #else
448     dbg->de_frame_cfa_col_number = DW_FRAME_CFA_COL3;
449 #endif
450     dbg->de_frame_same_value_number = DW_FRAME_SAME_VAL;
451     dbg->de_frame_undefined_value_number  = DW_FRAME_UNDEFINED_VAL;
452 
453     dbg->de_obj_file = obj;
454 
455     setup_result = _dwarf_setup(dbg, error);
456     if (setup_result != DW_DLV_OK) {
457         /* The status we want to return  here is of _dwarf_setup,
458            not of the  _dwarf_free_all_of_one_debug(dbg) call.
459            So use a local status variable for the free.  */
460         int freeresult = _dwarf_free_all_of_one_debug(dbg);
461         if (freeresult == DW_DLV_ERROR) {
462             DWARF_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, DW_DLV_ERROR);
463         }
464         dwarf_malloc_check_complete("After Final free");
465         return setup_result;
466     }
467 
468     dwarf_harmless_init(&dbg->de_harmless_errors,
469         DW_HARMLESS_ERROR_CIRCULAR_LIST_DEFAULT_SIZE);
470 
471     /* This call cannot fail: allocates nothing, releases nothing */
472     _dwarf_setup_debug(dbg);
473 
474 
475     *ret_dbg = dbg;
476     return DW_DLV_OK;
477 }
478 
479 
480 /*
481     A finish routine that is completely unaware of ELF.
482 
483     Frees all memory that was not previously freed by
484     dwarf_dealloc.
485     Aside frmo certain categories.
486  */
487 int
488 dwarf_object_finish(Dwarf_Debug dbg, Dwarf_Error * error)
489 {
490     int res = DW_DLV_OK;
491 
492     res = _dwarf_free_all_of_one_debug(dbg);
493     if (res == DW_DLV_ERROR) {
494         DWARF_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, DW_DLV_ERROR);
495     }
496     dwarf_malloc_check_complete("After Final free");
497 
498     return res;
499 }
500 
501 
502 /*
503     Load the ELF section with the specified index and set the
504     pointer pointed to by section_data to the memory where it
505     was loaded.
506  */
507 int
508 _dwarf_load_section(Dwarf_Debug dbg,
509     struct Dwarf_Section_s *section,
510     Dwarf_Error * error)
511 {
512     int res  = DW_DLV_ERROR;
513     int err = 0;
514     struct Dwarf_Obj_Access_Interface_s *o = 0;
515 
516     /* check to see if the section is already loaded */
517     if (section->dss_data !=  NULL) {
518         return DW_DLV_OK;
519     }
520     o = dbg->de_obj_file;
521     res = o->methods->load_section(
522         o->object, section->dss_index,
523         &section->dss_data, &err);
524     if(res == DW_DLV_ERROR){
525         DWARF_DBG_ERROR(dbg, err, DW_DLV_ERROR);
526     }
527     if(_dwarf_apply_relocs == 0) {
528         return res;
529     }
530     if(section->dss_reloc_size == 0) {
531         return res;
532     }
533     if(!o->methods->relocate_a_section) {
534         return res;
535     }
536     /*apply relocations */
537     res = o->methods->relocate_a_section( o->object, section->dss_index,
538         dbg, &err);
539     if(res == DW_DLV_ERROR) {
540         DWARF_DBG_ERROR(dbg, err, DW_DLV_ERROR);
541     }
542     return res;
543 }
544 
545 /* This is a hack so clients can verify offsets.
546    Added April 2005 so that debugger can detect broken offsets
547    (which happened in an IRIX  -64 executable larger than 2GB
548     using MIPSpro 7.3.1.3 compilers. A couple .debug_pubnames
549     offsets were wrong.).
550 */
551 int
552 dwarf_get_section_max_offsets(Dwarf_Debug dbg,
553     Dwarf_Unsigned * debug_info_size,
554     Dwarf_Unsigned * debug_abbrev_size,
555     Dwarf_Unsigned * debug_line_size,
556     Dwarf_Unsigned * debug_loc_size,
557     Dwarf_Unsigned * debug_aranges_size,
558     Dwarf_Unsigned * debug_macinfo_size,
559     Dwarf_Unsigned * debug_pubnames_size,
560     Dwarf_Unsigned * debug_str_size,
561     Dwarf_Unsigned * debug_frame_size,
562     Dwarf_Unsigned * debug_ranges_size,
563     Dwarf_Unsigned * debug_typenames_size)
564 {
565     *debug_info_size = dbg->de_debug_info.dss_size;
566     *debug_abbrev_size = dbg->de_debug_abbrev.dss_size;
567     *debug_line_size = dbg->de_debug_line.dss_size;
568     *debug_loc_size = dbg->de_debug_loc.dss_size;
569     *debug_aranges_size = dbg->de_debug_aranges.dss_size;
570     *debug_macinfo_size = dbg->de_debug_macinfo.dss_size;
571     *debug_pubnames_size = dbg->de_debug_pubnames.dss_size;
572     *debug_str_size = dbg->de_debug_str.dss_size;
573     *debug_frame_size = dbg->de_debug_frame.dss_size;
574     *debug_ranges_size = dbg->de_debug_ranges.dss_size;
575     *debug_typenames_size = dbg->de_debug_typenames.dss_size;
576     return DW_DLV_OK;
577 }
578