From bc1f688b4872ace323eaddbb1a6365d054e7bf56 Mon Sep 17 00:00:00 2001 From: Robert Mustacchi Date: Thu, 17 Jan 2019 17:50:46 +0000 Subject: 6885 CTF Everywhere Part 1 6886 Want ctfdiff 6887 ctfdump should be written in terms of libctf 6888 ctfmerge should be implemented in terms of libctf 6889 ctfconvert should be implemented in terms of libctf 6890 Want general workq 6891 Want general mergeq 6892 ctf_add_encoded assigns() incorrect byte size to types 6893 ctf_add_{struct,union,enum} can reuse forwards 6894 ctf_add_{struct,union,enum} occasionally forget to dirty the ctf_file_t 6895 ctf_add_member could better handle bitfields 6896 ctf_type_size() reports wrong size for forwards 6897 Want libctf ctf_kind_name() function 6898 Want libctf function to set struct/union size Portions contributed by: John Levon Portions contributed by: Richard Lowe Reviewed by: John Levon Reviewed by: Andy Fiddaman Reviewed by: GergÅ‘ Doma Approved by: Dan McDonald MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- usr/src/Makefile.lint | 1 + usr/src/Makefile.master | 10 + usr/src/Targetdirs | 10 + usr/src/cmd/Makefile | 4 + usr/src/cmd/ctfconvert/Makefile | 33 + usr/src/cmd/ctfconvert/ctfconvert.c | 388 +++ usr/src/cmd/ctfdiff/Makefile | 33 + usr/src/cmd/ctfdiff/ctfdiff.c | 518 ++++ usr/src/cmd/ctfdump/Makefile | 36 + usr/src/cmd/ctfdump/ctfdump.c | 1235 ++++++++ usr/src/cmd/ctfmerge/Makefile | 33 + usr/src/cmd/ctfmerge/ctfmerge.c | 536 ++++ usr/src/cmd/mdb/Makefile.libstandctf | 5 + usr/src/cmd/mdb/common/kmdb/kmdb_promif.c | 7 +- usr/src/cmd/mdb/common/libstandctf/ctf_subr.c | 9 +- usr/src/cmd/mdb/common/mdb/mdb_ctf.c | 15 +- usr/src/cmd/mdb/common/mdb/mdb_debug.c | 4 - usr/src/cmd/mdb/common/mdb/mdb_debug.h | 4 +- usr/src/common/ctf/ctf_create.c | 842 +++++- usr/src/common/ctf/ctf_error.c | 12 +- usr/src/common/ctf/ctf_hash.c | 3 +- usr/src/common/ctf/ctf_impl.h | 90 +- usr/src/common/ctf/ctf_open.c | 40 +- usr/src/common/ctf/ctf_types.c | 470 ++- usr/src/common/ctf/ctf_util.c | 43 +- usr/src/lib/Makefile | 5 +- usr/src/lib/Makefile.lib | 13 + usr/src/lib/Makefile.targ | 5 +- usr/src/lib/libctf/Makefile.com | 41 +- usr/src/lib/libctf/Makefile.shared.com | 90 + usr/src/lib/libctf/Makefile.shared.targ | 30 + usr/src/lib/libctf/common/ctf_convert.c | 210 ++ usr/src/lib/libctf/common/ctf_diff.c | 1360 +++++++++ usr/src/lib/libctf/common/ctf_dwarf.c | 2995 ++++++++++++++++++++ usr/src/lib/libctf/common/ctf_elfwrite.c | 422 +++ usr/src/lib/libctf/common/ctf_lib.c | 296 +- usr/src/lib/libctf/common/ctf_merge.c | 1551 ++++++++++ usr/src/lib/libctf/common/ctf_subr.c | 28 +- usr/src/lib/libctf/common/libctf.h | 45 +- usr/src/lib/libctf/common/libctf_impl.h | 59 + usr/src/lib/libctf/common/mapfile-vers | 38 +- usr/src/lib/libdtrace/common/dt_decl.c | 4 +- usr/src/lib/libdtrace/common/dt_open.c | 12 +- usr/src/lib/libdtrace/common/dt_parser.c | 4 +- usr/src/lib/libdwarf/Makefile | 40 + usr/src/lib/libdwarf/Makefile.com | 94 + usr/src/lib/libdwarf/THIRDPARTYLICENSE | 30 + usr/src/lib/libdwarf/THIRDPARTYLICENSE.descrip | 1 + usr/src/lib/libdwarf/amd64/Makefile | 19 + .../lib/libdwarf/common/cmplrs/dwarf_addr_finder.h | 55 + usr/src/lib/libdwarf/common/config.h | 143 + usr/src/lib/libdwarf/common/dwarf.h | 1078 +++++++ usr/src/lib/libdwarf/common/dwarf_abbrev.c | 259 ++ usr/src/lib/libdwarf/common/dwarf_abbrev.h | 55 + usr/src/lib/libdwarf/common/dwarf_addr_finder.c | 685 +++++ usr/src/lib/libdwarf/common/dwarf_alloc.c | 1258 ++++++++ usr/src/lib/libdwarf/common/dwarf_alloc.h | 177 ++ usr/src/lib/libdwarf/common/dwarf_arange.c | 593 ++++ usr/src/lib/libdwarf/common/dwarf_arange.h | 71 + usr/src/lib/libdwarf/common/dwarf_base_types.h | 123 + usr/src/lib/libdwarf/common/dwarf_die_deliv.c | 855 ++++++ usr/src/lib/libdwarf/common/dwarf_die_deliv.h | 57 + usr/src/lib/libdwarf/common/dwarf_elf_access.c | 976 +++++++ usr/src/lib/libdwarf/common/dwarf_elf_access.h | 55 + usr/src/lib/libdwarf/common/dwarf_error.c | 410 +++ usr/src/lib/libdwarf/common/dwarf_error.h | 43 + usr/src/lib/libdwarf/common/dwarf_form.c | 963 +++++++ usr/src/lib/libdwarf/common/dwarf_frame.c | 2442 ++++++++++++++++ usr/src/lib/libdwarf/common/dwarf_frame.h | 421 +++ usr/src/lib/libdwarf/common/dwarf_frame2.c | 1540 ++++++++++ usr/src/lib/libdwarf/common/dwarf_frame3.c | 290 ++ usr/src/lib/libdwarf/common/dwarf_funcs.c | 130 + usr/src/lib/libdwarf/common/dwarf_funcs.h | 42 + usr/src/lib/libdwarf/common/dwarf_global.c | 607 ++++ usr/src/lib/libdwarf/common/dwarf_global.h | 124 + usr/src/lib/libdwarf/common/dwarf_harmless.c | 226 ++ usr/src/lib/libdwarf/common/dwarf_harmless.h | 31 + usr/src/lib/libdwarf/common/dwarf_incl.h | 66 + usr/src/lib/libdwarf/common/dwarf_init_finish.c | 577 ++++ usr/src/lib/libdwarf/common/dwarf_leb.c | 149 + usr/src/lib/libdwarf/common/dwarf_line.c | 1951 +++++++++++++ usr/src/lib/libdwarf/common/dwarf_line.h | 331 +++ usr/src/lib/libdwarf/common/dwarf_line2.c | 110 + usr/src/lib/libdwarf/common/dwarf_loc.c | 1073 +++++++ usr/src/lib/libdwarf/common/dwarf_loc.h | 46 + usr/src/lib/libdwarf/common/dwarf_macro.c | 467 +++ usr/src/lib/libdwarf/common/dwarf_macro.h | 44 + usr/src/lib/libdwarf/common/dwarf_names.c | 2408 ++++++++++++++++ usr/src/lib/libdwarf/common/dwarf_names.h | 34 + usr/src/lib/libdwarf/common/dwarf_opaque.h | 339 +++ .../lib/libdwarf/common/dwarf_original_elf_init.c | 209 ++ usr/src/lib/libdwarf/common/dwarf_print_lines.c | 737 +++++ usr/src/lib/libdwarf/common/dwarf_pubtypes.c | 138 + usr/src/lib/libdwarf/common/dwarf_query.c | 789 ++++++ usr/src/lib/libdwarf/common/dwarf_ranges.c | 171 ++ usr/src/lib/libdwarf/common/dwarf_sort_line.c | 733 +++++ usr/src/lib/libdwarf/common/dwarf_string.c | 79 + usr/src/lib/libdwarf/common/dwarf_stubs.c | 50 + usr/src/lib/libdwarf/common/dwarf_types.c | 129 + usr/src/lib/libdwarf/common/dwarf_types.h | 41 + usr/src/lib/libdwarf/common/dwarf_util.c | 547 ++++ usr/src/lib/libdwarf/common/dwarf_util.h | 311 ++ usr/src/lib/libdwarf/common/dwarf_vars.c | 133 + usr/src/lib/libdwarf/common/dwarf_vars.h | 41 + usr/src/lib/libdwarf/common/dwarf_weaks.c | 130 + usr/src/lib/libdwarf/common/dwarf_weaks.h | 41 + usr/src/lib/libdwarf/common/libdwarf.h | 2736 ++++++++++++++++++ usr/src/lib/libdwarf/common/libdwarfdefs.h | 91 + usr/src/lib/libdwarf/common/malloc_check.c | 339 +++ usr/src/lib/libdwarf/common/malloc_check.h | 62 + usr/src/lib/libdwarf/common/mapfile-vers | 302 ++ usr/src/lib/libdwarf/common/pro_alloc.c | 188 ++ usr/src/lib/libdwarf/common/pro_alloc.h | 42 + usr/src/lib/libdwarf/common/pro_arange.c | 337 +++ usr/src/lib/libdwarf/common/pro_arange.h | 62 + usr/src/lib/libdwarf/common/pro_die.c | 442 +++ usr/src/lib/libdwarf/common/pro_die.h | 68 + usr/src/lib/libdwarf/common/pro_encode_nm.c | 123 + usr/src/lib/libdwarf/common/pro_encode_nm.h | 48 + usr/src/lib/libdwarf/common/pro_error.c | 97 + usr/src/lib/libdwarf/common/pro_error.h | 52 + usr/src/lib/libdwarf/common/pro_expr.c | 597 ++++ usr/src/lib/libdwarf/common/pro_expr.h | 45 + usr/src/lib/libdwarf/common/pro_finish.c | 57 + usr/src/lib/libdwarf/common/pro_forms.c | 1182 ++++++++ usr/src/lib/libdwarf/common/pro_frame.c | 598 ++++ usr/src/lib/libdwarf/common/pro_frame.h | 132 + usr/src/lib/libdwarf/common/pro_funcs.c | 62 + usr/src/lib/libdwarf/common/pro_incl.h | 92 + usr/src/lib/libdwarf/common/pro_init.c | 261 ++ usr/src/lib/libdwarf/common/pro_line.c | 300 ++ usr/src/lib/libdwarf/common/pro_line.h | 116 + usr/src/lib/libdwarf/common/pro_macinfo.c | 472 +++ usr/src/lib/libdwarf/common/pro_macinfo.h | 40 + usr/src/lib/libdwarf/common/pro_opaque.h | 484 ++++ usr/src/lib/libdwarf/common/pro_pubnames.c | 63 + usr/src/lib/libdwarf/common/pro_reloc.c | 269 ++ usr/src/lib/libdwarf/common/pro_reloc.h | 47 + usr/src/lib/libdwarf/common/pro_reloc_stream.c | 297 ++ usr/src/lib/libdwarf/common/pro_reloc_stream.h | 63 + usr/src/lib/libdwarf/common/pro_reloc_symbolic.c | 276 ++ usr/src/lib/libdwarf/common/pro_reloc_symbolic.h | 55 + usr/src/lib/libdwarf/common/pro_section.c | 2221 +++++++++++++++ usr/src/lib/libdwarf/common/pro_section.h | 112 + usr/src/lib/libdwarf/common/pro_types.c | 296 ++ usr/src/lib/libdwarf/common/pro_types.h | 44 + usr/src/lib/libdwarf/common/pro_util.h | 148 + usr/src/lib/libdwarf/common/pro_vars.c | 62 + usr/src/lib/libdwarf/common/pro_weaks.c | 61 + usr/src/lib/libdwarf/i386/Makefile | 18 + usr/src/lib/libdwarf/sparc/Makefile | 18 + usr/src/lib/libdwarf/sparcv9/Makefile | 19 + usr/src/lib/mergeq/mergeq.c | 606 ++++ usr/src/lib/mergeq/mergeq.h | 52 + usr/src/lib/mergeq/workq.c | 311 ++ usr/src/lib/mergeq/workq.h | 52 + usr/src/man/man1/Makefile | 2 + usr/src/man/man1/ctfdiff.1 | 348 +++ usr/src/man/man1/ctfdump.1 | 446 +++ usr/src/pkg/manifests/developer-build-onbld.mf | 7 +- usr/src/pkg/manifests/developer-debug-ctf.mf | 32 + usr/src/pkg/manifests/system-library.mf | 7 + usr/src/pkg/manifests/system-test-utiltest.mf | 3 + usr/src/test/util-tests/runfiles/default.run | 3 + usr/src/test/util-tests/tests/Makefile | 2 +- usr/src/test/util-tests/tests/mergeq/Makefile | 64 + usr/src/test/util-tests/tests/mergeq/mqt.c | 217 ++ usr/src/test/util-tests/tests/workq/Makefile | 64 + usr/src/test/util-tests/tests/workq/wqt.c | 196 ++ usr/src/tools/ctf/Makefile | 9 +- usr/src/tools/ctf/Makefile.ctf | 7 +- usr/src/tools/ctf/common/ctf_headers.h | 18 +- usr/src/tools/ctf/ctfconvert/Makefile | 44 + usr/src/tools/ctf/ctfconvert/Makefile.com | 44 + usr/src/tools/ctf/ctfconvert/i386/Makefile | 27 + usr/src/tools/ctf/ctfconvert/sparc/Makefile | 27 + usr/src/tools/ctf/ctfdiff/Makefile | 44 + usr/src/tools/ctf/ctfdiff/Makefile.com | 44 + usr/src/tools/ctf/ctfdiff/i386/Makefile | 16 + usr/src/tools/ctf/ctfdiff/sparc/Makefile | 16 + usr/src/tools/ctf/ctfdump/Makefile | 33 + usr/src/tools/ctf/ctfdump/Makefile.com | 47 + usr/src/tools/ctf/ctfdump/i386/Makefile | 16 + usr/src/tools/ctf/ctfdump/sparc/Makefile | 16 + usr/src/tools/ctf/ctfmerge/Makefile | 44 + usr/src/tools/ctf/ctfmerge/Makefile.com | 46 + usr/src/tools/ctf/ctfmerge/i386/Makefile | 27 + usr/src/tools/ctf/ctfmerge/sparc/Makefile | 27 + usr/src/tools/ctf/cvt/Makefile.com | 3 +- usr/src/tools/ctf/cvt/altexec.c | 45 + usr/src/tools/ctf/cvt/ctfconvert.c | 12 +- usr/src/tools/ctf/cvt/ctfmerge.c | 2 + usr/src/tools/ctf/cvt/ctftools.h | 3 + usr/src/tools/ctf/dump/Makefile | 45 - usr/src/tools/ctf/dump/Makefile.com | 67 - usr/src/tools/ctf/dump/dump.c | 1028 ------- usr/src/tools/ctf/dump/i386/Makefile | 28 - usr/src/tools/ctf/dump/sparc/Makefile | 28 - usr/src/tools/ctf/dwarf/Makefile.com | 7 +- usr/src/tools/ctf/dwarf/THIRDPARTYLICENSE | 30 - usr/src/tools/ctf/dwarf/THIRDPARTYLICENSE.descrip | 1 - .../ctf/dwarf/common/cmplrs/dwarf_addr_finder.h | 55 - usr/src/tools/ctf/dwarf/common/config.h | 143 - usr/src/tools/ctf/dwarf/common/dwarf.h | 1078 ------- usr/src/tools/ctf/dwarf/common/dwarf_abbrev.c | 259 -- usr/src/tools/ctf/dwarf/common/dwarf_abbrev.h | 55 - usr/src/tools/ctf/dwarf/common/dwarf_addr_finder.c | 685 ----- usr/src/tools/ctf/dwarf/common/dwarf_alloc.c | 1258 -------- usr/src/tools/ctf/dwarf/common/dwarf_alloc.h | 177 -- usr/src/tools/ctf/dwarf/common/dwarf_arange.c | 593 ---- usr/src/tools/ctf/dwarf/common/dwarf_arange.h | 71 - usr/src/tools/ctf/dwarf/common/dwarf_base_types.h | 123 - usr/src/tools/ctf/dwarf/common/dwarf_die_deliv.c | 855 ------ usr/src/tools/ctf/dwarf/common/dwarf_die_deliv.h | 57 - usr/src/tools/ctf/dwarf/common/dwarf_elf_access.c | 976 ------- usr/src/tools/ctf/dwarf/common/dwarf_elf_access.h | 55 - usr/src/tools/ctf/dwarf/common/dwarf_error.c | 410 --- usr/src/tools/ctf/dwarf/common/dwarf_error.h | 43 - usr/src/tools/ctf/dwarf/common/dwarf_form.c | 963 ------- usr/src/tools/ctf/dwarf/common/dwarf_frame.c | 2442 ---------------- usr/src/tools/ctf/dwarf/common/dwarf_frame.h | 421 --- usr/src/tools/ctf/dwarf/common/dwarf_frame2.c | 1540 ---------- usr/src/tools/ctf/dwarf/common/dwarf_frame3.c | 290 -- usr/src/tools/ctf/dwarf/common/dwarf_funcs.c | 130 - usr/src/tools/ctf/dwarf/common/dwarf_funcs.h | 42 - usr/src/tools/ctf/dwarf/common/dwarf_global.c | 607 ---- usr/src/tools/ctf/dwarf/common/dwarf_global.h | 124 - usr/src/tools/ctf/dwarf/common/dwarf_harmless.c | 226 -- usr/src/tools/ctf/dwarf/common/dwarf_harmless.h | 31 - usr/src/tools/ctf/dwarf/common/dwarf_incl.h | 66 - usr/src/tools/ctf/dwarf/common/dwarf_init_finish.c | 577 ---- usr/src/tools/ctf/dwarf/common/dwarf_leb.c | 149 - usr/src/tools/ctf/dwarf/common/dwarf_line.c | 1951 ------------- usr/src/tools/ctf/dwarf/common/dwarf_line.h | 331 --- usr/src/tools/ctf/dwarf/common/dwarf_line2.c | 110 - usr/src/tools/ctf/dwarf/common/dwarf_loc.c | 1073 ------- usr/src/tools/ctf/dwarf/common/dwarf_loc.h | 46 - usr/src/tools/ctf/dwarf/common/dwarf_macro.c | 467 --- usr/src/tools/ctf/dwarf/common/dwarf_macro.h | 44 - usr/src/tools/ctf/dwarf/common/dwarf_names.c | 2408 ---------------- usr/src/tools/ctf/dwarf/common/dwarf_names.h | 34 - usr/src/tools/ctf/dwarf/common/dwarf_opaque.h | 339 --- .../ctf/dwarf/common/dwarf_original_elf_init.c | 209 -- usr/src/tools/ctf/dwarf/common/dwarf_print_lines.c | 737 ----- usr/src/tools/ctf/dwarf/common/dwarf_pubtypes.c | 138 - usr/src/tools/ctf/dwarf/common/dwarf_query.c | 789 ------ usr/src/tools/ctf/dwarf/common/dwarf_ranges.c | 171 -- usr/src/tools/ctf/dwarf/common/dwarf_sort_line.c | 733 ----- usr/src/tools/ctf/dwarf/common/dwarf_string.c | 79 - usr/src/tools/ctf/dwarf/common/dwarf_stubs.c | 50 - usr/src/tools/ctf/dwarf/common/dwarf_types.c | 129 - usr/src/tools/ctf/dwarf/common/dwarf_types.h | 41 - usr/src/tools/ctf/dwarf/common/dwarf_util.c | 547 ---- usr/src/tools/ctf/dwarf/common/dwarf_util.h | 311 -- usr/src/tools/ctf/dwarf/common/dwarf_vars.c | 133 - usr/src/tools/ctf/dwarf/common/dwarf_vars.h | 41 - usr/src/tools/ctf/dwarf/common/dwarf_weaks.c | 130 - usr/src/tools/ctf/dwarf/common/dwarf_weaks.h | 41 - usr/src/tools/ctf/dwarf/common/libdwarf.h | 2736 ------------------ usr/src/tools/ctf/dwarf/common/libdwarfdefs.h | 91 - usr/src/tools/ctf/dwarf/common/malloc_check.c | 339 --- usr/src/tools/ctf/dwarf/common/malloc_check.h | 62 - usr/src/tools/ctf/dwarf/common/mapfile-vers | 302 -- usr/src/tools/ctf/dwarf/common/pro_alloc.c | 188 -- usr/src/tools/ctf/dwarf/common/pro_alloc.h | 42 - usr/src/tools/ctf/dwarf/common/pro_arange.c | 337 --- usr/src/tools/ctf/dwarf/common/pro_arange.h | 62 - usr/src/tools/ctf/dwarf/common/pro_die.c | 442 --- usr/src/tools/ctf/dwarf/common/pro_die.h | 68 - usr/src/tools/ctf/dwarf/common/pro_encode_nm.c | 123 - usr/src/tools/ctf/dwarf/common/pro_encode_nm.h | 48 - usr/src/tools/ctf/dwarf/common/pro_error.c | 97 - usr/src/tools/ctf/dwarf/common/pro_error.h | 52 - usr/src/tools/ctf/dwarf/common/pro_expr.c | 597 ---- usr/src/tools/ctf/dwarf/common/pro_expr.h | 45 - usr/src/tools/ctf/dwarf/common/pro_finish.c | 57 - usr/src/tools/ctf/dwarf/common/pro_forms.c | 1182 -------- usr/src/tools/ctf/dwarf/common/pro_frame.c | 598 ---- usr/src/tools/ctf/dwarf/common/pro_frame.h | 132 - usr/src/tools/ctf/dwarf/common/pro_funcs.c | 62 - usr/src/tools/ctf/dwarf/common/pro_incl.h | 92 - usr/src/tools/ctf/dwarf/common/pro_init.c | 261 -- usr/src/tools/ctf/dwarf/common/pro_line.c | 300 -- usr/src/tools/ctf/dwarf/common/pro_line.h | 116 - usr/src/tools/ctf/dwarf/common/pro_macinfo.c | 472 --- usr/src/tools/ctf/dwarf/common/pro_macinfo.h | 40 - usr/src/tools/ctf/dwarf/common/pro_opaque.h | 484 ---- usr/src/tools/ctf/dwarf/common/pro_pubnames.c | 63 - usr/src/tools/ctf/dwarf/common/pro_reloc.c | 269 -- usr/src/tools/ctf/dwarf/common/pro_reloc.h | 47 - usr/src/tools/ctf/dwarf/common/pro_reloc_stream.c | 297 -- usr/src/tools/ctf/dwarf/common/pro_reloc_stream.h | 63 - .../tools/ctf/dwarf/common/pro_reloc_symbolic.c | 276 -- .../tools/ctf/dwarf/common/pro_reloc_symbolic.h | 55 - usr/src/tools/ctf/dwarf/common/pro_section.c | 2221 --------------- usr/src/tools/ctf/dwarf/common/pro_section.h | 112 - usr/src/tools/ctf/dwarf/common/pro_types.c | 296 -- usr/src/tools/ctf/dwarf/common/pro_types.h | 44 - usr/src/tools/ctf/dwarf/common/pro_util.h | 148 - usr/src/tools/ctf/dwarf/common/pro_vars.c | 62 - usr/src/tools/ctf/dwarf/common/pro_weaks.c | 61 - usr/src/tools/ctf/libctf/Makefile | 46 + usr/src/tools/ctf/libctf/Makefile.com | 51 + usr/src/tools/ctf/libctf/i386/Makefile | 18 + usr/src/tools/ctf/libctf/sparc/Makefile | 18 + usr/src/tools/make/lib/bsd/Makefile | 4 + usr/src/tools/make/lib/makestate/Makefile.com | 4 + usr/src/tools/make/lib/mksh/Makefile | 4 + usr/src/tools/make/lib/vroot/Makefile | 4 + usr/src/uts/Makefile.uts | 8 + usr/src/uts/common/ctf/ctf_mod.c | 11 +- usr/src/uts/common/sys/ctf.h | 14 +- usr/src/uts/common/sys/ctf_api.h | 108 +- usr/src/uts/intel/ctf/Makefile | 4 + usr/src/uts/sparc/ctf/Makefile | 4 + 315 files changed, 53891 insertions(+), 40546 deletions(-) create mode 100644 usr/src/cmd/ctfconvert/Makefile create mode 100644 usr/src/cmd/ctfconvert/ctfconvert.c create mode 100644 usr/src/cmd/ctfdiff/Makefile create mode 100644 usr/src/cmd/ctfdiff/ctfdiff.c create mode 100644 usr/src/cmd/ctfdump/Makefile create mode 100644 usr/src/cmd/ctfdump/ctfdump.c create mode 100644 usr/src/cmd/ctfmerge/Makefile create mode 100644 usr/src/cmd/ctfmerge/ctfmerge.c create mode 100644 usr/src/lib/libctf/Makefile.shared.com create mode 100644 usr/src/lib/libctf/Makefile.shared.targ create mode 100644 usr/src/lib/libctf/common/ctf_convert.c create mode 100644 usr/src/lib/libctf/common/ctf_diff.c create mode 100644 usr/src/lib/libctf/common/ctf_dwarf.c create mode 100644 usr/src/lib/libctf/common/ctf_elfwrite.c create mode 100644 usr/src/lib/libctf/common/ctf_merge.c create mode 100644 usr/src/lib/libctf/common/libctf_impl.h create mode 100644 usr/src/lib/libdwarf/Makefile create mode 100644 usr/src/lib/libdwarf/Makefile.com create mode 100644 usr/src/lib/libdwarf/THIRDPARTYLICENSE create mode 100644 usr/src/lib/libdwarf/THIRDPARTYLICENSE.descrip create mode 100644 usr/src/lib/libdwarf/amd64/Makefile create mode 100644 usr/src/lib/libdwarf/common/cmplrs/dwarf_addr_finder.h create mode 100644 usr/src/lib/libdwarf/common/config.h create mode 100644 usr/src/lib/libdwarf/common/dwarf.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_abbrev.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_abbrev.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_addr_finder.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_alloc.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_alloc.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_arange.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_arange.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_base_types.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_die_deliv.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_die_deliv.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_elf_access.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_elf_access.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_error.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_error.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_form.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_frame.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_frame.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_frame2.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_frame3.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_funcs.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_funcs.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_global.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_global.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_harmless.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_harmless.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_incl.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_init_finish.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_leb.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_line.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_line.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_line2.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_loc.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_loc.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_macro.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_macro.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_names.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_names.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_opaque.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_original_elf_init.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_print_lines.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_pubtypes.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_query.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_ranges.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_sort_line.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_string.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_stubs.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_types.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_types.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_util.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_util.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_vars.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_vars.h create mode 100644 usr/src/lib/libdwarf/common/dwarf_weaks.c create mode 100644 usr/src/lib/libdwarf/common/dwarf_weaks.h create mode 100644 usr/src/lib/libdwarf/common/libdwarf.h create mode 100644 usr/src/lib/libdwarf/common/libdwarfdefs.h create mode 100644 usr/src/lib/libdwarf/common/malloc_check.c create mode 100644 usr/src/lib/libdwarf/common/malloc_check.h create mode 100644 usr/src/lib/libdwarf/common/mapfile-vers create mode 100644 usr/src/lib/libdwarf/common/pro_alloc.c create mode 100644 usr/src/lib/libdwarf/common/pro_alloc.h create mode 100644 usr/src/lib/libdwarf/common/pro_arange.c create mode 100644 usr/src/lib/libdwarf/common/pro_arange.h create mode 100644 usr/src/lib/libdwarf/common/pro_die.c create mode 100644 usr/src/lib/libdwarf/common/pro_die.h create mode 100644 usr/src/lib/libdwarf/common/pro_encode_nm.c create mode 100644 usr/src/lib/libdwarf/common/pro_encode_nm.h create mode 100644 usr/src/lib/libdwarf/common/pro_error.c create mode 100644 usr/src/lib/libdwarf/common/pro_error.h create mode 100644 usr/src/lib/libdwarf/common/pro_expr.c create mode 100644 usr/src/lib/libdwarf/common/pro_expr.h create mode 100644 usr/src/lib/libdwarf/common/pro_finish.c create mode 100644 usr/src/lib/libdwarf/common/pro_forms.c create mode 100644 usr/src/lib/libdwarf/common/pro_frame.c create mode 100644 usr/src/lib/libdwarf/common/pro_frame.h create mode 100644 usr/src/lib/libdwarf/common/pro_funcs.c create mode 100644 usr/src/lib/libdwarf/common/pro_incl.h create mode 100644 usr/src/lib/libdwarf/common/pro_init.c create mode 100644 usr/src/lib/libdwarf/common/pro_line.c create mode 100644 usr/src/lib/libdwarf/common/pro_line.h create mode 100644 usr/src/lib/libdwarf/common/pro_macinfo.c create mode 100644 usr/src/lib/libdwarf/common/pro_macinfo.h create mode 100644 usr/src/lib/libdwarf/common/pro_opaque.h create mode 100644 usr/src/lib/libdwarf/common/pro_pubnames.c create mode 100644 usr/src/lib/libdwarf/common/pro_reloc.c create mode 100644 usr/src/lib/libdwarf/common/pro_reloc.h create mode 100644 usr/src/lib/libdwarf/common/pro_reloc_stream.c create mode 100644 usr/src/lib/libdwarf/common/pro_reloc_stream.h create mode 100644 usr/src/lib/libdwarf/common/pro_reloc_symbolic.c create mode 100644 usr/src/lib/libdwarf/common/pro_reloc_symbolic.h create mode 100644 usr/src/lib/libdwarf/common/pro_section.c create mode 100644 usr/src/lib/libdwarf/common/pro_section.h create mode 100644 usr/src/lib/libdwarf/common/pro_types.c create mode 100644 usr/src/lib/libdwarf/common/pro_types.h create mode 100644 usr/src/lib/libdwarf/common/pro_util.h create mode 100644 usr/src/lib/libdwarf/common/pro_vars.c create mode 100644 usr/src/lib/libdwarf/common/pro_weaks.c create mode 100644 usr/src/lib/libdwarf/i386/Makefile create mode 100644 usr/src/lib/libdwarf/sparc/Makefile create mode 100644 usr/src/lib/libdwarf/sparcv9/Makefile create mode 100644 usr/src/lib/mergeq/mergeq.c create mode 100644 usr/src/lib/mergeq/mergeq.h create mode 100644 usr/src/lib/mergeq/workq.c create mode 100644 usr/src/lib/mergeq/workq.h create mode 100644 usr/src/man/man1/ctfdiff.1 create mode 100644 usr/src/man/man1/ctfdump.1 create mode 100644 usr/src/pkg/manifests/developer-debug-ctf.mf create mode 100644 usr/src/test/util-tests/tests/mergeq/Makefile create mode 100644 usr/src/test/util-tests/tests/mergeq/mqt.c create mode 100644 usr/src/test/util-tests/tests/workq/Makefile create mode 100644 usr/src/test/util-tests/tests/workq/wqt.c create mode 100644 usr/src/tools/ctf/ctfconvert/Makefile create mode 100644 usr/src/tools/ctf/ctfconvert/Makefile.com create mode 100644 usr/src/tools/ctf/ctfconvert/i386/Makefile create mode 100644 usr/src/tools/ctf/ctfconvert/sparc/Makefile create mode 100644 usr/src/tools/ctf/ctfdiff/Makefile create mode 100644 usr/src/tools/ctf/ctfdiff/Makefile.com create mode 100644 usr/src/tools/ctf/ctfdiff/i386/Makefile create mode 100644 usr/src/tools/ctf/ctfdiff/sparc/Makefile create mode 100644 usr/src/tools/ctf/ctfdump/Makefile create mode 100644 usr/src/tools/ctf/ctfdump/Makefile.com create mode 100644 usr/src/tools/ctf/ctfdump/i386/Makefile create mode 100644 usr/src/tools/ctf/ctfdump/sparc/Makefile create mode 100644 usr/src/tools/ctf/ctfmerge/Makefile create mode 100644 usr/src/tools/ctf/ctfmerge/Makefile.com create mode 100644 usr/src/tools/ctf/ctfmerge/i386/Makefile create mode 100644 usr/src/tools/ctf/ctfmerge/sparc/Makefile create mode 100644 usr/src/tools/ctf/cvt/altexec.c delete mode 100644 usr/src/tools/ctf/dump/Makefile delete mode 100644 usr/src/tools/ctf/dump/Makefile.com delete mode 100644 usr/src/tools/ctf/dump/dump.c delete mode 100644 usr/src/tools/ctf/dump/i386/Makefile delete mode 100644 usr/src/tools/ctf/dump/sparc/Makefile delete mode 100644 usr/src/tools/ctf/dwarf/THIRDPARTYLICENSE delete mode 100644 usr/src/tools/ctf/dwarf/THIRDPARTYLICENSE.descrip delete mode 100644 usr/src/tools/ctf/dwarf/common/cmplrs/dwarf_addr_finder.h delete mode 100644 usr/src/tools/ctf/dwarf/common/config.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_abbrev.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_abbrev.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_addr_finder.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_alloc.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_alloc.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_arange.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_arange.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_base_types.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_die_deliv.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_die_deliv.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_elf_access.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_elf_access.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_error.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_error.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_form.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_frame.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_frame.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_frame2.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_frame3.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_funcs.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_funcs.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_global.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_global.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_harmless.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_harmless.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_incl.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_init_finish.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_leb.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_line.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_line.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_line2.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_loc.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_loc.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_macro.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_macro.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_names.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_names.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_opaque.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_original_elf_init.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_print_lines.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_pubtypes.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_query.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_ranges.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_sort_line.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_string.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_stubs.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_types.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_types.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_util.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_util.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_vars.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_vars.h delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_weaks.c delete mode 100644 usr/src/tools/ctf/dwarf/common/dwarf_weaks.h delete mode 100644 usr/src/tools/ctf/dwarf/common/libdwarf.h delete mode 100644 usr/src/tools/ctf/dwarf/common/libdwarfdefs.h delete mode 100644 usr/src/tools/ctf/dwarf/common/malloc_check.c delete mode 100644 usr/src/tools/ctf/dwarf/common/malloc_check.h delete mode 100644 usr/src/tools/ctf/dwarf/common/mapfile-vers delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_alloc.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_alloc.h delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_arange.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_arange.h delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_die.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_die.h delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_encode_nm.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_encode_nm.h delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_error.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_error.h delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_expr.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_expr.h delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_finish.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_forms.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_frame.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_frame.h delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_funcs.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_incl.h delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_init.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_line.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_line.h delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_macinfo.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_macinfo.h delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_opaque.h delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_pubnames.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_reloc.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_reloc.h delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_reloc_stream.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_reloc_stream.h delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_reloc_symbolic.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_reloc_symbolic.h delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_section.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_section.h delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_types.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_types.h delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_util.h delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_vars.c delete mode 100644 usr/src/tools/ctf/dwarf/common/pro_weaks.c create mode 100644 usr/src/tools/ctf/libctf/Makefile create mode 100644 usr/src/tools/ctf/libctf/Makefile.com create mode 100644 usr/src/tools/ctf/libctf/i386/Makefile create mode 100644 usr/src/tools/ctf/libctf/sparc/Makefile (limited to 'usr/src') diff --git a/usr/src/Makefile.lint b/usr/src/Makefile.lint index 8cc78f94d9..cdacf2ddfd 100644 --- a/usr/src/Makefile.lint +++ b/usr/src/Makefile.lint @@ -95,6 +95,7 @@ COMMON_SUBDIRS = \ cmd/cpio \ cmd/crypt \ cmd/csplit \ + cmd/ctfdump \ cmd/ctrun \ cmd/ctstat \ cmd/ctwatch \ diff --git a/usr/src/Makefile.master b/usr/src/Makefile.master index 5b6cd53942..501853a6ed 100644 --- a/usr/src/Makefile.master +++ b/usr/src/Makefile.master @@ -182,6 +182,7 @@ JAVADOC= $(JAVA_ROOT)/bin/javadoc RMIC= $(JAVA_ROOT)/bin/rmic JAR= $(JAVA_ROOT)/bin/jar CTFCONVERT= $(ONBLD_TOOLS)/bin/$(MACH)/ctfconvert +CTFDIFF= $(ONBLD_TOOLS)/bin/$(MACH)/ctfdiff CTFMERGE= $(ONBLD_TOOLS)/bin/$(MACH)/ctfmerge CTFSTABS= $(ONBLD_TOOLS)/bin/$(MACH)/ctfstabs CTFSTRIP= $(ONBLD_TOOLS)/bin/$(MACH)/ctfstrip @@ -966,6 +967,15 @@ CTFCVTFLAGS= -i -L VERSION # CTFMRGFLAGS= +# +# Make the transition between old and new CTF Tools. The new ctf tools +# do not support stabs (eg. Sun Studio). By setting BUILD_OLD_CTF_TOOLS +# here or in the environment file, the old ones will be built. +# +BUILD_NEW_CTF_TOOLS= +BUILD_OLD_CTF_TOOLS=$(POUND_SIGN) +$(BUILD_OLD_CTF_TOOLS)BUILD_NEW_CTF_TOOLS= $(POUND_SIGN) + CTFCONVERT_O = $(CTFCONVERT) $(CTFCVTFLAGS) $@ # Rules (normally from make.rules) and macros which are used for post diff --git a/usr/src/Targetdirs b/usr/src/Targetdirs index 25ee9bc38a..a056fd2d22 100644 --- a/usr/src/Targetdirs +++ b/usr/src/Targetdirs @@ -855,6 +855,8 @@ $(ROOT)/usr/lib/libdlpi.so.1:= REALPATH=../../lib/libdlpi.so.1 $(ROOT)/usr/lib/libdlpi.so:= REALPATH=../../lib/libdlpi.so.1 $(ROOT)/usr/lib/libdoor.so.1:= REALPATH=../../lib/libdoor.so.1 $(ROOT)/usr/lib/libdoor.so:= REALPATH=../../lib/libdoor.so.1 +$(ROOT)/usr/lib/libdwarf.so.1:= REALPATH=../../lib/libdwarf.so.1 +$(ROOT)/usr/lib/libdwarf.so:= REALPATH=../../lib/libdwarf.so.1 $(ROOT)/usr/lib/libefi.so.1:= REALPATH=../../lib/libefi.so.1 $(ROOT)/usr/lib/libefi.so:= REALPATH=../../lib/libefi.so.1 $(ROOT)/usr/lib/libelf.so.1:= REALPATH=../../lib/libelf.so.1 @@ -1136,6 +1138,10 @@ $(ROOT)/usr/lib/$(MACH64)/libdoor.so.1:= \ REALPATH=../../../lib/$(MACH64)/libdoor.so.1 $(ROOT)/usr/lib/$(MACH64)/libdoor.so:= \ REALPATH=../../../lib/$(MACH64)/libdoor.so.1 +$(ROOT)/usr/lib/$(MACH64)/libdwarf.so.1:= \ + REALPATH=../../../lib/$(MACH64)/libdwarf.so.1 +$(ROOT)/usr/lib/$(MACH64)/libdwarf.so:= \ + REALPATH=../../../lib/$(MACH64)/libdwarf.so.1 $(ROOT)/usr/lib/$(MACH64)/libefi.so.1:= \ REALPATH=../../../lib/$(MACH64)/libefi.so.1 $(ROOT)/usr/lib/$(MACH64)/libefi.so:= \ @@ -1478,6 +1484,8 @@ SYM.USRLIB= \ /usr/lib/libdlpi.so.1 \ /usr/lib/libdoor.so \ /usr/lib/libdoor.so.1 \ + /usr/lib/libdwarf.so \ + /usr/lib/libdwarf.so.1 \ /usr/lib/libefi.so \ /usr/lib/libefi.so.1 \ /usr/lib/libelf.so \ @@ -1721,6 +1729,8 @@ SYM.USRLIB64= \ /usr/lib/$(MACH64)/libdlpi.so.1 \ /usr/lib/$(MACH64)/libdoor.so \ /usr/lib/$(MACH64)/libdoor.so.1 \ + /usr/lib/$(MACH64)/libdwarf.so \ + /usr/lib/$(MACH64)/libdwarf.so.1 \ /usr/lib/$(MACH64)/libefi.so \ /usr/lib/$(MACH64)/libefi.so.1 \ /usr/lib/$(MACH64)/libelf.so \ diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile index 300f92bf36..36ef810055 100644 --- a/usr/src/cmd/Makefile +++ b/usr/src/cmd/Makefile @@ -106,6 +106,10 @@ COMMON_SUBDIRS= \ crypt \ csh \ csplit \ + ctfconvert \ + ctfdiff \ + ctfdump \ + ctfmerge \ ctrun \ ctstat \ ctwatch \ diff --git a/usr/src/cmd/ctfconvert/Makefile b/usr/src/cmd/ctfconvert/Makefile new file mode 100644 index 0000000000..688addd9d1 --- /dev/null +++ b/usr/src/cmd/ctfconvert/Makefile @@ -0,0 +1,33 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015, Joyent, Inc. +# + +PROG= ctfconvert + +include ../Makefile.cmd + +CFLAGS += $(CCVERBOSE) +LDLIBS += -lctf -lelf + +.KEEP_STATE: + +all: $(PROG) + +install: all $(ROOTPROG) + +clean: + +lint: lint_PROG + +include ../Makefile.targ diff --git a/usr/src/cmd/ctfconvert/ctfconvert.c b/usr/src/cmd/ctfconvert/ctfconvert.c new file mode 100644 index 0000000000..3ff96c5089 --- /dev/null +++ b/usr/src/cmd/ctfconvert/ctfconvert.c @@ -0,0 +1,388 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Create CTF from extant debugging information + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CTFCONVERT_OK 0 +#define CTFCONVERT_FATAL 1 +#define CTFCONVERT_USAGE 2 + +#define CTFCONVERT_DEFAULT_NTHREADS 4 + +#define CTFCONVERT_ALTEXEC "CTFCONVERT_ALTEXEC" + +static char *ctfconvert_progname; + +static void +ctfconvert_fatal(const char *fmt, ...) +{ + va_list ap; + + (void) fprintf(stderr, "%s: ", ctfconvert_progname); + va_start(ap, fmt); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + + exit(CTFCONVERT_FATAL); +} + + +static void +ctfconvert_usage(const char *fmt, ...) +{ + if (fmt != NULL) { + va_list ap; + + (void) fprintf(stderr, "%s: ", ctfconvert_progname); + va_start(ap, fmt); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + } + + (void) fprintf(stderr, "Usage: %s [-is] [-j nthrs] [-l label | " + "-L labelenv] [-o outfile] input\n" + "\n" + "\t-i ignore files not built partially from C sources\n" + "\t-j use nthrs threads to perform the merge\n" + "\t-k keep around original input file on failure\n" + "\t-o copy input to outfile and add CTF\n" + "\t-l set output container's label to specified value\n" + "\t-L set output container's label to value from environment\n", + ctfconvert_progname); +} + +/* + * This is a bit unfortunate. Traditionally we do type uniquification across all + * modules in the kernel, including ip and unix against genunix. However, when + * _MACHDEP is defined, then the cpu_t ends up having an additional member + * (cpu_m), thus changing the ability for us to uniquify against it. This in + * turn causes a lot of type sprawl, as there's a lot of things that end up + * referring to the cpu_t and it chains out from there. + * + * So, if we find that a cpu_t has been defined and it has a couple of useful + * sentinel members and it does *not* have the cpu_m member, then we will try + * and lookup or create a forward declaration to the machcpu, append it to the + * end, and update the file. + * + * This currently is only invoked if an undocumented option -X is passed. This + * value is private to illumos and it can be changed at any time inside of it, + * so if -X wants to be used for something, it should be. The ability to rely on + * -X for others is strictly not an interface in any way, shape, or form. + * + * The following struct contains most of the information that we care about and + * that we want to validate exists before we decide what to do. + */ + +typedef struct ctfconvert_fixup { + boolean_t cf_cyclic; /* Do we have a cpu_cyclic member */ + boolean_t cf_mcpu; /* We have a cpu_m member */ + boolean_t cf_lastpad; /* Is the pad member the last entry */ + ulong_t cf_padoff; /* offset of the pad */ +} ctfconvert_fixup_t; + +/* ARGSUSED */ +static int +ctfconvert_fixup_genunix_cb(const char *name, ctf_id_t tid, ulong_t off, + void *arg) +{ + ctfconvert_fixup_t *cfp = arg; + + cfp->cf_lastpad = B_FALSE; + if (strcmp(name, "cpu_cyclic") == 0) { + cfp->cf_cyclic = B_TRUE; + return (0); + } + + if (strcmp(name, "cpu_m") == 0) { + cfp->cf_mcpu = B_TRUE; + return (0); + } + + if (strcmp(name, "cpu_m_pad") == 0) { + cfp->cf_lastpad = B_TRUE; + cfp->cf_padoff = off; + return (0); + } + + return (0); +} + +static void +ctfconvert_fixup_genunix(ctf_file_t *fp) +{ + ctf_id_t cpuid, mcpu; + ssize_t sz; + ctfconvert_fixup_t cf; + int model, ptrsz; + + cpuid = ctf_lookup_by_name(fp, "struct cpu"); + if (cpuid == CTF_ERR) + return; + + if (ctf_type_kind(fp, cpuid) != CTF_K_STRUCT) + return; + + if ((sz = ctf_type_size(fp, cpuid)) == CTF_ERR) + return; + + model = ctf_getmodel(fp); + VERIFY(model == CTF_MODEL_ILP32 || model == CTF_MODEL_LP64); + ptrsz = model == CTF_MODEL_ILP32 ? 4 : 8; + + bzero(&cf, sizeof (ctfconvert_fixup_t)); + if (ctf_member_iter(fp, cpuid, ctfconvert_fixup_genunix_cb, &cf) == + CTF_ERR) + return; + + /* + * Finally, we want to verify that the cpu_m is actually the last member + * that we have here. + */ + if (cf.cf_cyclic == B_FALSE || cf.cf_mcpu == B_TRUE || + cf.cf_lastpad == B_FALSE) { + return; + } + + if (cf.cf_padoff + ptrsz * NBBY != sz * NBBY) { + return; + } + + /* + * Okay, we're going to do this, try to find a struct machcpu. We either + * want a forward or a struct. If we find something else, error. If we + * find nothing, add a forward and then add the member. + */ + mcpu = ctf_lookup_by_name(fp, "struct machcpu"); + if (mcpu == CTF_ERR) { + mcpu = ctf_add_forward(fp, CTF_ADD_NONROOT, "machcpu", + CTF_K_STRUCT); + if (mcpu == CTF_ERR) { + ctfconvert_fatal("failed to add 'struct machcpu' " + "forward: %s", ctf_errmsg(ctf_errno(fp))); + } + } else { + int kind; + if ((kind = ctf_type_kind(fp, mcpu)) == CTF_ERR) { + ctfconvert_fatal("failed to get the type kind for " + "the struct machcpu: %s", + ctf_errmsg(ctf_errno(fp))); + } + + if (kind != CTF_K_STRUCT && kind != CTF_K_FORWARD) + ctfconvert_fatal("encountered a struct machcpu of the " + "wrong type, found type kind %d\n", kind); + } + + if (ctf_update(fp) == CTF_ERR) { + ctfconvert_fatal("failed to update output file: %s\n", + ctf_errmsg(ctf_errno(fp))); + } + + if (ctf_add_member(fp, cpuid, "cpu_m", mcpu, sz * NBBY) == CTF_ERR) { + ctfconvert_fatal("failed to add the m_cpu member: %s\n", + ctf_errmsg(ctf_errno(fp))); + } + + if (ctf_update(fp) == CTF_ERR) { + ctfconvert_fatal("failed to update output file: %s\n", + ctf_errmsg(ctf_errno(fp))); + } + + VERIFY(ctf_type_size(fp, cpuid) == sz); +} + +static void +ctfconvert_altexec(char **argv) +{ + const char *alt; + char *altexec; + + alt = getenv(CTFCONVERT_ALTEXEC); + if (alt == NULL || *alt == '\0') + return; + + altexec = strdup(alt); + if (altexec == NULL) + ctfconvert_fatal("failed to allocate memory for altexec\n"); + if (unsetenv(CTFCONVERT_ALTEXEC) != 0) + ctfconvert_fatal("failed to unset %s from environment: %s\n", + CTFCONVERT_ALTEXEC, strerror(errno)); + + (void) execv(altexec, argv); + ctfconvert_fatal("failed to execute alternate program %s: %s", + altexec, strerror(errno)); +} + +int +main(int argc, char *argv[]) +{ + int c, ifd, err; + boolean_t keep = B_FALSE; + uint_t flags = 0; + uint_t nthreads = CTFCONVERT_DEFAULT_NTHREADS; + const char *outfile = NULL; + const char *label = NULL; + const char *infile = NULL; + char *tmpfile; + ctf_file_t *ofp; + long argj; + char *eptr; + char buf[4096]; + boolean_t optx = B_FALSE; + + ctfconvert_progname = basename(argv[0]); + + ctfconvert_altexec(argv); + + while ((c = getopt(argc, argv, ":j:kl:L:o:iX")) != -1) { + switch (c) { + case 'k': + keep = B_TRUE; + break; + case 'l': + label = optarg; + break; + case 'L': + label = getenv(optarg); + break; + case 'j': + errno = 0; + argj = strtol(optarg, &eptr, 10); + if (errno != 0 || argj == LONG_MAX || + argj > 1024 || *eptr != '\0') { + ctfconvert_fatal("invalid argument for -j: " + "%s\n", optarg); + } + nthreads = (uint_t)argj; + break; + case 'o': + outfile = optarg; + break; + case 'i': + flags |= CTF_CONVERT_F_IGNNONC; + break; + case 'X': + optx = B_TRUE; + break; + case ':': + ctfconvert_usage("Option -%c requires an operand\n", + optopt); + return (CTFCONVERT_USAGE); + case '?': + ctfconvert_usage("Unknown option: -%c\n", optopt); + return (CTFCONVERT_USAGE); + } + } + + argv += optind; + argc -= optind; + + if (argc < 1) { + ctfconvert_usage("Missing required input file\n"); + return (CTFCONVERT_USAGE); + } + infile = argv[0]; + + if (elf_version(EV_CURRENT) == EV_NONE) + ctfconvert_fatal("failed to initialize libelf: library is " + "out of date\n"); + + ifd = open(infile, O_RDONLY); + if (ifd < 0) { + ctfconvert_fatal("failed to open input file %s: %s\n", infile, + strerror(errno)); + } + + /* + * By default we remove the input file on failure unless we've been + * given an output file or -k has been specified. + */ + if (outfile != NULL && strcmp(infile, outfile) != 0) + keep = B_TRUE; + + ofp = ctf_fdconvert(ifd, label, nthreads, flags, &err, buf, + sizeof (buf)); + if (ofp == NULL) { + /* + * -i says that we shouldn't concern ourselves with source files + * that weren't built from C source code in part. Because this + * has been traditionally used across all of illumos, we still + * honor it. + */ + if ((flags & CTF_CONVERT_F_IGNNONC) != 0 && + err == ECTF_CONVNOCSRC) { + exit(CTFCONVERT_OK); + } + if (keep == B_FALSE) + (void) unlink(infile); + ctfconvert_fatal("CTF conversion failed: %s\n", + err == ECTF_CONVBKERR ? buf : ctf_errmsg(err)); + } + + if (optx == B_TRUE) + ctfconvert_fixup_genunix(ofp); + + tmpfile = NULL; + if (outfile == NULL || strcmp(infile, outfile) == 0) { + if (asprintf(&tmpfile, "%s.ctf", infile) == -1) { + if (keep == B_FALSE) + (void) unlink(infile); + ctfconvert_fatal("failed to allocate memory for " + "temporary file: %s\n", strerror(errno)); + } + outfile = tmpfile; + } + err = ctf_elfwrite(ofp, infile, outfile, CTF_ELFWRITE_F_COMPRESS); + if (err == CTF_ERR) { + (void) unlink(outfile); + if (keep == B_FALSE) + (void) unlink(infile); + ctfconvert_fatal("failed to write CTF section to output file: " + "%s", ctf_errmsg(ctf_errno(ofp))); + } + ctf_close(ofp); + + if (tmpfile != NULL) { + if (rename(tmpfile, infile) != 0) { + int e = errno; + (void) unlink(outfile); + if (keep == B_FALSE) + (void) unlink(infile); + ctfconvert_fatal("failed to rename temporary file: " + "%s\n", strerror(e)); + } + } + free(tmpfile); + + return (CTFCONVERT_OK); +} diff --git a/usr/src/cmd/ctfdiff/Makefile b/usr/src/cmd/ctfdiff/Makefile new file mode 100644 index 0000000000..268bf9f3ed --- /dev/null +++ b/usr/src/cmd/ctfdiff/Makefile @@ -0,0 +1,33 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2015, Joyent, Inc. +# + +PROG= ctfdiff + +include ../Makefile.cmd + +CFLAGS += $(CCVERBOSE) +LDLIBS += -lctf + +.KEEP_STATE: + +all: $(PROG) + +install: all $(ROOTPROG) + +clean: + +lint: lint_PROG + +include ../Makefile.targ diff --git a/usr/src/cmd/ctfdiff/ctfdiff.c b/usr/src/cmd/ctfdiff/ctfdiff.c new file mode 100644 index 0000000000..731fba4af8 --- /dev/null +++ b/usr/src/cmd/ctfdiff/ctfdiff.c @@ -0,0 +1,518 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * diff two CTF containers + */ + +#include +#include +#include +#include +#include +#include +#include + +#define CTFDIFF_NAMELEN 256 + +#define CTFDIFF_EXIT_SIMILAR 0 +#define CTFDIFF_EXIT_DIFFERENT 1 +#define CTFDIFF_EXIT_USAGE 2 +#define CTFDIFF_EXIT_ERROR 3 + +typedef enum ctf_diff_cmd { + CTF_DIFF_TYPES = 0x01, + CTF_DIFF_FUNCS = 0x02, + CTF_DIFF_OBJS = 0x04, + CTF_DIFF_DEFAULT = 0x07, + CTF_DIFF_LABEL = 0x08, + CTF_DIFF_ALL = 0x0f +} ctf_diff_cmd_t; + +typedef struct { + int dil_next; + const char **dil_labels; +} ctfdiff_label_t; + +static char *g_progname; +static const char *g_iname; +static ctf_file_t *g_ifp; +static const char *g_oname; +static ctf_file_t *g_ofp; +static char **g_typelist = NULL; +static int g_nexttype = 0; +static int g_ntypes = 0; +static char **g_objlist = NULL; +static int g_nextfunc = 0; +static int g_nfuncs = 0; +static char **g_funclist = NULL; +static int g_nextobj = 0; +static int g_nobjs = 0; +static boolean_t g_onlydiff = B_FALSE; +static boolean_t g_different = B_FALSE; +static ctf_diff_cmd_t g_flag = 0; + +static void +ctfdiff_fatal(const char *fmt, ...) +{ + va_list ap; + + (void) fprintf(stderr, "%s: ", g_progname); + va_start(ap, fmt); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + + exit(CTFDIFF_EXIT_ERROR); +} + +static const char * +ctfdiff_fp_to_name(ctf_file_t *fp) +{ + if (fp == g_ifp) + return (g_iname); + if (fp == g_ofp) + return (g_oname); + return (NULL); +} + +/* ARGSUSED */ +static void +ctfdiff_func_cb(ctf_file_t *ifp, ulong_t iidx, boolean_t similar, + ctf_file_t *ofp, ulong_t oidx, void *arg) +{ + char namebuf[CTFDIFF_NAMELEN]; + + if (similar == B_TRUE) + return; + + if (ctf_symbol_name(ifp, iidx, namebuf, sizeof (namebuf)) == NULL) { + if (g_nextfunc != 0) + return; + (void) printf("ctf container %s function %lu is different\n", + ctfdiff_fp_to_name(ifp), iidx); + } else { + if (g_nextfunc != 0) { + int i; + for (i = 0; i < g_nextfunc; i++) { + if (strcmp(g_funclist[i], namebuf) == 0) + break; + } + if (i == g_nextfunc) + return; + } + (void) printf("ctf container %s function %s (%lu) is " + "different\n", ctfdiff_fp_to_name(ifp), namebuf, iidx); + } + + g_different = B_TRUE; +} + +/* ARGSUSED */ +static void +ctfdiff_obj_cb(ctf_file_t *ifp, ulong_t iidx, ctf_id_t iid, boolean_t similar, + ctf_file_t *ofp, ulong_t oidx, ctf_id_t oid, void *arg) +{ + char namebuf[CTFDIFF_NAMELEN]; + + if (similar == B_TRUE) + return; + + if (ctf_symbol_name(ifp, iidx, namebuf, sizeof (namebuf)) == NULL) { + if (g_nextobj != 0) + return; + (void) printf("ctf container %s object %lu is different\n", + ctfdiff_fp_to_name(ifp), iidx); + } else { + if (g_nextobj != 0) { + int i; + for (i = 0; i < g_nextobj; i++) { + if (strcmp(g_objlist[i], namebuf) == 0) + break; + } + if (i == g_nextobj) + return; + } + (void) printf("ctf container %s object %s (%lu) is different\n", + ctfdiff_fp_to_name(ifp), namebuf, iidx); + } + + g_different = B_TRUE; +} + +/* ARGSUSED */ +static void +ctfdiff_cb(ctf_file_t *ifp, ctf_id_t iid, boolean_t similar, ctf_file_t *ofp, + ctf_id_t oid, void *arg) +{ + if (similar == B_TRUE) + return; + + if (ctf_type_kind(ifp, iid) == CTF_K_UNKNOWN) + return; + + /* + * Check if it's the type the user cares about. + */ + if (g_nexttype != 0) { + int i; + char namebuf[CTFDIFF_NAMELEN]; + + if (ctf_type_name(ifp, iid, namebuf, sizeof (namebuf)) == + NULL) { + ctfdiff_fatal("failed to obtain the name " + "of type %ld from %s: %s\n", + iid, ctfdiff_fp_to_name(ifp), + ctf_errmsg(ctf_errno(ifp))); + } + + for (i = 0; i < g_nexttype; i++) { + if (strcmp(g_typelist[i], namebuf) == 0) + break; + } + + if (i == g_nexttype) + return; + } + + g_different = B_TRUE; + + if (g_onlydiff == B_TRUE) + return; + + (void) printf("ctf container %s type %ld is different\n", + ctfdiff_fp_to_name(ifp), iid); +} + +/* ARGSUSED */ +static int +ctfdiff_labels_count(const char *name, const ctf_lblinfo_t *li, void *arg) +{ + uint32_t *count = arg; + *count = *count + 1; + + return (0); +} + +/* ARGSUSED */ +static int +ctfdiff_labels_fill(const char *name, const ctf_lblinfo_t *li, void *arg) +{ + ctfdiff_label_t *dil = arg; + + dil->dil_labels[dil->dil_next] = name; + dil->dil_next++; + + return (0); +} + +static int +ctfdiff_labels(ctf_file_t *ifp, ctf_file_t *ofp) +{ + int ret; + uint32_t nilabel, nolabel, i, j; + ctfdiff_label_t idl, odl; + const char **ilptr, **olptr; + + nilabel = nolabel = 0; + ret = ctf_label_iter(ifp, ctfdiff_labels_count, &nilabel); + if (ret == CTF_ERR) + return (ret); + ret = ctf_label_iter(ofp, ctfdiff_labels_count, &nolabel); + if (ret == CTF_ERR) + return (ret); + + if (nilabel != nolabel) { + (void) printf("ctf container %s labels differ from ctf " + "container %s\n", ctfdiff_fp_to_name(ifp), + ctfdiff_fp_to_name(ofp)); + g_different = B_TRUE; + return (0); + } + + if (nilabel == 0) + return (0); + + ilptr = malloc(sizeof (char *) * nilabel); + olptr = malloc(sizeof (char *) * nolabel); + if (ilptr == NULL || olptr == NULL) { + ctfdiff_fatal("failed to allocate memory for label " + "comparison\n"); + } + + idl.dil_next = 0; + idl.dil_labels = ilptr; + odl.dil_next = 0; + odl.dil_labels = olptr; + + if ((ret = ctf_label_iter(ifp, ctfdiff_labels_fill, &idl)) != 0) + goto out; + if ((ret = ctf_label_iter(ofp, ctfdiff_labels_fill, &odl)) != 0) + goto out; + + for (i = 0; i < nilabel; i++) { + for (j = 0; j < nolabel; j++) { + if (strcmp(ilptr[i], olptr[j]) == 0) + break; + } + + if (j == nolabel) { + (void) printf("ctf container %s labels differ from ctf " + "container %s\n", ctfdiff_fp_to_name(ifp), + ctfdiff_fp_to_name(ofp)); + g_different = B_TRUE; + break; + } + } + + ret = 0; +out: + free(ilptr); + free(olptr); + return (ret); +} + +static void +ctfdiff_usage(const char *fmt, ...) +{ + if (fmt != NULL) { + va_list ap; + + (void) fprintf(stderr, "%s: ", g_progname); + va_start(ap, fmt); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + } + + (void) fprintf(stderr, "Usage: %s [-afIloqt] [-F function] [-O object]" + "[-p parent] [-P parent]\n" + "\t[-T type] file1 file2\n" + "\n" + "\t-a diff label, types, objects, and functions\n" + "\t-f diff function type information\n" + "\t-F when diffing functions, only consider those named\n" + "\t-I ignore the names of integral types\n" + "\t-l diff CTF labels\n" + "\t-o diff global object type information\n" + "\t-O when diffing objects, only consider those named\n" + "\t-p set the CTF parent for file1\n" + "\t-P set the CTF parent for file2\n" + "\t-q set quiet mode (no diff information sent to stdout)\n" + "\t-t diff CTF type information\n" + "\t-T when diffing types, only consider those named\n", + g_progname); +} + +int +main(int argc, char *argv[]) +{ + ctf_diff_flag_t flags = 0; + int err, c; + ctf_file_t *ifp, *ofp; + ctf_diff_t *cdp; + ctf_file_t *pifp = NULL; + ctf_file_t *pofp = NULL; + + g_progname = basename(argv[0]); + + while ((c = getopt(argc, argv, ":aqtfolIp:F:O:P:T:")) != -1) { + switch (c) { + case 'a': + g_flag |= CTF_DIFF_ALL; + break; + case 't': + g_flag |= CTF_DIFF_TYPES; + break; + case 'f': + g_flag |= CTF_DIFF_FUNCS; + break; + case 'o': + g_flag |= CTF_DIFF_OBJS; + break; + case 'l': + g_flag |= CTF_DIFF_LABEL; + break; + case 'q': + g_onlydiff = B_TRUE; + break; + case 'p': + pifp = ctf_open(optarg, &err); + if (pifp == NULL) { + ctfdiff_fatal("failed to open parent input " + "container %s: %s\n", optarg, + ctf_errmsg(err)); + } + break; + case 'F': + if (g_nextfunc == g_nfuncs) { + if (g_nfuncs == 0) + g_nfuncs = 16; + else + g_nfuncs *= 2; + g_funclist = realloc(g_funclist, + sizeof (char *) * g_nfuncs); + if (g_funclist == NULL) { + ctfdiff_fatal("failed to allocate " + "memory for the %dth -F option: " + "%s\n", g_nexttype + 1, + strerror(errno)); + } + } + g_funclist[g_nextfunc] = optarg; + g_nextfunc++; + break; + case 'O': + if (g_nextobj == g_nobjs) { + if (g_nobjs == 0) + g_nobjs = 16; + else + g_nobjs *= 2; + g_objlist = realloc(g_objlist, + sizeof (char *) * g_nobjs); + if (g_objlist == NULL) { + ctfdiff_fatal("failed to allocate " + "memory for the %dth -F option: " + "%s\n", g_nexttype + 1, + strerror(errno)); + return (CTFDIFF_EXIT_ERROR); + } + } + g_objlist[g_nextobj] = optarg; + g_nextobj++; + break; + case 'I': + flags |= CTF_DIFF_F_IGNORE_INTNAMES; + break; + case 'P': + pofp = ctf_open(optarg, &err); + if (pofp == NULL) { + ctfdiff_fatal("failed to open parent output " + "container %s: %s\n", optarg, + ctf_errmsg(err)); + } + break; + case 'T': + if (g_nexttype == g_ntypes) { + if (g_ntypes == 0) + g_ntypes = 16; + else + g_ntypes *= 2; + g_typelist = realloc(g_typelist, + sizeof (char *) * g_ntypes); + if (g_typelist == NULL) { + ctfdiff_fatal("failed to allocate " + "memory for the %dth -T option: " + "%s\n", g_nexttype + 1, + strerror(errno)); + } + } + g_typelist[g_nexttype] = optarg; + g_nexttype++; + break; + case ':': + ctfdiff_usage("Option -%c requires an operand\n", + optopt); + return (CTFDIFF_EXIT_USAGE); + case '?': + ctfdiff_usage("Unknown option: -%c\n", optopt); + return (CTFDIFF_EXIT_USAGE); + } + } + + argc -= optind - 1; + argv += optind - 1; + + if (g_flag == 0) + g_flag = CTF_DIFF_DEFAULT; + + if (argc != 3) { + ctfdiff_usage(NULL); + return (CTFDIFF_EXIT_USAGE); + } + + if (g_nexttype != 0 && !(g_flag & CTF_DIFF_TYPES)) { + ctfdiff_usage("-T cannot be used if not diffing types\n"); + return (CTFDIFF_EXIT_USAGE); + } + + if (g_nextfunc != 0 && !(g_flag & CTF_DIFF_FUNCS)) { + ctfdiff_usage("-F cannot be used if not diffing functions\n"); + return (CTFDIFF_EXIT_USAGE); + } + + if (g_nextobj != 0 && !(g_flag & CTF_DIFF_OBJS)) { + ctfdiff_usage("-O cannot be used if not diffing objects\n"); + return (CTFDIFF_EXIT_USAGE); + } + + ifp = ctf_open(argv[1], &err); + if (ifp == NULL) { + ctfdiff_fatal("failed to open %s: %s\n", argv[1], + ctf_errmsg(err)); + } + if (pifp != NULL) { + err = ctf_import(ifp, pifp); + if (err != 0) { + ctfdiff_fatal("failed to set parent container: %s\n", + ctf_errmsg(ctf_errno(pifp))); + } + } + g_iname = argv[1]; + g_ifp = ifp; + + ofp = ctf_open(argv[2], &err); + if (ofp == NULL) { + ctfdiff_fatal("failed to open %s: %s\n", argv[2], + ctf_errmsg(err)); + } + + if (pofp != NULL) { + err = ctf_import(ofp, pofp); + if (err != 0) { + ctfdiff_fatal("failed to set parent container: %s\n", + ctf_errmsg(ctf_errno(pofp))); + } + } + g_oname = argv[2]; + g_ofp = ofp; + + if (ctf_diff_init(ifp, ofp, &cdp) != 0) { + ctfdiff_fatal("failed to initialize libctf diff engine: %s\n", + ctf_errmsg(ctf_errno(ifp))); + } + + if (ctf_diff_setflags(cdp, flags) != 0) { + ctfdiff_fatal("failed to set ctfdiff flags: %s\n", + ctf_errmsg(ctf_errno(ifp))); + } + + err = 0; + if ((g_flag & CTF_DIFF_TYPES) && err != CTF_ERR) + err = ctf_diff_types(cdp, ctfdiff_cb, NULL); + if ((g_flag & CTF_DIFF_FUNCS) && err != CTF_ERR) + err = ctf_diff_functions(cdp, ctfdiff_func_cb, NULL); + if ((g_flag & CTF_DIFF_OBJS) && err != CTF_ERR) + err = ctf_diff_objects(cdp, ctfdiff_obj_cb, NULL); + if ((g_flag & CTF_DIFF_LABEL) && err != CTF_ERR) + err = ctfdiff_labels(ifp, ofp); + + ctf_diff_fini(cdp); + if (err == CTF_ERR) { + ctfdiff_fatal("encountered a libctf error: %s!\n", + ctf_errmsg(ctf_errno(ifp))); + } + + return (g_different == B_TRUE ? CTFDIFF_EXIT_DIFFERENT : + CTFDIFF_EXIT_SIMILAR); +} diff --git a/usr/src/cmd/ctfdump/Makefile b/usr/src/cmd/ctfdump/Makefile new file mode 100644 index 0000000000..37a1ef4cc8 --- /dev/null +++ b/usr/src/cmd/ctfdump/Makefile @@ -0,0 +1,36 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2018 Joyent, Inc. +# + +PROG= ctfdump + +include ../Makefile.cmd + +CFLAGS += $(CCVERBOSE) +LDLIBS += -lctf + +CSTD = $(CSTD_GNU99) +C99LMODE = -Xc99=%all + +.KEEP_STATE: + +all: $(PROG) + +install: all $(ROOTPROG) + +clean: + +lint: lint_PROG + +include ../Makefile.targ diff --git a/usr/src/cmd/ctfdump/ctfdump.c b/usr/src/cmd/ctfdump/ctfdump.c new file mode 100644 index 0000000000..e241c35b47 --- /dev/null +++ b/usr/src/cmd/ctfdump/ctfdump.c @@ -0,0 +1,1235 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2018, Joyent, Inc. + */ + +/* + * Dump information about CTF containers. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_NAMELEN (512) + +typedef enum ctfdump_arg { + CTFDUMP_OBJECTS = 0x001, + CTFDUMP_FUNCTIONS = 0x002, + CTFDUMP_HEADER = 0x004, + CTFDUMP_LABELS = 0x008, + CTFDUMP_STRINGS = 0x010, + CTFDUMP_STATS = 0x020, + CTFDUMP_TYPES = 0x040, + CTFDUMP_DEFAULT = 0x07f, + CTFDUMP_OUTPUT = 0x080, + CTFDUMP_SOURCE = 0x100, +} ctfdump_arg_t; + +typedef struct ctfdump_stat { + ulong_t cs_ndata; /* number of data objects */ + ulong_t cs_nfuncs; /* number of functions */ + ulong_t cs_nfuncargs; /* number of function args */ + ulong_t cs_nfuncmax; /* largest number of args */ + ulong_t cs_ntypes[CTF_K_MAX]; /* number of types */ + ulong_t cs_nsmembs; /* number of struct members */ + ulong_t cs_nsmax; /* largest number of members */ + ulong_t cs_structsz; /* sum of structures sizes */ + ulong_t cs_sszmax; /* largest structure */ + ulong_t cs_numembs; /* number of union members */ + ulong_t cs_numax; /* largest number of members */ + ulong_t cs_unionsz; /* sum of unions sizes */ + ulong_t cs_uszmax; /* largest union */ + ulong_t cs_nemembs; /* number of enum members */ + ulong_t cs_nemax; /* largest number of members */ + ulong_t cs_nstrings; /* number of strings */ + ulong_t cs_strsz; /* string size */ + ulong_t cs_strmax; /* longest string */ +} ctfdump_stat_t; + +typedef struct { + char ci_name[MAX_NAMELEN]; + ctf_id_t ci_id; + ulong_t ci_symidx; + ctf_funcinfo_t ci_funcinfo; +} ctf_idname_t; + +static ctf_idname_t *idnames; +static const char *g_progname; +static ctfdump_arg_t g_dump; +static ctf_file_t *g_fp; +static ctfdump_stat_t g_stats; +static ctf_id_t *g_fargc; +static int g_nfargc; + +static int g_exit = 0; + +static const char *ctfdump_fpenc[] = { + NULL, + "SINGLE", + "DOUBLE", + "COMPLEX", + "DCOMPLEX", + "LDCOMPLEX", + "LDOUBLE", + "INTERVAL", + "DINTERVAL", + "LDINTERVAL", + "IMAGINARY", + "DIMAGINARY", + "LDIMAGINARY" +}; + +/* + * When stats are requested, we have to go through everything. To make our lives + * easier, we'll just always allow the code to print everything out, but only + * output it if we have actually enabled that section. + */ +static void +ctfdump_printf(ctfdump_arg_t arg, const char *fmt, ...) +{ + va_list ap; + + if ((arg & g_dump) == 0) + return; + + va_start(ap, fmt); + (void) vfprintf(stdout, fmt, ap); + va_end(ap); +} + +static void +ctfdump_fatal(const char *fmt, ...) +{ + va_list ap; + + (void) fprintf(stderr, "%s: ", g_progname); + va_start(ap, fmt); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + + exit(1); +} + +static void +ctfdump_usage(const char *fmt, ...) +{ + if (fmt != NULL) { + va_list ap; + (void) fprintf(stderr, "%s: ", g_progname); + va_start(ap, fmt); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + } + + (void) fprintf(stderr, "Usage: %s [-cdfhlsSt] [-p parent] [-u outfile] " + "file\n" + "\n" + "\t-c dump C-style output\n" + "\t-d dump object data\n" + "\t-f dump function data\n" + "\t-h dump the CTF header\n" + "\t-l dump the label table\n" + "\t-p use parent to supply additional information\n" + "\t-s dump the string table\n" + "\t-S dump statistics about the CTF container\n" + "\t-t dump type information\n" + "\t-u dump uncompressed CTF data to outfile\n", + g_progname); +} + +static void +ctfdump_title(ctfdump_arg_t arg, const char *header) +{ + static const char line[] = "----------------------------------------" + "----------------------------------------"; + ctfdump_printf(arg, "\n- %s %.*s\n\n", header, (int)78 - strlen(header), + line); +} + +static int +ctfdump_objects_cb(const char *name, ctf_id_t id, ulong_t symidx, void *arg) +{ + _NOTE(ARGUNUSED(arg)); + + int len; + + len = snprintf(NULL, 0, " [%lu] %ld", g_stats.cs_ndata, id); + ctfdump_printf(CTFDUMP_OBJECTS, " [%lu] %ld %*s%s (%lu)\n", + g_stats.cs_ndata, id, MAX(15 - len, 0), "", name, symidx); + g_stats.cs_ndata++; + return (0); +} + +static void +ctfdump_objects(void) +{ + ctfdump_title(CTFDUMP_OBJECTS, "Data Objects"); + if (ctf_object_iter(g_fp, ctfdump_objects_cb, NULL) == CTF_ERR) { + warnx("failed to dump objects: %s", + ctf_errmsg(ctf_errno(g_fp))); + g_exit = 1; + } +} + +static void +ctfdump_fargs_grow(int nargs) +{ + if (g_nfargc < nargs) { + g_fargc = realloc(g_fargc, sizeof (ctf_id_t) * nargs); + if (g_fargc == NULL) + ctfdump_fatal("failed to get memory for %d " + "ctf_id_t's\n", nargs); + g_nfargc = nargs; + } +} + +static int +ctfdump_functions_cb(const char *name, ulong_t symidx, ctf_funcinfo_t *ctc, + void *arg) +{ + _NOTE(ARGUNUSED(arg)); + int i; + + if (ctc->ctc_argc != 0) { + ctfdump_fargs_grow(ctc->ctc_argc); + if (ctf_func_args(g_fp, symidx, g_nfargc, g_fargc) == CTF_ERR) + ctfdump_fatal("failed to get arguments for function " + "%s: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); + } + + ctfdump_printf(CTFDUMP_FUNCTIONS, + " [%lu] %s (%lu) returns: %ld args: (", g_stats.cs_nfuncs, name, + symidx, ctc->ctc_return); + for (i = 0; i < ctc->ctc_argc; i++) + ctfdump_printf(CTFDUMP_FUNCTIONS, "%ld%s", g_fargc[i], + i + 1 == ctc->ctc_argc ? "" : ", "); + if (ctc->ctc_flags & CTF_FUNC_VARARG) + ctfdump_printf(CTFDUMP_FUNCTIONS, "%s...", + ctc->ctc_argc == 0 ? "" : ", "); + ctfdump_printf(CTFDUMP_FUNCTIONS, ")\n"); + + g_stats.cs_nfuncs++; + g_stats.cs_nfuncargs += ctc->ctc_argc; + g_stats.cs_nfuncmax = MAX(ctc->ctc_argc, g_stats.cs_nfuncmax); + + return (0); +} + +static void +ctfdump_functions(void) +{ + ctfdump_title(CTFDUMP_FUNCTIONS, "Functions"); + + if (ctf_function_iter(g_fp, ctfdump_functions_cb, NULL) == CTF_ERR) { + warnx("failed to dump functions: %s", + ctf_errmsg(ctf_errno(g_fp))); + g_exit = 1; + } +} + +static void +ctfdump_header(void) +{ + const ctf_header_t *hp; + const char *parname, *parlabel; + + ctfdump_title(CTFDUMP_HEADER, "CTF Header"); + ctf_dataptr(g_fp, (const void **)&hp, NULL); + ctfdump_printf(CTFDUMP_HEADER, " cth_magic = 0x%04x\n", + hp->cth_magic); + ctfdump_printf(CTFDUMP_HEADER, " cth_version = %u\n", + hp->cth_version); + ctfdump_printf(CTFDUMP_HEADER, " cth_flags = 0x%02x\n", + ctf_flags(g_fp)); + parname = ctf_parent_name(g_fp); + parlabel = ctf_parent_label(g_fp); + ctfdump_printf(CTFDUMP_HEADER, " cth_parlabel = %s\n", + parlabel == NULL ? "(anon)" : parlabel); + ctfdump_printf(CTFDUMP_HEADER, " cth_parname = %s\n", + parname == NULL ? "(anon)" : parname); + ctfdump_printf(CTFDUMP_HEADER, " cth_lbloff = %u\n", + hp->cth_lbloff); + ctfdump_printf(CTFDUMP_HEADER, " cth_objtoff = %u\n", + hp->cth_objtoff); + ctfdump_printf(CTFDUMP_HEADER, " cth_funcoff = %u\n", + hp->cth_funcoff); + ctfdump_printf(CTFDUMP_HEADER, " cth_typeoff = %u\n", + hp->cth_typeoff); + ctfdump_printf(CTFDUMP_HEADER, " cth_stroff = %u\n", + hp->cth_stroff); + ctfdump_printf(CTFDUMP_HEADER, " cth_strlen = %u\n", + hp->cth_strlen); +} + +static int +ctfdump_labels_cb(const char *name, const ctf_lblinfo_t *li, void *arg) +{ + _NOTE(ARGUNUSED(arg)); + ctfdump_printf(CTFDUMP_LABELS, " %5ld %s\n", li->ctb_typeidx, name); + return (0); +} + +static void +ctfdump_labels(void) +{ + ctfdump_title(CTFDUMP_LABELS, "Label Table"); + if (ctf_label_iter(g_fp, ctfdump_labels_cb, NULL) == CTF_ERR) { + warnx("failed to dump labels: %s", + ctf_errmsg(ctf_errno(g_fp))); + g_exit = 1; + } +} + +static int +ctfdump_strings_cb(const char *s, void *arg) +{ + size_t len = strlen(s) + 1; + ulong_t *stroff = arg; + ctfdump_printf(CTFDUMP_STRINGS, " [%lu] %s\n", *stroff, + *s == '\0' ? "\\0" : s); + *stroff = *stroff + len; + g_stats.cs_nstrings++; + g_stats.cs_strsz += len; + g_stats.cs_strmax = MAX(g_stats.cs_strmax, len); + return (0); +} + +static void +ctfdump_strings(void) +{ + ulong_t stroff = 0; + + ctfdump_title(CTFDUMP_STRINGS, "String Table"); + if (ctf_string_iter(g_fp, ctfdump_strings_cb, &stroff) == CTF_ERR) { + warnx("failed to dump strings: %s", + ctf_errmsg(ctf_errno(g_fp))); + g_exit = 1; + } +} + +static void +ctfdump_stat_int(const char *name, ulong_t value) +{ + ctfdump_printf(CTFDUMP_STATS, " %-36s= %lu\n", name, value); +} + +static void +ctfdump_stat_fp(const char *name, float value) +{ + ctfdump_printf(CTFDUMP_STATS, " %-36s= %.2f\n", name, value); +} + +static void +ctfdump_stats(void) +{ + int i; + ulong_t sum; + + ctfdump_title(CTFDUMP_STATS, "CTF Statistics"); + + ctfdump_stat_int("total number of data objects", g_stats.cs_ndata); + ctfdump_printf(CTFDUMP_STATS, "\n"); + ctfdump_stat_int("total number of functions", g_stats.cs_nfuncs); + ctfdump_stat_int("total number of function arguments", + g_stats.cs_nfuncargs); + ctfdump_stat_int("maximum argument list length", g_stats.cs_nfuncmax); + if (g_stats.cs_nfuncs != 0) + ctfdump_stat_fp("average argument list length", + (float)g_stats.cs_nfuncargs / (float)g_stats.cs_nfuncs); + ctfdump_printf(CTFDUMP_STATS, "\n"); + + sum = 0; + for (i = 0; i < CTF_K_MAX; i++) + sum += g_stats.cs_ntypes[i]; + ctfdump_stat_int("total number of types", sum); + ctfdump_stat_int("total number of integers", + g_stats.cs_ntypes[CTF_K_INTEGER]); + ctfdump_stat_int("total number of floats", + g_stats.cs_ntypes[CTF_K_FLOAT]); + ctfdump_stat_int("total number of pointers", + g_stats.cs_ntypes[CTF_K_POINTER]); + ctfdump_stat_int("total number of arrays", + g_stats.cs_ntypes[CTF_K_ARRAY]); + ctfdump_stat_int("total number of func types", + g_stats.cs_ntypes[CTF_K_FUNCTION]); + ctfdump_stat_int("total number of structs", + g_stats.cs_ntypes[CTF_K_STRUCT]); + ctfdump_stat_int("total number of unions", + g_stats.cs_ntypes[CTF_K_UNION]); + ctfdump_stat_int("total number of enums", + g_stats.cs_ntypes[CTF_K_ENUM]); + ctfdump_stat_int("total number of forward tags", + g_stats.cs_ntypes[CTF_K_FORWARD]); + ctfdump_stat_int("total number of typedefs", + g_stats.cs_ntypes[CTF_K_TYPEDEF]); + ctfdump_stat_int("total number of volatile types", + g_stats.cs_ntypes[CTF_K_VOLATILE]); + ctfdump_stat_int("total number of const types", + g_stats.cs_ntypes[CTF_K_CONST]); + ctfdump_stat_int("total number of restrict types", + g_stats.cs_ntypes[CTF_K_RESTRICT]); + ctfdump_stat_int("total number of unknowns (holes)", + g_stats.cs_ntypes[CTF_K_UNKNOWN]); + + ctfdump_printf(CTFDUMP_STATS, "\n"); + ctfdump_stat_int("total number of struct members", g_stats.cs_nsmembs); + ctfdump_stat_int("maximum number of struct members", g_stats.cs_nsmax); + ctfdump_stat_int("total size of all structs", g_stats.cs_structsz); + ctfdump_stat_int("maximum size of a struct", g_stats.cs_sszmax); + if (g_stats.cs_ntypes[CTF_K_STRUCT] != 0) { + ctfdump_stat_fp("average number of struct members", + (float)g_stats.cs_nsmembs / + (float)g_stats.cs_ntypes[CTF_K_STRUCT]); + ctfdump_stat_fp("average size of a struct", + (float)g_stats.cs_structsz / + (float)g_stats.cs_ntypes[CTF_K_STRUCT]); + } + ctfdump_printf(CTFDUMP_STATS, "\n"); + ctfdump_stat_int("total number of union members", g_stats.cs_numembs); + ctfdump_stat_int("maximum number of union members", g_stats.cs_numax); + ctfdump_stat_int("total size of all unions", g_stats.cs_unionsz); + ctfdump_stat_int("maximum size of a union", g_stats.cs_uszmax); + if (g_stats.cs_ntypes[CTF_K_UNION] != 0) { + ctfdump_stat_fp("average number of union members", + (float)g_stats.cs_numembs / + (float)g_stats.cs_ntypes[CTF_K_UNION]); + ctfdump_stat_fp("average size of a union", + (float)g_stats.cs_unionsz / + (float)g_stats.cs_ntypes[CTF_K_UNION]); + } + ctfdump_printf(CTFDUMP_STATS, "\n"); + + ctfdump_stat_int("total number of enum members", g_stats.cs_nemembs); + ctfdump_stat_int("maximum number of enum members", g_stats.cs_nemax); + if (g_stats.cs_ntypes[CTF_K_ENUM] != 0) { + ctfdump_stat_fp("average number of enum members", + (float)g_stats.cs_nemembs / + (float)g_stats.cs_ntypes[CTF_K_ENUM]); + } + ctfdump_printf(CTFDUMP_STATS, "\n"); + + ctfdump_stat_int("total number of strings", g_stats.cs_nstrings); + ctfdump_stat_int("bytes of string data", g_stats.cs_strsz); + ctfdump_stat_int("maximum string length", g_stats.cs_strmax); + if (g_stats.cs_nstrings != 0) + ctfdump_stat_fp("average string length", + (float)g_stats.cs_strsz / (float)g_stats.cs_nstrings); + ctfdump_printf(CTFDUMP_STATS, "\n"); +} + +static void +ctfdump_intenc_name(ctf_encoding_t *cte, char *buf, int len) +{ + int off = 0; + boolean_t space = B_FALSE; + + if (cte->cte_format == 0 || (cte->cte_format & + ~(CTF_INT_SIGNED | CTF_INT_CHAR | CTF_INT_BOOL | + CTF_INT_VARARGS)) != 0) { + (void) snprintf(buf, len, "0x%x", cte->cte_format); + return; + } + + if (cte->cte_format & CTF_INT_SIGNED) { + off += snprintf(buf + off, MAX(len - off, 0), "%sSIGNED", + space == B_TRUE ? " " : ""); + space = B_TRUE; + } + + if (cte->cte_format & CTF_INT_CHAR) { + off += snprintf(buf + off, MAX(len - off, 0), "%sCHAR", + space == B_TRUE ? " " : ""); + space = B_TRUE; + } + + if (cte->cte_format & CTF_INT_BOOL) { + off += snprintf(buf + off, MAX(len - off, 0), "%sBOOL", + space == B_TRUE ? " " : ""); + space = B_TRUE; + } + + if (cte->cte_format & CTF_INT_VARARGS) { + off += snprintf(buf + off, MAX(len - off, 0), "%sVARARGS", + space == B_TRUE ? " " : ""); + space = B_TRUE; + } +} + +static int +ctfdump_member_cb(const char *member, ctf_id_t type, ulong_t off, void *arg) +{ + int *count = arg; + ctfdump_printf(CTFDUMP_TYPES, "\t%s type=%ld off=%lu\n", member, type, + off); + *count = *count + 1; + return (0); +} + +static int +ctfdump_enum_cb(const char *name, int value, void *arg) +{ + int *count = arg; + ctfdump_printf(CTFDUMP_TYPES, "\t%s = %d\n", name, value); + *count = *count + 1; + return (0); +} + +static int +ctfdump_types_cb(ctf_id_t id, boolean_t root, void *arg) +{ + _NOTE(ARGUNUSED(arg)); + int kind, i, count; + ctf_id_t ref; + char name[MAX_NAMELEN], ienc[128]; + const char *encn; + ctf_funcinfo_t ctc; + ctf_arinfo_t ar; + ctf_encoding_t cte; + ssize_t size; + + if ((kind = ctf_type_kind(g_fp, id)) == CTF_ERR) + ctfdump_fatal("encountered malformed ctf, type %s does not " + "have a kind: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); + + if (ctf_type_name(g_fp, id, name, sizeof (name)) == NULL) { + if (ctf_errno(g_fp) != ECTF_NOPARENT) + ctfdump_fatal("type %ld missing name: %s\n", id, + ctf_errmsg(ctf_errno(g_fp))); + (void) snprintf(name, sizeof (name), "(unknown %s)", + ctf_kind_name(g_fp, kind)); + } + + g_stats.cs_ntypes[kind]++; + if (root == B_TRUE) + ctfdump_printf(CTFDUMP_TYPES, " <%ld> ", id); + else + ctfdump_printf(CTFDUMP_TYPES, " [%ld] ", id); + + switch (kind) { + case CTF_K_UNKNOWN: + break; + case CTF_K_INTEGER: + if (ctf_type_encoding(g_fp, id, &cte) == CTF_ERR) + ctfdump_fatal("failed to get encoding information " + "for %s: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); + ctfdump_intenc_name(&cte, ienc, sizeof (ienc)); + ctfdump_printf(CTFDUMP_TYPES, + "%s encoding=%s offset=%u bits=%u", + name, ienc, cte.cte_offset, cte.cte_bits); + break; + case CTF_K_FLOAT: + if (ctf_type_encoding(g_fp, id, &cte) == CTF_ERR) + ctfdump_fatal("failed to get encoding information " + "for %s: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); + if (cte.cte_format < 1 || cte.cte_format > 12) + encn = "unknown"; + else + encn = ctfdump_fpenc[cte.cte_format]; + ctfdump_printf(CTFDUMP_TYPES, "%s encoding=%s offset=%u " + "bits=%u", name, encn, cte.cte_offset, cte.cte_bits); + break; + case CTF_K_POINTER: + if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) + ctfdump_fatal("failed to get reference type for %s: " + "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); + ctfdump_printf(CTFDUMP_TYPES, "%s refers to %ld", name, + ref); + break; + case CTF_K_ARRAY: + if (ctf_array_info(g_fp, id, &ar) == CTF_ERR) + ctfdump_fatal("failed to get array information for " + "%s: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); + ctfdump_printf(CTFDUMP_TYPES, "%s contents: %ld, index: %ld", + name, ar.ctr_contents, ar.ctr_index); + break; + case CTF_K_FUNCTION: + if (ctf_func_info_by_id(g_fp, id, &ctc) == CTF_ERR) + ctfdump_fatal("failed to get function info for %s: " + "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); + if (ctc.ctc_argc > 0) { + ctfdump_fargs_grow(ctc.ctc_argc); + if (ctf_func_args_by_id(g_fp, id, g_nfargc, g_fargc) == + CTF_ERR) + ctfdump_fatal("failed to get function " + "arguments for %s: %s\n", name, + ctf_errmsg(ctf_errno(g_fp))); + } + ctfdump_printf(CTFDUMP_TYPES, + "%s returns: %ld args: (", name, ctc.ctc_return); + for (i = 0; i < ctc.ctc_argc; i++) { + ctfdump_printf(CTFDUMP_TYPES, "%ld%s", g_fargc[i], + i + 1 == ctc.ctc_argc ? "" : ", "); + } + if (ctc.ctc_flags & CTF_FUNC_VARARG) + ctfdump_printf(CTFDUMP_TYPES, "%s...", + ctc.ctc_argc == 0 ? "" : ", "); + ctfdump_printf(CTFDUMP_TYPES, ")"); + break; + case CTF_K_STRUCT: + case CTF_K_UNION: + size = ctf_type_size(g_fp, id); + if (size == CTF_ERR) + ctfdump_fatal("failed to get size of %s: %s\n", name, + ctf_errmsg(ctf_errno(g_fp))); + ctfdump_printf(CTFDUMP_TYPES, "%s (%zd bytes)\n", name, size); + count = 0; + if (ctf_member_iter(g_fp, id, ctfdump_member_cb, &count) != 0) + ctfdump_fatal("failed to iterate members of %s: %s\n", + name, ctf_errmsg(ctf_errno(g_fp))); + if (kind == CTF_K_STRUCT) { + g_stats.cs_nsmembs += count; + g_stats.cs_nsmax = MAX(count, g_stats.cs_nsmax); + g_stats.cs_structsz += size; + g_stats.cs_sszmax = MAX(size, g_stats.cs_sszmax); + } else { + g_stats.cs_numembs += count; + g_stats.cs_numax = MAX(count, g_stats.cs_numax); + g_stats.cs_unionsz += size; + g_stats.cs_uszmax = MAX(count, g_stats.cs_uszmax); + } + break; + case CTF_K_ENUM: + ctfdump_printf(CTFDUMP_TYPES, "%s\n", name); + count = 0; + if (ctf_enum_iter(g_fp, id, ctfdump_enum_cb, &count) != 0) + ctfdump_fatal("failed to iterate enumerators of %s: " + "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); + g_stats.cs_nemembs += count; + g_stats.cs_nemax = MAX(g_stats.cs_nemax, count); + break; + case CTF_K_FORWARD: + ctfdump_printf(CTFDUMP_TYPES, "forward %s\n", name); + break; + case CTF_K_TYPEDEF: + if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) + ctfdump_fatal("failed to get reference type for %s: " + "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); + ctfdump_printf(CTFDUMP_TYPES, "typedef %s refers to %ld", name, + ref); + break; + case CTF_K_VOLATILE: + if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) + ctfdump_fatal("failed to get reference type for %s: " + "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); + ctfdump_printf(CTFDUMP_TYPES, "%s refers to %ld", name, + ref); + break; + case CTF_K_CONST: + if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) + ctfdump_fatal("failed to get reference type for %s: " + "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); + ctfdump_printf(CTFDUMP_TYPES, "%s refers to %ld", name, + ref); + break; + case CTF_K_RESTRICT: + if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) + ctfdump_fatal("failed to get reference type for %s: " + "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); + ctfdump_printf(CTFDUMP_TYPES, "%s refers to %ld", name, + ref); + break; + default: + ctfdump_fatal("encountered unknown kind for type %s: %d\n", + name, kind); + } + + ctfdump_printf(CTFDUMP_TYPES, "\n"); + + return (0); +} + +static void +ctfdump_types(void) +{ + ctfdump_title(CTFDUMP_TYPES, "Types"); + + if (ctf_type_iter(g_fp, B_TRUE, ctfdump_types_cb, NULL) == CTF_ERR) { + warnx("failed to dump types: %s", + ctf_errmsg(ctf_errno(g_fp))); + g_exit = 1; + } +} + +/* + * C-style output. This is designed mainly for comparison purposes, and doesn't + * produce directly valid C: + * + * - the declarations are sorted alphabetically not semantically + * - anonymous enums without other users are elided (e.g. IDCS_PROBE_SENT) + * - doubly-pointed-to functions are wrong (e.g. in kiconv_ops_t) + * - anon unions declared within SOUs aren't expanded + * - function arguments aren't expanded recursively + */ + +static void +ctfsrc_refname(ctf_id_t id, char *buf, size_t bufsize) +{ + ctf_id_t ref; + + if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) { + ctfdump_fatal("failed to get reference type for %ld: " + "%s\n", id, ctf_errmsg(ctf_errno(g_fp))); + } + + (void) ctf_type_name(g_fp, ref, buf, bufsize); +} + +static int +ctfsrc_member_cb(const char *member, ctf_id_t type, ulong_t off, void *arg) +{ + _NOTE(ARGUNUSED(arg)); + char name[MAX_NAMELEN]; + + if (ctf_type_cname(g_fp, type, name, sizeof (name), member) == NULL) { + if (ctf_errno(g_fp) != ECTF_NOPARENT) { + ctfdump_fatal("type %ld missing name: %s\n", type, + ctf_errmsg(ctf_errno(g_fp))); + } + + (void) snprintf(name, sizeof (name), "unknown_t %s", member); + } + + /* + * A byte offset is friendlier, but we'll print bits too if it's not + * aligned (i.e. a bitfield). + */ + if (off % NBBY != 0) { + (void) printf("\t%s; /* offset: %lu bytes (%lu bits) */\n", + name, off / NBBY, off); + } else { + (void) printf("\t%s; /* offset: %lu bytes */\n", + name, off / NBBY); + } + return (0); +} + +static int +ctfsrc_enum_cb(const char *name, int value, void *arg) +{ + _NOTE(ARGUNUSED(arg)); + (void) printf("\t%s = %d,\n", name, value); + return (0); +} + +static int +is_anon_refname(const char *refname) +{ + return ((strcmp(refname, "struct ") == 0 || + strcmp(refname, "union ") == 0 || + strcmp(refname, "enum ") == 0)); +} + +static int +ctfsrc_collect_types_cb(ctf_id_t id, boolean_t root, void *arg) +{ + _NOTE(ARGUNUSED(root, arg)); + (void) ctf_type_name(g_fp, id, idnames[id].ci_name, + sizeof (idnames[id].ci_name)); + idnames[id].ci_id = id; + return (0); +} + +static void +ctfsrc_type(ctf_id_t id, const char *name) +{ + char refname[MAX_NAMELEN]; + ctf_id_t ref; + ssize_t size; + int kind; + + if ((kind = ctf_type_kind(g_fp, id)) == CTF_ERR) { + ctfdump_fatal("encountered malformed ctf, type %s does not " + "have a kind: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); + } + + switch (kind) { + case CTF_K_STRUCT: + case CTF_K_UNION: + /* + * Delay printing anonymous SOUs; a later typedef will usually + * pick them up. + */ + if (is_anon_refname(name)) + break; + + if ((size = ctf_type_size(g_fp, id)) == CTF_ERR) { + ctfdump_fatal("failed to get size of %s: %s\n", name, + ctf_errmsg(ctf_errno(g_fp))); + } + + (void) printf("%s { /* 0x%x bytes */\n", name, size); + + if (ctf_member_iter(g_fp, id, ctfsrc_member_cb, NULL) != 0) { + ctfdump_fatal("failed to iterate members of %s: %s\n", + name, ctf_errmsg(ctf_errno(g_fp))); + } + + (void) printf("};\n\n"); + break; + case CTF_K_ENUM: + /* + * This will throw away any anon enum that isn't followed by a + * typedef... + */ + if (is_anon_refname(name)) + break; + + (void) printf("%s {\n", name); + + if (ctf_enum_iter(g_fp, id, ctfsrc_enum_cb, NULL) != 0) { + ctfdump_fatal("failed to iterate enumerators of %s: " + "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); + } + + (void) printf("};\n\n"); + break; + case CTF_K_TYPEDEF: + ctfsrc_refname(id, refname, sizeof (refname)); + + if (!is_anon_refname(refname)) { + (void) ctf_type_cname(g_fp, + ctf_type_reference(g_fp, id), refname, + sizeof (refname), name); + + (void) printf("typedef %s;\n\n", refname); + break; + } + + ref = ctf_type_reference(g_fp, id); + + if (ctf_type_kind(g_fp, ref) == CTF_K_ENUM) { + (void) printf("typedef enum {\n"); + + if (ctf_enum_iter(g_fp, ref, + ctfsrc_enum_cb, NULL) != 0) { + ctfdump_fatal("failed to iterate enumerators " + "of %s: %s\n", refname, + ctf_errmsg(ctf_errno(g_fp))); + } + + (void) printf("} %s;\n\n", name); + } else { + if ((size = ctf_type_size(g_fp, ref)) == CTF_ERR) { + ctfdump_fatal("failed to get size of %s: %s\n", + refname, ctf_errmsg(ctf_errno(g_fp))); + } + + (void) printf("typedef %s{ /* 0x%zx bytes */\n", + refname, size); + + if (ctf_member_iter(g_fp, ref, + ctfsrc_member_cb, NULL) != 0) { + ctfdump_fatal("failed to iterate members " + "of %s: %s\n", refname, + ctf_errmsg(ctf_errno(g_fp))); + } + + (void) printf("} %s;\n\n", name); + } + + break; + case CTF_K_FORWARD: + (void) printf("%s;\n\n", name); + break; + case CTF_K_UNKNOWN: + case CTF_K_INTEGER: + case CTF_K_FLOAT: + case CTF_K_POINTER: + case CTF_K_ARRAY: + case CTF_K_FUNCTION: + case CTF_K_VOLATILE: + case CTF_K_CONST: + case CTF_K_RESTRICT: + break; + default: + ctfdump_fatal("encountered unknown kind for type %s: %d\n", + name, kind); + break; + } +} + +static int +ctfsrc_collect_objects_cb(const char *name, ctf_id_t id, + ulong_t symidx, void *arg) +{ + size_t *count = arg; + + /* local static vars can have an unknown ID */ + if (id == 0) + return (0); + + (void) strlcpy(idnames[*count].ci_name, name, + sizeof (idnames[*count].ci_name)); + idnames[*count].ci_id = id; + idnames[*count].ci_symidx = symidx; + *count = *count + 1; + return (0); +} + +static void +ctfsrc_object(ctf_id_t id, const char *name) +{ + char tname[MAX_NAMELEN]; + + if (ctf_type_cname(g_fp, id, tname, sizeof (tname), name) == NULL) { + if (ctf_errno(g_fp) != ECTF_NOPARENT) { + ctfdump_fatal("type %ld missing name: %s\n", id, + ctf_errmsg(ctf_errno(g_fp))); + } + (void) snprintf(tname, sizeof (tname), "unknown_t %s", name); + } + + (void) printf("extern %s;\n", tname); +} + +static int +ctfsrc_collect_functions_cb(const char *name, ulong_t symidx, + ctf_funcinfo_t *ctc, void *arg) +{ + size_t *count = arg; + + (void) strlcpy(idnames[*count].ci_name, name, + sizeof (idnames[*count].ci_name)); + bcopy(ctc, &idnames[*count].ci_funcinfo, sizeof (*ctc)); + idnames[*count].ci_id = 0; + idnames[*count].ci_symidx = symidx; + *count = *count + 1; + return (0); +} + +static void +ctfsrc_function(ctf_idname_t *idn) +{ + ctf_funcinfo_t *cfi = &idn->ci_funcinfo; + char name[MAX_NAMELEN] = "unknown_t"; + + (void) ctf_type_name(g_fp, cfi->ctc_return, name, sizeof (name)); + + (void) printf("extern %s %s(", name, idn->ci_name); + + if (cfi->ctc_argc != 0) { + ctfdump_fargs_grow(cfi->ctc_argc); + if (ctf_func_args(g_fp, idn->ci_symidx, + g_nfargc, g_fargc) == CTF_ERR) { + ctfdump_fatal("failed to get arguments for function " + "%s: %s\n", idn->ci_name, + ctf_errmsg(ctf_errno(g_fp))); + } + + for (size_t i = 0; i < cfi->ctc_argc; i++) { + ctf_id_t aid = g_fargc[i]; + + name[0] = '\0'; + + (void) ctf_type_name(g_fp, aid, name, sizeof (name)); + + (void) printf("%s%s", name, + i + 1 == cfi->ctc_argc ? "" : ", "); + } + } else { + if (!(cfi->ctc_flags & CTF_FUNC_VARARG)) + (void) printf("void"); + } + + if (cfi->ctc_flags & CTF_FUNC_VARARG) + (void) printf("%s...", cfi->ctc_argc == 0 ? "" : ", "); + + (void) printf(");\n"); +} + +static int +idname_compare(const void *lhs, const void *rhs) +{ + return (strcmp(((ctf_idname_t *)lhs)->ci_name, + ((ctf_idname_t *)rhs)->ci_name)); +} + +static void +ctfdump_source(void) +{ + ulong_t nr_syms = ctf_nr_syms(g_fp); + ctf_id_t max_id = ctf_max_id(g_fp); + size_t count = 0; + + (void) printf("/* Types */\n\n"); + + if ((idnames = calloc(max_id + 1, sizeof (idnames[0]))) == NULL) { + ctfdump_fatal("failed to alloc idnames: %s\n", + strerror(errno)); + } + + if (ctf_type_iter(g_fp, B_FALSE, ctfsrc_collect_types_cb, + idnames) == CTF_ERR) { + warnx("failed to collect types: %s", + ctf_errmsg(ctf_errno(g_fp))); + g_exit = 1; + } + + qsort(idnames, max_id, sizeof (ctf_idname_t), idname_compare); + + for (size_t i = 0; i < max_id; i++) { + if (idnames[i].ci_id != 0) + ctfsrc_type(idnames[i].ci_id, idnames[i].ci_name); + } + + free(idnames); + + (void) printf("\n\n/* Data Objects */\n\n"); + + if ((idnames = calloc(nr_syms, sizeof (idnames[0]))) == NULL) { + ctfdump_fatal("failed to alloc idnames: %s\n", + strerror(errno)); + } + + if (ctf_object_iter(g_fp, ctfsrc_collect_objects_cb, + &count) == CTF_ERR) { + warnx("failed to collect objects: %s", + ctf_errmsg(ctf_errno(g_fp))); + g_exit = 1; + } + + qsort(idnames, count, sizeof (ctf_idname_t), idname_compare); + + for (size_t i = 0; i < count; i++) + ctfsrc_object(idnames[i].ci_id, idnames[i].ci_name); + + free(idnames); + + (void) printf("\n\n/* Functions */\n\n"); + + if ((idnames = calloc(nr_syms, sizeof (idnames[0]))) == NULL) { + ctfdump_fatal("failed to alloc idnames: %s\n", + strerror(errno)); + } + + count = 0; + + if (ctf_function_iter(g_fp, ctfsrc_collect_functions_cb, + &count) == CTF_ERR) { + warnx("failed to collect functions: %s", + ctf_errmsg(ctf_errno(g_fp))); + g_exit = 1; + } + + qsort(idnames, count, sizeof (ctf_idname_t), idname_compare); + + for (size_t i = 0; i < count; i++) + ctfsrc_function(&idnames[i]); + + free(idnames); +} + +static void +ctfdump_output(const char *out) +{ + int fd, ret; + const void *data; + size_t len; + + ctf_dataptr(g_fp, &data, &len); + if ((fd = open(out, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) + ctfdump_fatal("failed to open output file %s: %s\n", out, + strerror(errno)); + + while (len > 0) { + ret = write(fd, data, len); + if (ret == -1 && errno == EINTR) + continue; + else if (ret == -1 && (errno == EFAULT || errno == EBADF)) + abort(); + else if (ret == -1) + ctfdump_fatal("failed to write to %s: %s\n", out, + strerror(errno)); + data = ((char *)data) + ret; + len -= ret; + } + + do { + ret = close(fd); + } while (ret == -1 && errno == EINTR); + if (ret != 0 && errno == EBADF) + abort(); + if (ret != 0) + ctfdump_fatal("failed to close %s: %s\n", out, strerror(errno)); +} + +int +main(int argc, char *argv[]) +{ + int c, fd, err; + const char *ufile = NULL, *parent = NULL; + + g_progname = basename(argv[0]); + while ((c = getopt(argc, argv, ":cdfhlp:sStu:")) != -1) { + switch (c) { + case 'c': + g_dump |= CTFDUMP_SOURCE; + break; + case 'd': + g_dump |= CTFDUMP_OBJECTS; + break; + case 'f': + g_dump |= CTFDUMP_FUNCTIONS; + break; + case 'h': + g_dump |= CTFDUMP_HEADER; + break; + case 'l': + g_dump |= CTFDUMP_LABELS; + break; + case 'p': + parent = optarg; + break; + case 's': + g_dump |= CTFDUMP_STRINGS; + break; + case 'S': + g_dump |= CTFDUMP_STATS; + break; + case 't': + g_dump |= CTFDUMP_TYPES; + break; + case 'u': + g_dump |= CTFDUMP_OUTPUT; + ufile = optarg; + break; + case '?': + ctfdump_usage("Unknown option: -%c\n", optopt); + return (2); + case ':': + ctfdump_usage("Option -%c requires an operand\n", + optopt); + return (2); + } + } + + argc -= optind; + argv += optind; + + if ((g_dump & CTFDUMP_SOURCE) && !!(g_dump & ~CTFDUMP_SOURCE)) { + ctfdump_usage("-c must be specified on its own\n"); + return (2); + } + + /* + * Dump all information except C source by default. + */ + if (g_dump == 0) + g_dump = CTFDUMP_DEFAULT; + + if (argc != 1) { + ctfdump_usage("no file to dump\n"); + return (2); + } + + if ((fd = open(argv[0], O_RDONLY)) < 0) + ctfdump_fatal("failed to open file %s: %s\n", argv[0], + strerror(errno)); + + g_fp = ctf_fdopen(fd, &err); + if (g_fp == NULL) + ctfdump_fatal("failed to open file %s: %s\n", argv[0], + ctf_errmsg(err)); + + /* + * Check to see if this file needs a parent. If it does not and we were + * given one, that should be an error. If it does need one and the + * parent is not specified, that is fine, we just won't know how to + * find child types. If we are given a parent, check at least that the + * labels match. + */ + if (ctf_parent_name(g_fp) == NULL) { + if (parent != NULL) + ctfdump_fatal("cannot use %s as a parent file, %s is " + "not a child\n", parent, argv[0]); + } else if (parent != NULL) { + const char *explabel, *label; + ctf_file_t *pfp = ctf_open(parent, &err); + + if (pfp == NULL) + ctfdump_fatal("failed to open parent file %s: %s\n", + parent, ctf_errmsg(err)); + + /* + * Before we import the parent into the child, check that the + * labels match. While there is also the notion of the parent + * name, it's less straightforward to match that. Require that + * labels match. + */ + explabel = ctf_parent_label(g_fp); + label = ctf_label_topmost(pfp); + if (explabel == NULL || label == NULL || + strcmp(explabel, label) != 0) { + if (label == NULL) + label = ""; + if (explabel == NULL) + explabel = ""; + ctfdump_fatal("label mismatch between parent %s and " + "child %s, parent has %s, child expects %s\n", + parent, argv[0], label, explabel); + } + + if (ctf_import(g_fp, pfp) != 0) + ctfdump_fatal("failed to import parent %s: %s\n", + parent, ctf_errmsg(ctf_errno(g_fp))); + } + + if (g_dump & CTFDUMP_SOURCE) { + ctfdump_source(); + return (0); + } + + /* + * If stats is set, we must run through everything exect CTFDUMP_OUTPUT. + * We also do CTFDUMP_STATS last as a result. + */ + if (g_dump & CTFDUMP_HEADER) + ctfdump_header(); + + if (g_dump & (CTFDUMP_LABELS | CTFDUMP_STATS)) + ctfdump_labels(); + + if (g_dump & (CTFDUMP_OBJECTS | CTFDUMP_STATS)) + ctfdump_objects(); + + if (g_dump & (CTFDUMP_FUNCTIONS | CTFDUMP_STATS)) + ctfdump_functions(); + + if (g_dump & (CTFDUMP_TYPES | CTFDUMP_STATS)) + ctfdump_types(); + + if (g_dump & (CTFDUMP_STRINGS | CTFDUMP_STATS)) + ctfdump_strings(); + + if (g_dump & CTFDUMP_STATS) + ctfdump_stats(); + + if (g_dump & CTFDUMP_OUTPUT) + ctfdump_output(ufile); + + return (g_exit); +} diff --git a/usr/src/cmd/ctfmerge/Makefile b/usr/src/cmd/ctfmerge/Makefile new file mode 100644 index 0000000000..8f156c9c48 --- /dev/null +++ b/usr/src/cmd/ctfmerge/Makefile @@ -0,0 +1,33 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015, Joyent, Inc. +# + +PROG= ctfmerge + +include ../Makefile.cmd + +CFLAGS += $(CCVERBOSE) +LDLIBS += -lctf -lelf + +.KEEP_STATE: + +all: $(PROG) + +install: all $(ROOTPROG) + +clean: + +lint: lint_PROG + +include ../Makefile.targ diff --git a/usr/src/cmd/ctfmerge/ctfmerge.c b/usr/src/cmd/ctfmerge/ctfmerge.c new file mode 100644 index 0000000000..1257fd16c9 --- /dev/null +++ b/usr/src/cmd/ctfmerge/ctfmerge.c @@ -0,0 +1,536 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2017, Joyent, Inc. + */ + +/* + * merge CTF containers + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static char *g_progname; +static char *g_unique; +static char *g_outfile; +static boolean_t g_req; +static uint_t g_nctf; + +#define CTFMERGE_OK 0 +#define CTFMERGE_FATAL 1 +#define CTFMERGE_USAGE 2 + +#define CTFMERGE_DEFAULT_NTHREADS 8 +#define CTFMERGE_ALTEXEC "CTFMERGE_ALTEXEC" + +static void +ctfmerge_fatal(const char *fmt, ...) +{ + va_list ap; + + (void) fprintf(stderr, "%s: ", g_progname); + va_start(ap, fmt); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + + if (g_outfile != NULL) + (void) unlink(g_outfile); + + exit(CTFMERGE_FATAL); +} + +static boolean_t +ctfmerge_expect_ctf(const char *name, Elf *elf) +{ + Elf_Scn *scn, *strscn; + Elf_Data *data, *strdata; + GElf_Shdr shdr; + ulong_t i; + + if (g_req == B_FALSE) + return (B_FALSE); + + scn = NULL; + while ((scn = elf_nextscn(elf, scn)) != NULL) { + if (gelf_getshdr(scn, &shdr) == NULL) { + ctfmerge_fatal("failed to get section header for file " + "%s: %s\n", name, elf_errmsg(elf_errno())); + } + + if (shdr.sh_type == SHT_SYMTAB) + break; + } + + if (scn == NULL) + return (B_FALSE); + + if ((strscn = elf_getscn(elf, shdr.sh_link)) == NULL) + ctfmerge_fatal("failed to get section header for file %s: %s\n", + name, elf_errmsg(elf_errno())); + + if ((data = elf_getdata(scn, NULL)) == NULL) + ctfmerge_fatal("failed to read symbol table for %s: %s\n", + name, elf_errmsg(elf_errno())); + + if ((strdata = elf_getdata(strscn, NULL)) == NULL) + ctfmerge_fatal("failed to read string table for %s: %s\n", + name, elf_errmsg(elf_errno())); + + for (i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) { + GElf_Sym sym; + const char *file; + size_t len; + + if (gelf_getsym(data, i, &sym) == NULL) + ctfmerge_fatal("failed to read symbol table entry %lu " + "for %s: %s\n", i, name, elf_errmsg(elf_errno())); + + if (GELF_ST_TYPE(sym.st_info) != STT_FILE) + continue; + + file = (const char *)((uintptr_t)strdata->d_buf + sym.st_name); + len = strlen(file); + if (len < 2 || name[len - 2] != '.') + continue; + + if (name[len - 1] == 'c') + return (B_TRUE); + } + + return (B_FALSE); +} + +/* + * Go through and construct enough information for this Elf Object to try and do + * a ctf_bufopen(). + */ +static void +ctfmerge_elfopen(const char *name, Elf *elf, ctf_merge_t *cmh) +{ + GElf_Ehdr ehdr; + GElf_Shdr shdr; + Elf_Scn *scn; + Elf_Data *ctf_data, *str_data, *sym_data; + ctf_sect_t ctfsect, symsect, strsect; + ctf_file_t *fp; + int err; + + if (gelf_getehdr(elf, &ehdr) == NULL) + ctfmerge_fatal("failed to get ELF header for %s: %s\n", + name, elf_errmsg(elf_errno())); + + bzero(&ctfsect, sizeof (ctf_sect_t)); + bzero(&symsect, sizeof (ctf_sect_t)); + bzero(&strsect, sizeof (ctf_sect_t)); + + scn = NULL; + while ((scn = elf_nextscn(elf, scn)) != NULL) { + const char *sname; + + if (gelf_getshdr(scn, &shdr) == NULL) + ctfmerge_fatal("failed to get section header for " + "file %s: %s\n", name, elf_errmsg(elf_errno())); + + sname = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name); + if (shdr.sh_type == SHT_PROGBITS && + strcmp(sname, ".SUNW_ctf") == 0) { + ctfsect.cts_name = sname; + ctfsect.cts_type = shdr.sh_type; + ctfsect.cts_flags = shdr.sh_flags; + ctfsect.cts_size = shdr.sh_size; + ctfsect.cts_entsize = shdr.sh_entsize; + ctfsect.cts_offset = (off64_t)shdr.sh_offset; + + ctf_data = elf_getdata(scn, NULL); + if (ctf_data == NULL) + ctfmerge_fatal("failed to get ELF CTF " + "data section for %s: %s\n", name, + elf_errmsg(elf_errno())); + ctfsect.cts_data = ctf_data->d_buf; + } else if (shdr.sh_type == SHT_SYMTAB) { + Elf_Scn *strscn; + GElf_Shdr strhdr; + + symsect.cts_name = sname; + symsect.cts_type = shdr.sh_type; + symsect.cts_flags = shdr.sh_flags; + symsect.cts_size = shdr.sh_size; + symsect.cts_entsize = shdr.sh_entsize; + symsect.cts_offset = (off64_t)shdr.sh_offset; + + if ((strscn = elf_getscn(elf, shdr.sh_link)) == NULL || + gelf_getshdr(strscn, &strhdr) == NULL) + ctfmerge_fatal("failed to get " + "string table for file %s: %s\n", name, + elf_errmsg(elf_errno())); + + strsect.cts_name = elf_strptr(elf, ehdr.e_shstrndx, + strhdr.sh_name); + strsect.cts_type = strhdr.sh_type; + strsect.cts_flags = strhdr.sh_flags; + strsect.cts_size = strhdr.sh_size; + strsect.cts_entsize = strhdr.sh_entsize; + strsect.cts_offset = (off64_t)strhdr.sh_offset; + + sym_data = elf_getdata(scn, NULL); + if (sym_data == NULL) + ctfmerge_fatal("failed to get ELF CTF " + "data section for %s: %s\n", name, + elf_errmsg(elf_errno())); + symsect.cts_data = sym_data->d_buf; + + str_data = elf_getdata(strscn, NULL); + if (str_data == NULL) + ctfmerge_fatal("failed to get ELF CTF " + "data section for %s: %s\n", name, + elf_errmsg(elf_errno())); + strsect.cts_data = str_data->d_buf; + } + } + + if (ctfsect.cts_type == SHT_NULL) { + if (ctfmerge_expect_ctf(name, elf) == B_FALSE) + return; + ctfmerge_fatal("failed to open %s: %s\n", name, + ctf_errmsg(ECTF_NOCTFDATA)); + } + + if (symsect.cts_type != SHT_NULL && strsect.cts_type != SHT_NULL) { + fp = ctf_bufopen(&ctfsect, &symsect, &strsect, &err); + } else { + fp = ctf_bufopen(&ctfsect, NULL, NULL, &err); + } + + if (fp == NULL) { + if (ctfmerge_expect_ctf(name, elf) == B_TRUE) { + ctfmerge_fatal("failed to open file %s: %s\n", + name, ctf_errmsg(err)); + } + } else { + if ((err = ctf_merge_add(cmh, fp)) != 0) { + ctfmerge_fatal("failed to add input %s: %s\n", + name, ctf_errmsg(err)); + } + g_nctf++; + } +} + +static void +ctfmerge_read_archive(const char *name, int fd, Elf *elf, + ctf_merge_t *cmh) +{ + Elf *aelf; + Elf_Cmd cmd = ELF_C_READ; + int cursec = 1; + char *nname; + + while ((aelf = elf_begin(fd, cmd, elf)) != NULL) { + Elf_Arhdr *arhdr; + boolean_t leakelf = B_FALSE; + + if ((arhdr = elf_getarhdr(aelf)) == NULL) + ctfmerge_fatal("failed to get archive header %d for " + "%s: %s\n", cursec, name, elf_errmsg(elf_errno())); + + if (*(arhdr->ar_name) == '/') + goto next; + + if (asprintf(&nname, "%s.%s.%d", name, arhdr->ar_name, + cursec) < 0) + ctfmerge_fatal("failed to allocate memory for archive " + "%d of file %s\n", cursec, name); + + switch (elf_kind(aelf)) { + case ELF_K_AR: + ctfmerge_read_archive(nname, fd, aelf, cmh); + free(nname); + break; + case ELF_K_ELF: + ctfmerge_elfopen(nname, aelf, cmh); + free(nname); + leakelf = B_TRUE; + break; + default: + ctfmerge_fatal("unknown elf kind (%d) in archive %d " + "for %s\n", elf_kind(aelf), cursec, name); + } + +next: + cmd = elf_next(aelf); + if (leakelf == B_FALSE) + (void) elf_end(aelf); + cursec++; + } +} + +static void +ctfmerge_usage(const char *fmt, ...) +{ + if (fmt != NULL) { + va_list ap; + + (void) fprintf(stderr, "%s: ", g_progname); + va_start(ap, fmt); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + } + + (void) fprintf(stderr, "Usage: %s [-t] [-d uniqfile] [-l label] " + "[-L labelenv] [-j nthrs] -o outfile file ...\n" + "\n" + "\t-d uniquify merged output against uniqfile\n" + "\t-j use nthrs threads to perform the merge\n" + "\t-l set output container's label to specified value\n" + "\t-L set output container's label to value from environment\n" + "\t-o file to add CTF data to\n" + "\t-t require CTF data from all inputs built from C sources\n", + g_progname); +} + +static void +ctfmerge_altexec(char **argv) +{ + const char *alt; + char *altexec; + + alt = getenv(CTFMERGE_ALTEXEC); + if (alt == NULL || *alt == '\0') + return; + + altexec = strdup(alt); + if (altexec == NULL) + ctfmerge_fatal("failed to allocate memory for altexec\n"); + if (unsetenv(CTFMERGE_ALTEXEC) != 0) + ctfmerge_fatal("failed to unset %s from environment: %s\n", + CTFMERGE_ALTEXEC, strerror(errno)); + + (void) execv(altexec, argv); + ctfmerge_fatal("failed to execute alternate program %s: %s", + altexec, strerror(errno)); +} + +int +main(int argc, char *argv[]) +{ + int err, i, c, ofd; + uint_t nthreads = CTFMERGE_DEFAULT_NTHREADS; + char *tmpfile = NULL, *label = NULL; + int wflags = CTF_ELFWRITE_F_COMPRESS; + ctf_file_t *ofp; + ctf_merge_t *cmh; + long argj; + char *eptr; + + g_progname = basename(argv[0]); + + ctfmerge_altexec(argv); + + /* + * We support a subset of the old CTF merge flags, mostly for + * compatability. + */ + while ((c = getopt(argc, argv, ":d:fgj:l:L:o:t")) != -1) { + switch (c) { + case 'd': + g_unique = optarg; + break; + case 'f': + /* Silently ignored for compatibility */ + break; + case 'g': + /* Silently ignored for compatibility */ + break; + case 'j': + errno = 0; + argj = strtol(optarg, &eptr, 10); + if (errno != 0 || argj == LONG_MAX || + argj > 1024 || *eptr != '\0') { + ctfmerge_fatal("invalid argument for -j: %s\n", + optarg); + } + nthreads = (uint_t)argj; + break; + case 'l': + label = optarg; + break; + case 'L': + label = getenv(optarg); + break; + case 'o': + g_outfile = optarg; + break; + case 't': + g_req = B_TRUE; + break; + case ':': + ctfmerge_usage("Option -%c requires an operand\n", + optopt); + return (CTFMERGE_USAGE); + case '?': + ctfmerge_usage("Unknown option: -%c\n", optopt); + return (CTFMERGE_USAGE); + } + } + + if (g_outfile == NULL) { + ctfmerge_usage("missing required -o output file\n"); + return (CTFMERGE_USAGE); + } + + (void) elf_version(EV_CURRENT); + + /* + * Obviously this isn't atomic, but at least gives us a good starting + * point. + */ + if ((ofd = open(g_outfile, O_RDWR)) < 0) + ctfmerge_fatal("cannot open output file %s: %s\n", g_outfile, + strerror(errno)); + + argc -= optind; + argv += optind; + + if (argc < 1) { + ctfmerge_usage("no input files specified"); + return (CTFMERGE_USAGE); + } + + cmh = ctf_merge_init(ofd, &err); + if (cmh == NULL) + ctfmerge_fatal("failed to create merge handle: %s\n", + ctf_errmsg(err)); + + if ((err = ctf_merge_set_nthreads(cmh, nthreads)) != 0) + ctfmerge_fatal("failed to set parallelism to %u: %s\n", + nthreads, ctf_errmsg(err)); + + for (i = 0; i < argc; i++) { + ctf_file_t *ifp; + int fd; + + if ((fd = open(argv[i], O_RDONLY)) < 0) + ctfmerge_fatal("failed to open file %s: %s\n", + argv[i], strerror(errno)); + ifp = ctf_fdopen(fd, &err); + if (ifp == NULL) { + Elf *e; + + if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { + (void) close(fd); + ctfmerge_fatal("failed to open %s: %s\n", + argv[i], ctf_errmsg(err)); + } + + /* + * It's an ELF file, check if we have an archive or if + * we're expecting CTF here. + */ + switch (elf_kind(e)) { + case ELF_K_AR: + break; + case ELF_K_ELF: + if (ctfmerge_expect_ctf(argv[i], e) == B_TRUE) { + (void) elf_end(e); + (void) close(fd); + ctfmerge_fatal("failed to " + "open %s: file was built from C " + "sources, but missing CTF\n", + argv[i]); + } + (void) elf_end(e); + (void) close(fd); + continue; + default: + (void) elf_end(e); + (void) close(fd); + ctfmerge_fatal("failed to open %s: " + "unsupported ELF file type", argv[i]); + } + + ctfmerge_read_archive(argv[i], fd, e, cmh); + (void) elf_end(e); + (void) close(fd); + continue; + } + (void) close(fd); + if ((err = ctf_merge_add(cmh, ifp)) != 0) + ctfmerge_fatal("failed to add input %s: %s\n", + argv[i], ctf_errmsg(err)); + g_nctf++; + } + + if (g_nctf == 0) { + ctf_merge_fini(cmh); + return (0); + } + + if (g_unique != NULL) { + ctf_file_t *ufp; + char *base; + + ufp = ctf_open(g_unique, &err); + if (ufp == NULL) { + ctfmerge_fatal("failed to open uniquify file %s: %s\n", + g_unique, ctf_errmsg(err)); + } + + base = basename(g_unique); + (void) ctf_merge_uniquify(cmh, ufp, base); + } + + if (label != NULL) { + if ((err = ctf_merge_label(cmh, label)) != 0) + ctfmerge_fatal("failed to add label %s: %s\n", label, + ctf_errmsg(err)); + } + + err = ctf_merge_merge(cmh, &ofp); + if (err != 0) + ctfmerge_fatal("failed to merge types: %s\n", ctf_errmsg(err)); + ctf_merge_fini(cmh); + + if (asprintf(&tmpfile, "%s.ctf", g_outfile) == -1) + ctfmerge_fatal("ran out of memory for temporary file name\n"); + err = ctf_elfwrite(ofp, g_outfile, tmpfile, wflags); + if (err == CTF_ERR) { + (void) unlink(tmpfile); + free(tmpfile); + ctfmerge_fatal("encountered a libctf error: %s!\n", + ctf_errmsg(ctf_errno(ofp))); + } + + if (rename(tmpfile, g_outfile) != 0) { + (void) unlink(tmpfile); + free(tmpfile); + ctfmerge_fatal("failed to rename temporary file: %s\n", + strerror(errno)); + } + free(tmpfile); + + return (CTFMERGE_OK); +} diff --git a/usr/src/cmd/mdb/Makefile.libstandctf b/usr/src/cmd/mdb/Makefile.libstandctf index caa621be0e..176291399c 100644 --- a/usr/src/cmd/mdb/Makefile.libstandctf +++ b/usr/src/cmd/mdb/Makefile.libstandctf @@ -22,6 +22,8 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2018 Joyent, Inc. +# .KEEP_STATE: @@ -45,6 +47,9 @@ $(NOT_RELEASE_BUILD)CPPFLAGS += -DDEBUG CPPFLAGS += -I$(SRC)/common/ctf -I../../../common -DCTF_OLD_VERSIONS -D_MDB \ -Dvsnprintf=ctf_vsnprintf -Dassfail=kmdb_prom_assfail +CSTD = $(CSTD_GNU99) +C99LMODE = -Xc99=%all + # # kmdb is a kernel module, so we'll use the kernel's build flags. CFLAGS64 += $(STAND_FLAGS_64) diff --git a/usr/src/cmd/mdb/common/kmdb/kmdb_promif.c b/usr/src/cmd/mdb/common/kmdb/kmdb_promif.c index 637e685b06..b82ab3275e 100644 --- a/usr/src/cmd/mdb/common/kmdb/kmdb_promif.c +++ b/usr/src/cmd/mdb/common/kmdb/kmdb_promif.c @@ -742,10 +742,10 @@ kmdb_prom_debugger_exit(void) mdb.m_pio = NULL; } -#ifdef DEBUG /* - * The prom_* files use ASSERT, which is #defined as assfail(). - * We need to redirect that to our assert function. + * The prom_* files use ASSERT, which is #defined as assfail(). We need to + * redirect that to our assert function. This is also used by the various STAND + * libraries. */ int kmdb_prom_assfail(const char *assertion, const char *file, int line) @@ -754,7 +754,6 @@ kmdb_prom_assfail(const char *assertion, const char *file, int line) /*NOTREACHED*/ return (0); } -#endif /* * Begin the initialization of the debugger/PROM interface. Initialization is diff --git a/usr/src/cmd/mdb/common/libstandctf/ctf_subr.c b/usr/src/cmd/mdb/common/libstandctf/ctf_subr.c index 0a211fcd22..e8c703e754 100644 --- a/usr/src/cmd/mdb/common/libstandctf/ctf_subr.c +++ b/usr/src/cmd/mdb/common/libstandctf/ctf_subr.c @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include #include @@ -65,6 +63,13 @@ ctf_fdopen(int fd, int *errp) return (ctf_set_open_errno(errp, ENOTSUP)); } +/*ARGSUSED*/ +ctf_file_t * +ctf_fdcreate_int(int fd, int *errp, ctf_sect_t *ctfp) +{ + return (ctf_set_open_errno(errp, ENOTSUP)); +} + /*ARGSUSED*/ ctf_file_t * ctf_open(const char *filename, int *errp) diff --git a/usr/src/cmd/mdb/common/mdb/mdb_ctf.c b/usr/src/cmd/mdb/common/mdb/mdb_ctf.c index dde087206c..9af52917b4 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_ctf.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_ctf.c @@ -24,7 +24,7 @@ */ /* * Copyright (c) 2013, 2016 by Delphix. All rights reserved. - * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. All rights reserved. */ #include @@ -37,6 +37,7 @@ #include #include +#include typedef struct tnarg { mdb_tgt_t *tn_tgt; /* target to use for lookup */ @@ -781,8 +782,9 @@ mdb_ctf_enum_iter(mdb_ctf_id_t id, mdb_ctf_enum_f *cb, void *data) /* * callback proxy for mdb_ctf_type_iter */ +/* ARGSUSED */ static int -type_iter_cb(ctf_id_t type, void *data) +type_iter_cb(ctf_id_t type, boolean_t root, void *data) { type_iter_t *tip = data; mdb_ctf_id_t id; @@ -812,7 +814,7 @@ mdb_ctf_type_iter(const char *object, mdb_ctf_type_f *cb, void *data) ti.ti_arg = data; ti.ti_fp = fp; - if ((ret = ctf_type_iter(fp, type_iter_cb, &ti)) == CTF_ERR) + if ((ret = ctf_type_iter(fp, B_FALSE, type_iter_cb, &ti)) == CTF_ERR) return (set_errno(ctf_to_errno(ctf_errno(fp)))); return (ret); @@ -1980,7 +1982,7 @@ mdb_ctf_add_member(const mdb_ctf_id_t *p, const char *name, return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); } - id = ctf_add_member(mdb.m_synth, mcip->mci_id, name, mtid); + id = ctf_add_member(mdb.m_synth, mcip->mci_id, name, mtid, ULONG_MAX); if (id == CTF_ERR) { mdb_dprintf(MDB_DBG_CTF, "failed to add member %s: %s\n", name, ctf_errmsg(ctf_errno(mdb.m_synth))); @@ -2081,7 +2083,7 @@ mdb_ctf_add_pointer(const mdb_ctf_id_t *p, mdb_ctf_id_t *rid) } - id = ctf_add_pointer(mdb.m_synth, CTF_ADD_ROOT, id); + id = ctf_add_pointer(mdb.m_synth, CTF_ADD_ROOT, NULL, id); if (id == CTF_ERR) { mdb_dprintf(MDB_DBG_CTF, "failed to add pointer: %s\n", ctf_errmsg(ctf_errno(mdb.m_synth))); @@ -2129,6 +2131,7 @@ mdb_ctf_type_delete(const mdb_ctf_id_t *id) return (0); } +/* ARGSUSED */ static int mdb_ctf_synthetics_file_cb(mdb_ctf_id_t id, void *arg) { @@ -2166,7 +2169,7 @@ mdb_ctf_synthetics_from_file(const char *file) ti.ti_fp = fp; ti.ti_arg = syn; ti.ti_cb = mdb_ctf_synthetics_file_cb; - if (ctf_type_iter(fp, type_iter_cb, &ti) == CTF_ERR) { + if (ctf_type_iter(fp, B_FALSE, type_iter_cb, &ti) == CTF_ERR) { ret = set_errno(ctf_to_errno(ctf_errno(fp))); mdb_warn("failed to add types"); goto cleanup; diff --git a/usr/src/cmd/mdb/common/mdb/mdb_debug.c b/usr/src/cmd/mdb/common/mdb/mdb_debug.c index d373d3726e..a158864a28 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_debug.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_debug.c @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include #include #include @@ -157,7 +155,6 @@ mdb_dmode(uint_t bits) mdb.m_debug = bits; } -#ifdef DEBUG int mdb_dassert(const char *expr, const char *file, int line) { @@ -165,7 +162,6 @@ mdb_dassert(const char *expr, const char *file, int line) /*NOTREACHED*/ return (0); } -#endif /* * Function to convert mdb longjmp codes (see ) into a string for diff --git a/usr/src/cmd/mdb/common/mdb/mdb_debug.h b/usr/src/cmd/mdb/common/mdb/mdb_debug.h index cf3b97b499..f889238e4f 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_debug.h +++ b/usr/src/cmd/mdb/common/mdb/mdb_debug.h @@ -27,8 +27,6 @@ #ifndef _MDB_DEBUG_H #define _MDB_DEBUG_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -66,8 +64,8 @@ extern void mdb_dmode(uint_t); extern const char *mdb_err2str(int); -#ifdef DEBUG extern int mdb_dassert(const char *, const char *, int); +#ifdef DEBUG #define ASSERT(x) ((void)((x) || mdb_dassert(#x, __FILE__, __LINE__))) #else #define ASSERT(x) diff --git a/usr/src/common/ctf/ctf_create.c b/usr/src/common/ctf/ctf_create.c index 239d166f44..c0a4b15055 100644 --- a/usr/src/common/ctf/ctf_create.c +++ b/usr/src/common/ctf/ctf_create.c @@ -25,7 +25,7 @@ * Use is subject to license terms. */ /* - * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. */ #include @@ -86,6 +86,48 @@ ctf_create(int *errp) return (fp); } +ctf_file_t * +ctf_fdcreate(int fd, int *errp) +{ + ctf_file_t *fp; + static const ctf_header_t hdr = { { CTF_MAGIC, CTF_VERSION, 0 } }; + + const ulong_t hashlen = 128; + ctf_dtdef_t **hash; + ctf_sect_t cts; + + if (fd == -1) + return (ctf_create(errp)); + + hash = ctf_alloc(hashlen * sizeof (ctf_dtdef_t *)); + + if (hash == NULL) + return (ctf_set_open_errno(errp, EAGAIN)); + + cts.cts_name = _CTF_SECTION; + cts.cts_type = SHT_PROGBITS; + cts.cts_flags = 0; + cts.cts_data = &hdr; + cts.cts_size = sizeof (hdr); + cts.cts_entsize = 1; + cts.cts_offset = 0; + + if ((fp = ctf_fdcreate_int(fd, errp, &cts)) == NULL) { + ctf_free(hash, hashlen * sizeof (ctf_dtdef_t *)); + return (NULL); + } + + fp->ctf_flags |= LCTF_RDWR; + fp->ctf_dthashlen = hashlen; + bzero(hash, hashlen * sizeof (ctf_dtdef_t *)); + fp->ctf_dthash = hash; + fp->ctf_dtstrlen = sizeof (_CTF_STRTAB_TEMPLATE); + fp->ctf_dtnextid = 1; + fp->ctf_dtoldid = 0; + + return (fp); +} + static uchar_t * ctf_copy_smembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t) { @@ -236,14 +278,24 @@ int ctf_update(ctf_file_t *fp) { ctf_file_t ofp, *nfp; - ctf_header_t hdr; + ctf_header_t hdr, *bhdr; ctf_dtdef_t *dtd; - ctf_sect_t cts; + ctf_dsdef_t *dsd; + ctf_dldef_t *dld; + ctf_sect_t cts, *symp, *strp; uchar_t *s, *s0, *t; - size_t size; + ctf_lblent_t *label; + uint16_t *obj, *func; + size_t size, objsize, funcsize, labelsize, plen; void *buf; int err; + ulong_t i; + const char *plabel; + const char *sname; + + uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data; + uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data; if (!(fp->ctf_flags & LCTF_RDWR)) return (ctf_set_errno(fp, ECTF_RDONLY)); @@ -261,8 +313,26 @@ ctf_update(ctf_file_t *fp) hdr.cth_magic = CTF_MAGIC; hdr.cth_version = CTF_VERSION; - if (fp->ctf_flags & LCTF_CHILD) - hdr.cth_parname = 1; /* i.e. _CTF_STRTAB_TEMPLATE[1] */ + if (fp->ctf_flags & LCTF_CHILD) { + if (fp->ctf_parname == NULL) { + plen = 0; + hdr.cth_parname = 1; /* i.e. _CTF_STRTAB_TEMPLATE[1] */ + plabel = NULL; + } else { + plen = strlen(fp->ctf_parname) + 1; + plabel = ctf_label_topmost(fp->ctf_parent); + } + } else { + plabel = NULL; + plen = 0; + } + + /* + * Iterate over the labels that we have. + */ + for (labelsize = 0, dld = ctf_list_next(&fp->ctf_dldefs); + dld != NULL; dld = ctf_list_next(dld)) + labelsize += sizeof (ctf_lblent_t); /* * Iterate through the dynamic type definition list and compute the @@ -303,25 +373,121 @@ ctf_update(ctf_file_t *fp) } } + /* + * An entry for each object must exist in the data section. However, if + * the symbol is SHN_UNDEF, then it is skipped. For objects, the storage + * is just the size of the 2-byte id. For functions it's always 2 bytes, + * plus 2 bytes per argument and the return type. + */ + dsd = ctf_list_next(&fp->ctf_dsdefs); + for (objsize = 0, funcsize = 0, i = 0; i < fp->ctf_nsyms; i++) { + int type; + + if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) { + const Elf32_Sym *symp = (Elf32_Sym *)symbase + i; + + type = ELF32_ST_TYPE(symp->st_info); + if (ctf_sym_valid(strbase, type, symp->st_shndx, + symp->st_value, symp->st_name) == B_FALSE) + continue; + } else { + const Elf64_Sym *symp = (Elf64_Sym *)symbase + i; + + type = ELF64_ST_TYPE(symp->st_info); + if (ctf_sym_valid(strbase, type, symp->st_shndx, + symp->st_value, symp->st_name) == B_FALSE) + continue; + } + + while (dsd != NULL && i > dsd->dsd_symidx) + dsd = ctf_list_next(dsd); + if (type == STT_OBJECT) { + objsize += sizeof (uint16_t); + } else { + /* Every function has a uint16_t info no matter what */ + if (dsd == NULL || i < dsd->dsd_symidx) { + funcsize += sizeof (uint16_t); + } else { + funcsize += sizeof (uint16_t) * + (dsd->dsd_nargs + 2); + } + } + } + + /* + * The objtoff and funcoffset must be 2-byte aligned. We're guaranteed + * that this is always true for the objtoff because labels are always 8 + * bytes large. Similarly, because objects are always two bytes of data, + * this will always be true for funcoff. + */ + hdr.cth_objtoff = hdr.cth_lbloff + labelsize; + hdr.cth_funcoff = hdr.cth_objtoff + objsize; + + /* + * The type offset must be 4 byte aligned. + */ + hdr.cth_typeoff = hdr.cth_funcoff + funcsize; + if (hdr.cth_typeoff & 3) + hdr.cth_typeoff += 4 - (hdr.cth_typeoff & 3); + ASSERT((hdr.cth_typeoff & 3) == 0); + /* * Fill in the string table offset and size, compute the size of the * entire CTF buffer we need, and then allocate a new buffer and * bcopy the finished header to the start of the buffer. */ hdr.cth_stroff = hdr.cth_typeoff + size; - hdr.cth_strlen = fp->ctf_dtstrlen; + hdr.cth_strlen = fp->ctf_dtstrlen + plen; size = sizeof (ctf_header_t) + hdr.cth_stroff + hdr.cth_strlen; + ctf_dprintf("lbloff: %u\nobjtoff: %u\nfuncoff: %u\n" + "typeoff: %u\nstroff: %u\nstrlen: %u\n", + hdr.cth_lbloff, hdr.cth_objtoff, hdr.cth_funcoff, + hdr.cth_typeoff, hdr.cth_stroff, hdr.cth_strlen); if ((buf = ctf_data_alloc(size)) == MAP_FAILED) return (ctf_set_errno(fp, EAGAIN)); bcopy(&hdr, buf, sizeof (ctf_header_t)); - t = (uchar_t *)buf + sizeof (ctf_header_t); + bhdr = buf; + label = (ctf_lblent_t *)((uintptr_t)buf + sizeof (ctf_header_t)); + t = (uchar_t *)buf + sizeof (ctf_header_t) + hdr.cth_typeoff; s = s0 = (uchar_t *)buf + sizeof (ctf_header_t) + hdr.cth_stroff; + obj = (uint16_t *)((uintptr_t)buf + sizeof (ctf_header_t) + + hdr.cth_objtoff); + func = (uint16_t *)((uintptr_t)buf + sizeof (ctf_header_t) + + hdr.cth_funcoff); bcopy(_CTF_STRTAB_TEMPLATE, s, sizeof (_CTF_STRTAB_TEMPLATE)); s += sizeof (_CTF_STRTAB_TEMPLATE); + /* + * We have an actual parent name and we're a child container, therefore + * we should make sure to note our parent's name here. + */ + if (plen != 0) { + VERIFY(s + plen - s0 <= hdr.cth_strlen); + bcopy(fp->ctf_parname, s, plen); + bhdr->cth_parname = s - s0; + s += plen; + } + + /* + * First pass over the labels and copy them out. + */ + for (dld = ctf_list_next(&fp->ctf_dldefs); dld != NULL; + dld = ctf_list_next(dld), label++) { + size_t len = strlen(dld->dld_name) + 1; + + VERIFY(s + len - s0 <= hdr.cth_strlen); + bcopy(dld->dld_name, s, len); + label->ctl_typeidx = dld->dld_type; + label->ctl_label = s - s0; + s += len; + + if (plabel != NULL && strcmp(plabel, dld->dld_name) == 0) + bhdr->cth_parlabel = label->ctl_label; + } + /* * We now take a final lap through the dynamic type definition list and * copy the appropriate type records and strings to the output buffer. @@ -339,6 +505,7 @@ ctf_update(ctf_file_t *fp) if (dtd->dtd_name != NULL) { dtd->dtd_data.ctt_name = (uint_t)(s - s0); len = strlen(dtd->dtd_name) + 1; + VERIFY(s + len - s0 <= hdr.cth_strlen); bcopy(dtd->dtd_name, s, len); s += len; } else @@ -410,6 +577,61 @@ ctf_update(ctf_file_t *fp) } } + /* + * Now we fill in our dynamic data and function sections. We use the + * same criteria as above, but also consult the dsd list. + */ + dsd = ctf_list_next(&fp->ctf_dsdefs); + for (i = 0; i < fp->ctf_nsyms; i++) { + int type; + if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) { + const Elf32_Sym *symp = (Elf32_Sym *)symbase + i; + type = ELF32_ST_TYPE(symp->st_info); + + if (ctf_sym_valid(strbase, type, symp->st_shndx, + symp->st_value, symp->st_name) == B_FALSE) + continue; + } else { + const Elf64_Sym *symp = (Elf64_Sym *)symbase + i; + type = ELF64_ST_TYPE(symp->st_info); + if (ctf_sym_valid(strbase, type, symp->st_shndx, + symp->st_value, symp->st_name) == B_FALSE) + continue; + } + + while (dsd != NULL && i > dsd->dsd_symidx) { + dsd = ctf_list_next(dsd); + } + if (type == STT_OBJECT) { + if (dsd == NULL || i < dsd->dsd_symidx) { + *obj = 0; + } else { + *obj = dsd->dsd_tid; + } + obj++; + VERIFY((uintptr_t)obj <= (uintptr_t)func); + } else { + if (dsd == NULL || i < dsd->dsd_symidx) { + ushort_t data = CTF_TYPE_INFO(CTF_K_UNKNOWN, + 0, 0); + *func = data; + func++; + } else { + int j; + ushort_t data = CTF_TYPE_INFO(CTF_K_FUNCTION, 0, + dsd->dsd_nargs); + + *func = data; + func++; + *func = dsd->dsd_tid; + func++; + for (j = 0; j < dsd->dsd_nargs; j++) + func[j] = dsd->dsd_argc[j]; + func += dsd->dsd_nargs; + } + } + } + /* * Finally, we are ready to ctf_bufopen() the new container. If this * is successful, we then switch nfp and fp and free the old container. @@ -423,7 +645,15 @@ ctf_update(ctf_file_t *fp) cts.cts_entsize = 1; cts.cts_offset = 0; - if ((nfp = ctf_bufopen(&cts, NULL, NULL, &err)) == NULL) { + if (fp->ctf_nsyms == 0) { + symp = NULL; + strp = NULL; + } else { + symp = &fp->ctf_symtab; + strp = &fp->ctf_strtab; + } + + if ((nfp = ctf_bufopen(&cts, symp, strp, &err)) == NULL) { ctf_data_free(buf, size); return (ctf_set_errno(fp, err)); } @@ -433,10 +663,11 @@ ctf_update(ctf_file_t *fp) nfp->ctf_refcnt = fp->ctf_refcnt; nfp->ctf_flags |= fp->ctf_flags & ~LCTF_DIRTY; - nfp->ctf_data.cts_data = NULL; /* force ctf_data_free() on close */ nfp->ctf_dthash = fp->ctf_dthash; nfp->ctf_dthashlen = fp->ctf_dthashlen; nfp->ctf_dtdefs = fp->ctf_dtdefs; + nfp->ctf_dsdefs = fp->ctf_dsdefs; + nfp->ctf_dldefs = fp->ctf_dldefs; nfp->ctf_dtstrlen = fp->ctf_dtstrlen; nfp->ctf_dtnextid = fp->ctf_dtnextid; nfp->ctf_dtoldid = fp->ctf_dtnextid - 1; @@ -445,6 +676,23 @@ ctf_update(ctf_file_t *fp) fp->ctf_dthash = NULL; fp->ctf_dthashlen = 0; bzero(&fp->ctf_dtdefs, sizeof (ctf_list_t)); + bzero(&fp->ctf_dsdefs, sizeof (ctf_list_t)); + bzero(&fp->ctf_dldefs, sizeof (ctf_list_t)); + + /* + * Because the various containers share the data sections, we don't want + * to have ctf_close free it all. However, the name of the section is in + * fact unique to the ctf_sect_t. Thus we save the names of the symbol + * and string sections around the bzero() and restore them afterwards, + * ensuring that we don't result in a memory leak. + */ + sname = fp->ctf_symtab.cts_name; + bzero(&fp->ctf_symtab, sizeof (ctf_sect_t)); + fp->ctf_symtab.cts_name = sname; + + sname = fp->ctf_strtab.cts_name; + bzero(&fp->ctf_strtab, sizeof (ctf_sect_t)); + fp->ctf_strtab.cts_name = sname; bcopy(fp, &ofp, sizeof (ctf_file_t)); bcopy(nfp, fp, sizeof (ctf_file_t)); @@ -563,6 +811,101 @@ ctf_dtd_lookup(ctf_file_t *fp, ctf_id_t type) return (dtd); } +ctf_dsdef_t * +ctf_dsd_lookup(ctf_file_t *fp, ulong_t idx) +{ + ctf_dsdef_t *dsd; + + for (dsd = ctf_list_next(&fp->ctf_dsdefs); dsd != NULL; + dsd = ctf_list_next(dsd)) { + if (dsd->dsd_symidx == idx) + return (dsd); + } + + return (NULL); +} + +/* + * We order the ctf_dsdef_t by symbol index to make things better for updates. + */ +void +ctf_dsd_insert(ctf_file_t *fp, ctf_dsdef_t *dsd) +{ + ctf_dsdef_t *i; + + for (i = ctf_list_next(&fp->ctf_dsdefs); i != NULL; + i = ctf_list_next(i)) { + if (i->dsd_symidx > dsd->dsd_symidx) + break; + } + + if (i == NULL) { + ctf_list_append(&fp->ctf_dsdefs, dsd); + return; + } + + ctf_list_insert_before(&fp->ctf_dsdefs, i, dsd); +} + +/* ARGSUSED */ +void +ctf_dsd_delete(ctf_file_t *fp, ctf_dsdef_t *dsd) +{ + if (dsd->dsd_nargs > 0) + ctf_free(dsd->dsd_argc, + sizeof (ctf_id_t) * dsd->dsd_nargs); + ctf_list_delete(&fp->ctf_dsdefs, dsd); + ctf_free(dsd, sizeof (ctf_dsdef_t)); +} + +ctf_dldef_t * +ctf_dld_lookup(ctf_file_t *fp, const char *name) +{ + ctf_dldef_t *dld; + + for (dld = ctf_list_next(&fp->ctf_dldefs); dld != NULL; + dld = ctf_list_next(dld)) { + if (strcmp(name, dld->dld_name) == 0) + return (dld); + } + + return (NULL); +} + +void +ctf_dld_insert(ctf_file_t *fp, ctf_dldef_t *dld, uint_t pos) +{ + ctf_dldef_t *l; + + if (pos == 0) { + ctf_list_prepend(&fp->ctf_dldefs, dld); + return; + } + + for (l = ctf_list_next(&fp->ctf_dldefs); pos != 0 && dld != NULL; + l = ctf_list_next(l), pos--) + ; + + if (l == NULL) + ctf_list_append(&fp->ctf_dldefs, dld); + else + ctf_list_insert_before(&fp->ctf_dsdefs, l, dld); +} + +void +ctf_dld_delete(ctf_file_t *fp, ctf_dldef_t *dld) +{ + ctf_list_delete(&fp->ctf_dldefs, dld); + + if (dld->dld_name != NULL) { + size_t len = strlen(dld->dld_name) + 1; + ctf_free(dld->dld_name, len); + fp->ctf_dtstrlen -= len; + } + + ctf_free(dld, sizeof (ctf_dldef_t)); +} + /* * Discard all of the dynamic type definitions that have been added to the * container since the last call to ctf_update(). We locate such types by @@ -583,10 +926,10 @@ ctf_discard(ctf_file_t *fp) return (0); /* no update required */ for (dtd = ctf_list_prev(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) { + ntd = ctf_list_prev(dtd); if (dtd->dtd_type <= fp->ctf_dtoldid) continue; /* skip types that have been committed */ - ntd = ctf_list_prev(dtd); ctf_dtd_delete(fp, dtd); } @@ -637,26 +980,7 @@ ctf_add_generic(ctf_file_t *fp, uint_t flag, const char *name, ctf_dtdef_t **rp) return (type); } -/* - * When encoding integer sizes, we want to convert a byte count in the range - * 1-8 to the closest power of 2 (e.g. 3->4, 5->8, etc). The clp2() function - * is a clever implementation from "Hacker's Delight" by Henry Warren, Jr. - */ -static size_t -clp2(size_t x) -{ - x--; - - x |= (x >> 1); - x |= (x >> 2); - x |= (x >> 4); - x |= (x >> 8); - x |= (x >> 16); - - return (x + 1); -} - -static ctf_id_t +ctf_id_t ctf_add_encoded(ctf_file_t *fp, uint_t flag, const char *name, const ctf_encoding_t *ep, uint_t kind) { @@ -670,14 +994,22 @@ ctf_add_encoded(ctf_file_t *fp, uint_t flag, return (CTF_ERR); /* errno is set for us */ dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, 0); - dtd->dtd_data.ctt_size = clp2(P2ROUNDUP(ep->cte_bits, NBBY) / NBBY); + + /* + * If the type's size is not an even number of bytes, then we should + * round up the type size to the nearest byte. + */ + dtd->dtd_data.ctt_size = ep->cte_bits / NBBY; + if ((ep->cte_bits % NBBY) != 0) + dtd->dtd_data.ctt_size++; dtd->dtd_u.dtu_enc = *ep; return (type); } -static ctf_id_t -ctf_add_reftype(ctf_file_t *fp, uint_t flag, ctf_id_t ref, uint_t kind) +ctf_id_t +ctf_add_reftype(ctf_file_t *fp, uint_t flag, + const char *name, ctf_id_t ref, uint_t kind) { ctf_dtdef_t *dtd; ctf_id_t type; @@ -685,7 +1017,7 @@ ctf_add_reftype(ctf_file_t *fp, uint_t flag, ctf_id_t ref, uint_t kind) if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE) return (ctf_set_errno(fp, EINVAL)); - if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR) + if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR) return (CTF_ERR); /* errno is set for us */ ctf_ref_inc(fp, ref); @@ -711,9 +1043,9 @@ ctf_add_float(ctf_file_t *fp, uint_t flag, } ctf_id_t -ctf_add_pointer(ctf_file_t *fp, uint_t flag, ctf_id_t ref) +ctf_add_pointer(ctf_file_t *fp, uint_t flag, const char *name, ctf_id_t ref) { - return (ctf_add_reftype(fp, flag, ref, CTF_K_POINTER)); + return (ctf_add_reftype(fp, flag, name, ref, CTF_K_POINTER)); } ctf_id_t @@ -728,13 +1060,18 @@ ctf_add_array(ctf_file_t *fp, uint_t flag, const ctf_arinfo_t *arp) fpd = fp; if (ctf_lookup_by_id(&fpd, arp->ctr_contents) == NULL && - ctf_dtd_lookup(fp, arp->ctr_contents) == NULL) + ctf_dtd_lookup(fp, arp->ctr_contents) == NULL) { + ctf_dprintf("bad contents for array: %ld\n", + arp->ctr_contents); return (ctf_set_errno(fp, ECTF_BADID)); + } fpd = fp; if (ctf_lookup_by_id(&fpd, arp->ctr_index) == NULL && - ctf_dtd_lookup(fp, arp->ctr_index) == NULL) + ctf_dtd_lookup(fp, arp->ctr_index) == NULL) { + ctf_dprintf("bad index for array: %ld\n", arp->ctr_index); return (ctf_set_errno(fp, ECTF_BADID)); + } if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR) return (CTF_ERR); /* errno is set for us */ @@ -781,7 +1118,7 @@ ctf_set_array(ctf_file_t *fp, ctf_id_t type, const ctf_arinfo_t *arp) } ctf_id_t -ctf_add_function(ctf_file_t *fp, uint_t flag, +ctf_add_funcptr(ctf_file_t *fp, uint_t flag, const ctf_funcinfo_t *ctc, const ctf_id_t *argv) { ctf_dtdef_t *dtd; @@ -842,20 +1179,34 @@ ctf_add_struct(ctf_file_t *fp, uint_t flag, const char *name) { ctf_hash_t *hp = &fp->ctf_structs; ctf_helem_t *hep = NULL; - ctf_dtdef_t *dtd; - ctf_id_t type; + ctf_dtdef_t *dtd = NULL; + ctf_id_t type = CTF_ERR; if (name != NULL) hep = ctf_hash_lookup(hp, fp, name, strlen(name)); - if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD) - dtd = ctf_dtd_lookup(fp, type = hep->h_type); - else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR) - return (CTF_ERR); /* errno is set for us */ + if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD) { + type = hep->h_type; + dtd = ctf_dtd_lookup(fp, type); + if (CTF_INFO_KIND(dtd->dtd_data.ctt_info) != CTF_K_FORWARD) + dtd = NULL; + } + if (dtd == NULL) { + type = ctf_add_generic(fp, flag, name, &dtd); + if (type == CTF_ERR) + return (CTF_ERR); /* errno is set for us */ + } + + VERIFY(type != CTF_ERR); dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_STRUCT, flag, 0); dtd->dtd_data.ctt_size = 0; + /* + * Always dirty in case we modified a forward. + */ + fp->ctf_flags |= LCTF_DIRTY; + return (type); } @@ -864,20 +1215,34 @@ ctf_add_union(ctf_file_t *fp, uint_t flag, const char *name) { ctf_hash_t *hp = &fp->ctf_unions; ctf_helem_t *hep = NULL; - ctf_dtdef_t *dtd; - ctf_id_t type; + ctf_dtdef_t *dtd = NULL; + ctf_id_t type = CTF_ERR; if (name != NULL) hep = ctf_hash_lookup(hp, fp, name, strlen(name)); - if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD) - dtd = ctf_dtd_lookup(fp, type = hep->h_type); - else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR) - return (CTF_ERR); /* errno is set for us */ + if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD) { + type = hep->h_type; + dtd = ctf_dtd_lookup(fp, type); + if (CTF_INFO_KIND(dtd->dtd_data.ctt_info) != CTF_K_FORWARD) + dtd = NULL; + } + if (dtd == NULL) { + type = ctf_add_generic(fp, flag, name, &dtd); + if (type == CTF_ERR) + return (CTF_ERR); /* errno is set for us */ + } + + VERIFY(type != CTF_ERR); dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_UNION, flag, 0); dtd->dtd_data.ctt_size = 0; + /* + * Always dirty in case we modified a forward. + */ + fp->ctf_flags |= LCTF_DIRTY; + return (type); } @@ -886,20 +1251,34 @@ ctf_add_enum(ctf_file_t *fp, uint_t flag, const char *name) { ctf_hash_t *hp = &fp->ctf_enums; ctf_helem_t *hep = NULL; - ctf_dtdef_t *dtd; - ctf_id_t type; + ctf_dtdef_t *dtd = NULL; + ctf_id_t type = CTF_ERR; if (name != NULL) hep = ctf_hash_lookup(hp, fp, name, strlen(name)); - if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD) - dtd = ctf_dtd_lookup(fp, type = hep->h_type); - else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR) - return (CTF_ERR); /* errno is set for us */ + if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD) { + type = hep->h_type; + dtd = ctf_dtd_lookup(fp, type); + if (CTF_INFO_KIND(dtd->dtd_data.ctt_info) != CTF_K_FORWARD) + dtd = NULL; + } + if (dtd == NULL) { + type = ctf_add_generic(fp, flag, name, &dtd); + if (type == CTF_ERR) + return (CTF_ERR); /* errno is set for us */ + } + + VERIFY(type != CTF_ERR); dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, flag, 0); dtd->dtd_data.ctt_size = fp->ctf_dmodel->ctd_int; + /* + * Always dirty in case we modified a forward. + */ + fp->ctf_flags |= LCTF_DIRTY; + return (type); } @@ -965,21 +1344,21 @@ ctf_add_typedef(ctf_file_t *fp, uint_t flag, const char *name, ctf_id_t ref) } ctf_id_t -ctf_add_volatile(ctf_file_t *fp, uint_t flag, ctf_id_t ref) +ctf_add_volatile(ctf_file_t *fp, uint_t flag, const char *name, ctf_id_t ref) { - return (ctf_add_reftype(fp, flag, ref, CTF_K_VOLATILE)); + return (ctf_add_reftype(fp, flag, name, ref, CTF_K_VOLATILE)); } ctf_id_t -ctf_add_const(ctf_file_t *fp, uint_t flag, ctf_id_t ref) +ctf_add_const(ctf_file_t *fp, uint_t flag, const char *name, ctf_id_t ref) { - return (ctf_add_reftype(fp, flag, ref, CTF_K_CONST)); + return (ctf_add_reftype(fp, flag, name, ref, CTF_K_CONST)); } ctf_id_t -ctf_add_restrict(ctf_file_t *fp, uint_t flag, ctf_id_t ref) +ctf_add_restrict(ctf_file_t *fp, uint_t flag, const char *name, ctf_id_t ref) { - return (ctf_add_reftype(fp, flag, ref, CTF_K_RESTRICT)); + return (ctf_add_reftype(fp, flag, name, ref, CTF_K_RESTRICT)); } int @@ -1012,8 +1391,10 @@ ctf_add_enumerator(ctf_file_t *fp, ctf_id_t enid, const char *name, int value) for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members); dmd != NULL; dmd = ctf_list_next(dmd)) { - if (strcmp(dmd->dmd_name, name) == 0) + if (strcmp(dmd->dmd_name, name) == 0) { + ctf_dprintf("encountered duplicate member %s\n", name); return (ctf_set_errno(fp, ECTF_DUPMEMBER)); + } } if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL) @@ -1039,13 +1420,16 @@ ctf_add_enumerator(ctf_file_t *fp, ctf_id_t enid, const char *name, int value) } int -ctf_add_member(ctf_file_t *fp, ctf_id_t souid, const char *name, ctf_id_t type) +ctf_add_member(ctf_file_t *fp, ctf_id_t souid, const char *name, ctf_id_t type, + ulong_t offset) { ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, souid); ctf_dmdef_t *dmd; + ulong_t mbitsz; ssize_t msize, malign, ssize; uint_t kind, vlen, root; + int mkind; char *s = NULL; if (!(fp->ctf_flags & LCTF_RDWR)) @@ -1064,19 +1448,58 @@ ctf_add_member(ctf_file_t *fp, ctf_id_t souid, const char *name, ctf_id_t type) if (vlen == CTF_MAX_VLEN) return (ctf_set_errno(fp, ECTF_DTFULL)); - if (name != NULL) { + /* + * Structures may have members which are anonymous. If they have two of + * these, then the duplicate member detection would find it due to the + * string of "", so we skip it. + */ + if (name != NULL && *name != '\0') { for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members); dmd != NULL; dmd = ctf_list_next(dmd)) { if (dmd->dmd_name != NULL && - strcmp(dmd->dmd_name, name) == 0) + strcmp(dmd->dmd_name, name) == 0) { return (ctf_set_errno(fp, ECTF_DUPMEMBER)); + } } } if ((msize = ctf_type_size(fp, type)) == CTF_ERR || - (malign = ctf_type_align(fp, type)) == CTF_ERR) + (malign = ctf_type_align(fp, type)) == CTF_ERR || + (mkind = ctf_type_kind(fp, type)) == CTF_ERR) return (CTF_ERR); /* errno is set for us */ + /* + * ctf_type_size returns sizes in bytes. However, for bitfields, that + * means that it may misrepresent and actually rounds it up to a power + * of two and store that in bytes. So instead we have to get the + * Integers encoding and rely on that. + */ + if (mkind == CTF_K_INTEGER) { + ctf_encoding_t e; + + if (ctf_type_encoding(fp, type, &e) == CTF_ERR) + return (CTF_ERR); /* errno is set for us */ + mbitsz = e.cte_bits; + } else if (mkind == CTF_K_FORWARD) { + /* + * This is a rather rare case. In general one cannot add a + * forward to a structure. However, the CTF tools traditionally + * tried to add a forward to the struct cpu as the last member. + * Therefore, if we find one here, we're going to verify the + * size and make sure it's zero. It's certainly odd, but that's + * life. + * + * Further, if it's not an absolute position being specified, + * then we refuse to add it. + */ + if (offset == ULONG_MAX) + return (ctf_set_errno(fp, EINVAL)); + VERIFY(msize == 0); + mbitsz = msize; + } else { + mbitsz = msize * 8; + } + if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL) return (ctf_set_errno(fp, EAGAIN)); @@ -1092,29 +1515,36 @@ ctf_add_member(ctf_file_t *fp, ctf_id_t souid, const char *name, ctf_id_t type) if (kind == CTF_K_STRUCT && vlen != 0) { ctf_dmdef_t *lmd = ctf_list_prev(&dtd->dtd_u.dtu_members); ctf_id_t ltype = ctf_type_resolve(fp, lmd->dmd_type); - size_t off = lmd->dmd_offset; - - ctf_encoding_t linfo; - ssize_t lsize; - - if (ctf_type_encoding(fp, ltype, &linfo) != CTF_ERR) - off += linfo.cte_bits; - else if ((lsize = ctf_type_size(fp, ltype)) != CTF_ERR) - off += lsize * NBBY; - - /* - * Round up the offset of the end of the last member to the - * next byte boundary, convert 'off' to bytes, and then round - * it up again to the next multiple of the alignment required - * by the new member. Finally, convert back to bits and store - * the result in dmd_offset. Technically we could do more - * efficient packing if the new member is a bit-field, but - * we're the "compiler" and ANSI says we can do as we choose. - */ - off = roundup(off, NBBY) / NBBY; - off = roundup(off, MAX(malign, 1)); - dmd->dmd_offset = off * NBBY; - ssize = off + msize; + size_t off; + + if (offset == ULONG_MAX) { + ctf_encoding_t linfo; + ssize_t lsize; + + off = lmd->dmd_offset; + if (ctf_type_encoding(fp, ltype, &linfo) != CTF_ERR) + off += linfo.cte_bits; + else if ((lsize = ctf_type_size(fp, ltype)) != CTF_ERR) + off += lsize * NBBY; + + /* + * Round up the offset of the end of the last member to + * the next byte boundary, convert 'off' to bytes, and + * then round it up again to the next multiple of the + * alignment required by the new member. Finally, + * convert back to bits and store the result in + * dmd_offset. Technically we could do more efficient + * packing if the new member is a bit-field, but we're + * the "compiler" and ANSI says we can do as we choose. + */ + off = roundup(off, NBBY) / NBBY; + off = roundup(off, MAX(malign, 1)); + dmd->dmd_offset = off * NBBY; + ssize = off + msize; + } else { + dmd->dmd_offset = offset; + ssize = (offset + mbitsz) / NBBY; + } } else { dmd->dmd_offset = 0; ssize = ctf_get_ctt_size(fp, &dtd->dtd_data, NULL, NULL); @@ -1380,7 +1810,7 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) if (src_type == CTF_ERR) return (CTF_ERR); /* errno is set for us */ - dst_type = ctf_add_reftype(dst_fp, flag, src_type, kind); + dst_type = ctf_add_reftype(dst_fp, flag, NULL, src_type, kind); break; case CTF_K_ARRAY: @@ -1415,7 +1845,7 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) if (ctc.ctc_return == CTF_ERR) return (CTF_ERR); /* errno is set for us */ - dst_type = ctf_add_function(dst_fp, flag, &ctc, NULL); + dst_type = ctf_add_funcptr(dst_fp, flag, &ctc, NULL); break; case CTF_K_STRUCT: @@ -1540,3 +1970,227 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) return (dst_type); } + +int +ctf_add_function(ctf_file_t *fp, ulong_t idx, const ctf_funcinfo_t *fip, + const ctf_id_t *argc) +{ + int i; + ctf_dsdef_t *dsd; + ctf_file_t *afp; + uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data; + + if (!(fp->ctf_flags & LCTF_RDWR)) + return (ctf_set_errno(fp, ECTF_RDONLY)); + + if (ctf_dsd_lookup(fp, idx) != NULL) + return (ctf_set_errno(fp, ECTF_CONFLICT)); + + if (symbase == NULL) + return (ctf_set_errno(fp, ECTF_STRTAB)); + + if (idx > fp->ctf_nsyms) + return (ctf_set_errno(fp, ECTF_NOTDATA)); + + if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) { + const Elf32_Sym *symp = (Elf32_Sym *)symbase + idx; + if (ELF32_ST_TYPE(symp->st_info) != STT_FUNC) + return (ctf_set_errno(fp, ECTF_NOTFUNC)); + } else { + const Elf64_Sym *symp = (Elf64_Sym *)symbase + idx; + if (ELF64_ST_TYPE(symp->st_info) != STT_FUNC) + return (ctf_set_errno(fp, ECTF_NOTFUNC)); + } + + afp = fp; + if (ctf_lookup_by_id(&afp, fip->ctc_return) == NULL) + return (CTF_ERR); /* errno is set for us */ + + for (i = 0; i < fip->ctc_argc; i++) { + afp = fp; + if (ctf_lookup_by_id(&afp, argc[i]) == NULL) + return (CTF_ERR); /* errno is set for us */ + } + + dsd = ctf_alloc(sizeof (ctf_dsdef_t)); + if (dsd == NULL) + return (ctf_set_errno(fp, ENOMEM)); + dsd->dsd_nargs = fip->ctc_argc; + if (fip->ctc_flags & CTF_FUNC_VARARG) + dsd->dsd_nargs++; + if (dsd->dsd_nargs != 0) { + dsd->dsd_argc = ctf_alloc(sizeof (ctf_id_t) * dsd->dsd_nargs); + if (dsd->dsd_argc == NULL) { + ctf_free(dsd, sizeof (ctf_dsdef_t)); + return (ctf_set_errno(fp, ENOMEM)); + } + bcopy(argc, dsd->dsd_argc, sizeof (ctf_id_t) * fip->ctc_argc); + if (fip->ctc_flags & CTF_FUNC_VARARG) + dsd->dsd_argc[fip->ctc_argc] = 0; + } + dsd->dsd_symidx = idx; + dsd->dsd_tid = fip->ctc_return; + + ctf_dsd_insert(fp, dsd); + fp->ctf_flags |= LCTF_DIRTY; + + return (0); +} + +int +ctf_add_object(ctf_file_t *fp, ulong_t idx, ctf_id_t type) +{ + ctf_dsdef_t *dsd; + ctf_file_t *afp; + uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data; + + if (!(fp->ctf_flags & LCTF_RDWR)) + return (ctf_set_errno(fp, ECTF_RDONLY)); + + if (!(fp->ctf_flags & LCTF_RDWR)) + return (ctf_set_errno(fp, ECTF_RDONLY)); + + if (ctf_dsd_lookup(fp, idx) != NULL) + return (ctf_set_errno(fp, ECTF_CONFLICT)); + + if (symbase == NULL) + return (ctf_set_errno(fp, ECTF_STRTAB)); + + if (idx > fp->ctf_nsyms) + return (ctf_set_errno(fp, ECTF_NOTDATA)); + + if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) { + const Elf32_Sym *symp = (Elf32_Sym *)symbase + idx; + if (ELF32_ST_TYPE(symp->st_info) != STT_OBJECT) + return (ctf_set_errno(fp, ECTF_NOTDATA)); + } else { + const Elf64_Sym *symp = (Elf64_Sym *)symbase + idx; + if (ELF64_ST_TYPE(symp->st_info) != STT_OBJECT) + return (ctf_set_errno(fp, ECTF_NOTDATA)); + } + + afp = fp; + if (ctf_lookup_by_id(&afp, type) == NULL) + return (CTF_ERR); /* errno is set for us */ + + dsd = ctf_alloc(sizeof (ctf_dsdef_t)); + if (dsd == NULL) + return (ctf_set_errno(fp, ENOMEM)); + dsd->dsd_symidx = idx; + dsd->dsd_tid = type; + dsd->dsd_argc = NULL; + + ctf_dsd_insert(fp, dsd); + fp->ctf_flags |= LCTF_DIRTY; + + return (0); +} + +void +ctf_dataptr(ctf_file_t *fp, const void **addrp, size_t *sizep) +{ + if (addrp != NULL) + *addrp = fp->ctf_base; + if (sizep != NULL) + *sizep = fp->ctf_size; +} + +int +ctf_add_label(ctf_file_t *fp, const char *name, ctf_id_t type, uint_t position) +{ + ctf_file_t *fpd; + ctf_dldef_t *dld; + + if (name == NULL) + return (ctf_set_errno(fp, EINVAL)); + + if (!(fp->ctf_flags & LCTF_RDWR)) + return (ctf_set_errno(fp, ECTF_RDONLY)); + + fpd = fp; + if (type != 0 && ctf_lookup_by_id(&fpd, type) == NULL) + return (CTF_ERR); /* errno is set for us */ + + if (type != 0 && (fp->ctf_flags & LCTF_CHILD) && + CTF_TYPE_ISPARENT(type)) + return (ctf_set_errno(fp, ECTF_NOPARENT)); + + if (ctf_dld_lookup(fp, name) != NULL) + return (ctf_set_errno(fp, ECTF_LABELEXISTS)); + + if ((dld = ctf_alloc(sizeof (ctf_dldef_t))) == NULL) + return (ctf_set_errno(fp, EAGAIN)); + + if ((dld->dld_name = ctf_strdup(name)) == NULL) { + ctf_free(dld, sizeof (ctf_dldef_t)); + return (ctf_set_errno(fp, EAGAIN)); + } + + dld->dld_type = type; + fp->ctf_dtstrlen += strlen(name) + 1; + ctf_dld_insert(fp, dld, position); + fp->ctf_flags |= LCTF_DIRTY; + + return (0); +} + +/* + * Update the size of a structure or union. Note that we don't allow this to + * shrink the size of a struct or union, only to increase it. This is useful for + * cases when you have a structure whose actual size is larger than the sum of + * its members due to padding for natural alignment. + */ +int +ctf_set_size(ctf_file_t *fp, ctf_id_t id, const ulong_t newsz) +{ + ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, id); + uint_t kind; + size_t oldsz; + + if (!(fp->ctf_flags & LCTF_RDWR)) + return (ctf_set_errno(fp, ECTF_RDONLY)); + + if (dtd == NULL) + return (ctf_set_errno(fp, ECTF_BADID)); + + kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info); + + if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) + return (ctf_set_errno(fp, ECTF_NOTSOU)); + + if ((oldsz = dtd->dtd_data.ctt_size) == CTF_LSIZE_SENT) + oldsz = CTF_TYPE_LSIZE(&dtd->dtd_data); + + if (newsz < oldsz) + return (ctf_set_errno(fp, EINVAL)); + + if (newsz > CTF_MAX_SIZE) { + dtd->dtd_data.ctt_size = CTF_LSIZE_SENT; + dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(newsz); + dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(newsz); + } else { + dtd->dtd_data.ctt_size = (ushort_t)newsz; + } + + fp->ctf_flags |= LCTF_DIRTY; + return (0); +} + +int +ctf_set_root(ctf_file_t *fp, ctf_id_t id, const boolean_t vis) +{ + ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, id); + uint_t kind, vlen; + + if (!(fp->ctf_flags & LCTF_RDWR)) + return (ctf_set_errno(fp, ECTF_RDONLY)); + + if (dtd == NULL) + return (ctf_set_errno(fp, ECTF_BADID)); + + kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info); + vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info); + + dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, vis, vlen); + return (0); +} diff --git a/usr/src/common/ctf/ctf_error.c b/usr/src/common/ctf/ctf_error.c index fe3d0de0cb..1765b77b54 100644 --- a/usr/src/common/ctf/ctf_error.c +++ b/usr/src/common/ctf/ctf_error.c @@ -24,7 +24,7 @@ * Use is subject to license terms. */ /* - * Copyright (c) 2012, Joyent, Inc. + * Copyright (c) 2015, Joyent, Inc. */ #include @@ -75,7 +75,15 @@ static const char *const _ctf_errlist[] = { "Duplicate member name definition", /* ECTF_DUPMEMBER */ "Conflicting type is already defined", /* ECTF_CONFLICT */ "Type has outstanding references", /* ECTF_REFERENCED */ - "Type is not a dynamic type" /* ECTF_NOTDYN */ + "Type is not a dynamic type", /* ECTF_NOTDYN */ + "Elf library failure", /* ECTF_ELF */ + "Cannot merge child container", /* ECTF_MCHILD */ + "Label already exists", /* ECTF_LABEL */ + "Merged labels conflict", /* ECTF_LCONFLICT */ + "Zlib library failure", /* ECTF_ZLIB */ + "CTF conversion backend error", /* ECTF_CONVBKERR */ + "No C source to convert from", /* ECTF_CONVNOCSRC */ + "No applicable conversion backend" /* ECTF_NOCONVBKEND */ }; static const int _ctf_nerr = sizeof (_ctf_errlist) / sizeof (_ctf_errlist[0]); diff --git a/usr/src/common/ctf/ctf_hash.c b/usr/src/common/ctf/ctf_hash.c index b10a7618f6..0c5a71a5ac 100644 --- a/usr/src/common/ctf/ctf_hash.c +++ b/usr/src/common/ctf/ctf_hash.c @@ -25,9 +25,8 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include +#include static const ushort_t _CTF_EMPTY[1] = { 0 }; diff --git a/usr/src/common/ctf/ctf_impl.h b/usr/src/common/ctf/ctf_impl.h index f56fa6a005..93a85a8b4f 100644 --- a/usr/src/common/ctf/ctf_impl.h +++ b/usr/src/common/ctf/ctf_impl.h @@ -25,7 +25,7 @@ * Use is subject to license terms. */ /* - * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. All rights reserved. */ #ifndef _CTF_IMPL_H @@ -41,6 +41,8 @@ #include #include #include +#include +#include #define isspace(c) \ ((c) == ' ' || (c) == '\t' || (c) == '\n' || \ @@ -56,6 +58,7 @@ #include #include #include +#include #endif /* _KERNEL */ @@ -77,6 +80,10 @@ typedef struct ctf_hash { uint_t h_free; /* index of next free hash element */ } ctf_hash_t; +struct ctf_idhash_iter { + int cii_id; /* Current iteration id */ +}; + typedef struct ctf_strs { const char *cts_strs; /* base address of string table */ size_t cts_len; /* size of string table in bytes */ @@ -159,6 +166,20 @@ typedef struct ctf_dtdef { } dtd_u; } ctf_dtdef_t; +typedef struct ctf_dsdef { + ctf_list_t dsd_list; /* list forward/back pointers */ + ulong_t dsd_symidx; /* symbol id */ + ctf_id_t dsd_tid; /* type for obj, 0 if function */ + uint_t dsd_nargs; + ctf_id_t *dsd_argc; /* function argv */ +} ctf_dsdef_t; + +typedef struct ctf_dldef { + ctf_list_t dld_list; /* list forward/back pointers */ + char *dld_name; /* name of the label */ + ctf_id_t dld_type; /* type ID associated with the label */ +} ctf_dldef_t; + typedef struct ctf_bundle { ctf_file_t *ctb_file; /* CTF container handle */ ctf_id_t ctb_type; /* CTF type identifier */ @@ -211,6 +232,9 @@ struct ctf_file { ulong_t ctf_dtnextid; /* next dynamic type id to assign */ ulong_t ctf_dtoldid; /* oldest id that has been committed */ void *ctf_specific; /* data for ctf_get/setspecific */ + ctf_list_t ctf_dsdefs; /* list of dynamic obj/func definitions */ + ctf_list_t ctf_dldefs; /* list of dynamic labels */ + uint_t ctf_hflags; /* original flags on the header */ }; #define LCTF_INDEX_TO_TYPEPTR(fp, i) \ @@ -225,62 +249,15 @@ struct ctf_file { #define LCTF_RDWR 0x0004 /* CTF container is writable */ #define LCTF_DIRTY 0x0008 /* CTF container has been modified */ -#define ECTF_BASE 1000 /* base value for libctf errnos */ - -enum { - ECTF_FMT = ECTF_BASE, /* file is not in CTF or ELF format */ - ECTF_ELFVERS, /* ELF version is more recent than libctf */ - ECTF_CTFVERS, /* CTF version is more recent than libctf */ - ECTF_ENDIAN, /* data is different endian-ness than lib */ - ECTF_SYMTAB, /* symbol table uses invalid entry size */ - ECTF_SYMBAD, /* symbol table data buffer invalid */ - ECTF_STRBAD, /* string table data buffer invalid */ - ECTF_CORRUPT, /* file data corruption detected */ - ECTF_NOCTFDATA, /* ELF file does not contain CTF data */ - ECTF_NOCTFBUF, /* buffer does not contain CTF data */ - ECTF_NOSYMTAB, /* symbol table data is not available */ - ECTF_NOPARENT, /* parent CTF container is not available */ - ECTF_DMODEL, /* data model mismatch */ - ECTF_MMAP, /* failed to mmap a data section */ - ECTF_ZMISSING, /* decompression library not installed */ - ECTF_ZINIT, /* failed to initialize decompression library */ - ECTF_ZALLOC, /* failed to allocate decompression buffer */ - ECTF_DECOMPRESS, /* failed to decompress CTF data */ - ECTF_STRTAB, /* string table for this string is missing */ - ECTF_BADNAME, /* string offset is corrupt w.r.t. strtab */ - ECTF_BADID, /* invalid type ID number */ - ECTF_NOTSOU, /* type is not a struct or union */ - ECTF_NOTENUM, /* type is not an enum */ - ECTF_NOTSUE, /* type is not a struct, union, or enum */ - ECTF_NOTINTFP, /* type is not an integer or float */ - ECTF_NOTARRAY, /* type is not an array */ - ECTF_NOTREF, /* type does not reference another type */ - ECTF_NAMELEN, /* buffer is too small to hold type name */ - ECTF_NOTYPE, /* no type found corresponding to name */ - ECTF_SYNTAX, /* syntax error in type name */ - ECTF_NOTFUNC, /* symtab entry does not refer to a function */ - ECTF_NOFUNCDAT, /* no func info available for function */ - ECTF_NOTDATA, /* symtab entry does not refer to a data obj */ - ECTF_NOTYPEDAT, /* no type info available for object */ - ECTF_NOLABEL, /* no label found corresponding to name */ - ECTF_NOLABELDATA, /* file does not contain any labels */ - ECTF_NOTSUP, /* feature not supported */ - ECTF_NOENUMNAM, /* enum element name not found */ - ECTF_NOMEMBNAM, /* member name not found */ - ECTF_RDONLY, /* CTF container is read-only */ - ECTF_DTFULL, /* CTF type is full (no more members allowed) */ - ECTF_FULL, /* CTF container is full */ - ECTF_DUPMEMBER, /* duplicate member name definition */ - ECTF_CONFLICT, /* conflicting type definition present */ - ECTF_REFERENCED, /* type has outstanding references */ - ECTF_NOTDYN /* type is not a dynamic type */ -}; +#define CTF_ELF_SCN_NAME ".SUNW_ctf" extern ssize_t ctf_get_ctt_size(const ctf_file_t *, const ctf_type_t *, ssize_t *, ssize_t *); extern const ctf_type_t *ctf_lookup_by_id(ctf_file_t **, ctf_id_t); +extern ctf_file_t *ctf_fdcreate_int(int, int *, ctf_sect_t *); + extern int ctf_hash_create(ctf_hash_t *, ulong_t); extern int ctf_hash_insert(ctf_hash_t *, ctf_file_t *, ushort_t, uint_t); extern int ctf_hash_define(ctf_hash_t *, ctf_file_t *, ushort_t, uint_t); @@ -294,12 +271,16 @@ extern void ctf_hash_destroy(ctf_hash_t *); extern void ctf_list_append(ctf_list_t *, void *); extern void ctf_list_prepend(ctf_list_t *, void *); +extern void ctf_list_insert_before(ctf_list_t *, void *, void *); extern void ctf_list_delete(ctf_list_t *, void *); extern void ctf_dtd_insert(ctf_file_t *, ctf_dtdef_t *); extern void ctf_dtd_delete(ctf_file_t *, ctf_dtdef_t *); extern ctf_dtdef_t *ctf_dtd_lookup(ctf_file_t *, ctf_id_t); +extern void ctf_dsd_delete(ctf_file_t *, ctf_dsdef_t *); +extern void ctf_dld_delete(ctf_file_t *, ctf_dldef_t *); + extern void ctf_decl_init(ctf_decl_t *, char *, size_t); extern void ctf_decl_fini(ctf_decl_t *); extern void ctf_decl_push(ctf_decl_t *, ctf_file_t *, ctf_id_t); @@ -327,6 +308,13 @@ extern void ctf_dprintf(const char *, ...); extern void *ctf_zopen(int *); +extern ctf_id_t ctf_add_encoded(ctf_file_t *, uint_t, const char *, + const ctf_encoding_t *, uint_t); +extern ctf_id_t ctf_add_reftype(ctf_file_t *, uint_t, const char *, ctf_id_t, + uint_t); +extern boolean_t ctf_sym_valid(uintptr_t, int, uint16_t, uint64_t, + uint32_t); + extern const char _CTF_SECTION[]; /* name of CTF ELF section */ extern const char _CTF_NULLSTR[]; /* empty string */ diff --git a/usr/src/common/ctf/ctf_open.c b/usr/src/common/ctf/ctf_open.c index 001cf5c591..82b396e825 100644 --- a/usr/src/common/ctf/ctf_open.c +++ b/usr/src/common/ctf/ctf_open.c @@ -25,7 +25,7 @@ * Use is subject to license terms. */ /* - * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. All rights reserved. */ #include @@ -550,6 +550,7 @@ ctf_bufopen(const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, void *buf, *base; size_t size, hdrsz; int err; + uint_t hflags; if (ctfsect == NULL || ((symsect == NULL) != (strsect == NULL))) return (ctf_set_open_errno(errp, EINVAL)); @@ -631,6 +632,7 @@ ctf_bufopen(const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, * the CTF data buffer if it is compressed. Otherwise we just put * the data section's buffer pointer into ctf_buf, below. */ + hflags = hp.cth_flags; if (hp.cth_flags & CTF_F_COMPRESS) { size_t srclen, dstlen; const void *src; @@ -680,6 +682,7 @@ ctf_bufopen(const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, bzero(fp, sizeof (ctf_file_t)); fp->ctf_version = hp.cth_version; fp->ctf_fileops = &ctf_fileops[hp.cth_version]; + fp->ctf_hflags = hflags; bcopy(ctfsect, &fp->ctf_data, sizeof (ctf_sect_t)); if (symsect != NULL) { @@ -883,6 +886,8 @@ void ctf_close(ctf_file_t *fp) { ctf_dtdef_t *dtd, *ntd; + ctf_dsdef_t *dsd, *nsd; + ctf_dldef_t *dld, *nld; if (fp == NULL) return; /* allow ctf_close(NULL) to simplify caller code */ @@ -906,10 +911,25 @@ ctf_close(ctf_file_t *fp) ctf_dtd_delete(fp, dtd); } + for (dsd = ctf_list_prev(&fp->ctf_dsdefs); dsd != NULL; dsd = nsd) { + nsd = ctf_list_prev(dsd); + ctf_dsd_delete(fp, dsd); + } + + for (dld = ctf_list_prev(&fp->ctf_dldefs); dld != NULL; dld = nld) { + nld = ctf_list_prev(dld); + ctf_dld_delete(fp, dld); + } + ctf_free(fp->ctf_dthash, fp->ctf_dthashlen * sizeof (ctf_dtdef_t *)); if (fp->ctf_flags & LCTF_MMAP) { - if (fp->ctf_data.cts_data != NULL) + /* + * Writeable containers shouldn't necessairily have the CTF + * section freed. + */ + if (fp->ctf_data.cts_data != NULL && + !(fp->ctf_flags & LCTF_RDWR)) ctf_sect_munmap(&fp->ctf_data); if (fp->ctf_symtab.cts_data != NULL) ctf_sect_munmap(&fp->ctf_symtab); @@ -979,6 +999,16 @@ ctf_parent_name(ctf_file_t *fp) return (fp->ctf_parname); } +/* + * Return the label of the parent CTF container, if one exists. Otherwise return + * NULL. + */ +const char * +ctf_parent_label(ctf_file_t *fp) +{ + return (fp->ctf_parlabel); +} + /* * Import the types from the specified parent container by storing a pointer * to it in ctf_parent and incrementing its reference count. Only one parent @@ -1043,3 +1073,9 @@ ctf_getspecific(ctf_file_t *fp) { return (fp->ctf_specific); } + +uint_t +ctf_flags(ctf_file_t *fp) +{ + return (fp->ctf_hflags); +} diff --git a/usr/src/common/ctf/ctf_types.c b/usr/src/common/ctf/ctf_types.c index ab1b9ff14b..18d2d3d88a 100644 --- a/usr/src/common/ctf/ctf_types.c +++ b/usr/src/common/ctf/ctf_types.c @@ -24,8 +24,12 @@ * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2018 Joyent, Inc. + */ #include +#include ssize_t ctf_get_ctt_size(const ctf_file_t *fp, const ctf_type_t *tp, ssize_t *sizep, @@ -138,19 +142,21 @@ ctf_enum_iter(ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg) } /* - * Iterate over every root (user-visible) type in the given CTF container. - * We pass the type ID of each type to the specified callback function. + * Iterate over every type in the given CTF container. If the user doesn't ask + * for all types, then we only give them the user visible, aka root, types. We + * pass the type ID of each type to the specified callback function. */ int -ctf_type_iter(ctf_file_t *fp, ctf_type_f *func, void *arg) +ctf_type_iter(ctf_file_t *fp, boolean_t nonroot, ctf_type_f *func, void *arg) { ctf_id_t id, max = fp->ctf_typemax; int rc, child = (fp->ctf_flags & LCTF_CHILD); for (id = 1; id <= max; id++) { const ctf_type_t *tp = LCTF_INDEX_TO_TYPEPTR(fp, id); - if (CTF_INFO_ISROOT(tp->ctt_info) && - (rc = func(CTF_INDEX_TO_TYPE(id, child), arg)) != 0) + if ((nonroot || CTF_INFO_ISROOT(tp->ctt_info)) && + (rc = func(CTF_INDEX_TO_TYPE(id, child), + CTF_INFO_ISROOT(tp->ctt_info), arg)) != 0) return (rc); } @@ -194,13 +200,91 @@ ctf_type_resolve(ctf_file_t *fp, ctf_id_t type) } /* - * Lookup the given type ID and print a string name for it into buf. Return - * the actual number of bytes (not including \0) needed to format the name. + * Format an integer type; if a vname is specified, we need to insert it prior + * to any bitfield ":24" suffix. This works out far simpler than figuring it + * out from scratch. + */ +static const char * +ctf_format_int(ctf_decl_t *cd, const char *vname, const char *qname, + const char *name) +{ + const char *c; + + if (vname == NULL) { + if (qname != NULL) + ctf_decl_sprintf(cd, "%s`%s", qname, name); + else + ctf_decl_sprintf(cd, "%s", name); + return (NULL); + } + + if ((c = strchr(name, ':')) == NULL) { + ctf_decl_sprintf(cd, "%s", name); + return (vname); + } + + /* "unsigned int mybits:23" */ + ctf_decl_sprintf(cd, "%.*s %s%s", c - name, name, vname, c); + return (NULL); +} + +static void +ctf_format_func(ctf_file_t *fp, ctf_decl_t *cd, + const char *vname, ctf_id_t id, int want_func_args) +{ + ctf_funcinfo_t fi; + /* We'll presume zone_create() is a bad example. */ + ctf_id_t args[20]; + + ctf_decl_sprintf(cd, "%s(", vname == NULL ? "" : vname); + + if (!want_func_args) + goto out; + + if (ctf_func_info_by_id(fp, id, &fi) != 0) + goto out; + + if (fi.ctc_argc > ARRAY_SIZE(args)) + fi.ctc_argc = ARRAY_SIZE(args); + + if (fi.ctc_argc == 0) { + ctf_decl_sprintf(cd, "void"); + goto out; + } + + if (ctf_func_args_by_id(fp, id, fi.ctc_argc, args) != 0) + goto out; + + for (size_t i = 0; i < fi.ctc_argc; i++) { + char aname[512]; + + if (ctf_type_name(fp, args[i], aname, sizeof (aname)) == NULL) + (void) strlcpy(aname, "unknown_t", sizeof (aname)); + + ctf_decl_sprintf(cd, "%s%s", aname, + i + 1 == fi.ctc_argc ? "" : ", "); + } + + if (fi.ctc_flags & CTF_FUNC_VARARG) + ctf_decl_sprintf(cd, "%s...", fi.ctc_argc == 0 ? "" : ", "); + +out: + ctf_decl_sprintf(cd, ")"); +} + +/* + * Lookup the given type ID and print a string name for it into buf. Return the + * actual number of bytes (not including \0) needed to format the name. + * + * "vname" is an optional variable name or similar, so array suffix formatting, + * bitfields, and functions are C-correct. (This is not perfect, as can be seen + * in kiconv_ops_t.) */ static ssize_t ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len, - const char *qname) + const char *vname, const char *qname) { + int want_func_args = (vname != NULL); ctf_decl_t cd; ctf_decl_node_t *cdp; ctf_decl_prec_t prec, lp, rp; @@ -252,6 +336,8 @@ ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len, switch (cdp->cd_kind) { case CTF_K_INTEGER: + vname = ctf_format_int(&cd, vname, qname, name); + break; case CTF_K_FLOAT: case CTF_K_TYPEDEF: if (qname != NULL) @@ -262,10 +348,14 @@ ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len, ctf_decl_sprintf(&cd, "*"); break; case CTF_K_ARRAY: - ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n); + ctf_decl_sprintf(&cd, "%s[%u]", + vname != NULL ? vname : "", cdp->cd_n); + vname = NULL; break; case CTF_K_FUNCTION: - ctf_decl_sprintf(&cd, "()"); + ctf_format_func(fp, &cd, vname, + cdp->cd_type, want_func_args); + vname = NULL; break; case CTF_K_STRUCT: case CTF_K_FORWARD: @@ -300,10 +390,29 @@ ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len, k = cdp->cd_kind; } - if (rp == prec) + if (rp == prec) { + /* + * Peek ahead: if we're going to hit a function, + * we want to insert its name now before this closing + * bracket. + */ + if (vname != NULL && prec < CTF_PREC_FUNCTION) { + cdp = ctf_list_next( + &cd.cd_nodes[CTF_PREC_FUNCTION]); + + if (cdp != NULL) { + ctf_decl_sprintf(&cd, "%s", vname); + vname = NULL; + } + } + ctf_decl_sprintf(&cd, ")"); + } } + if (vname != NULL) + ctf_decl_sprintf(&cd, " %s", vname); + if (cd.cd_len >= len) (void) ctf_set_errno(fp, ECTF_NAMELEN); @@ -314,7 +423,7 @@ ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len, ssize_t ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len) { - return (ctf_type_qlname(fp, type, buf, len, NULL)); + return (ctf_type_qlname(fp, type, buf, len, NULL, NULL)); } /* @@ -324,7 +433,7 @@ ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len) char * ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len) { - ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL); + ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL, NULL); return (rv >= 0 && rv < len ? buf : NULL); } @@ -332,10 +441,17 @@ char * ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len, const char *qname) { - ssize_t rv = ctf_type_qlname(fp, type, buf, len, qname); + ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL, qname); return (rv >= 0 && rv < len ? buf : NULL); } +char * +ctf_type_cname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len, + const char *cname) +{ + ssize_t rv = ctf_type_qlname(fp, type, buf, len, cname, NULL); + return (rv >= 0 && rv < len ? buf : NULL); +} /* * Resolve the type down to a base type node, and then return the size @@ -361,6 +477,9 @@ ctf_type_size(ctf_file_t *fp, ctf_id_t type) case CTF_K_FUNCTION: return (0); /* function size is only known by symtab */ + case CTF_K_FORWARD: + return (0); + case CTF_K_ENUM: return (fp->ctf_dmodel->ctd_int); @@ -380,7 +499,22 @@ ctf_type_size(ctf_file_t *fp, ctf_id_t type) return (-1); /* errno is set for us */ return (size * ar.ctr_nelems); - + case CTF_K_STRUCT: + case CTF_K_UNION: + /* + * If we have a zero size, we may be in the process of adding a + * structure or union but having not called ctf_update() to deal + * with the circular dependencies in such structures and unions. + * To handle that case, if we get a size of zero from the ctt, + * we look up the dtdef and use its size instead. + */ + size = ctf_get_ctt_size(fp, tp, NULL, NULL); + if (size == 0) { + ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, type); + if (dtd != NULL) + return (dtd->dtd_data.ctt_size); + } + return (size); default: return (ctf_get_ctt_size(fp, tp, NULL, NULL)); } @@ -868,3 +1002,309 @@ ctf_type_visit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg) { return (ctf_type_rvisit(fp, type, func, arg, "", 0, 0)); } + +int +ctf_func_info_by_id(ctf_file_t *fp, ctf_id_t type, ctf_funcinfo_t *fip) +{ + ctf_file_t *ofp = fp; + const ctf_type_t *tp; + const ushort_t *dp; + int nargs; + ssize_t increment; + + if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) + return (CTF_ERR); /* errno is set for us */ + + if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_FUNCTION) + return (ctf_set_errno(ofp, ECTF_NOTFUNC)); + + fip->ctc_return = tp->ctt_type; + nargs = LCTF_INFO_VLEN(fp, tp->ctt_info); + fip->ctc_argc = nargs; + fip->ctc_flags = 0; + + /* dp should now point to the first argument */ + if (nargs != 0) { + (void) ctf_get_ctt_size(fp, tp, NULL, &increment); + dp = (ushort_t *)((uintptr_t)fp->ctf_buf + + fp->ctf_txlate[CTF_TYPE_TO_INDEX(type)] + increment); + if (dp[nargs - 1] == 0) { + fip->ctc_flags |= CTF_FUNC_VARARG; + fip->ctc_argc--; + } + } + + return (0); +} + +int +ctf_func_args_by_id(ctf_file_t *fp, ctf_id_t type, uint_t argc, ctf_id_t *argv) +{ + ctf_file_t *ofp = fp; + const ctf_type_t *tp; + const ushort_t *dp; + int nargs; + ssize_t increment; + + if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) + return (CTF_ERR); /* errno is set for us */ + + if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_FUNCTION) + return (ctf_set_errno(ofp, ECTF_NOTFUNC)); + + nargs = LCTF_INFO_VLEN(fp, tp->ctt_info); + (void) ctf_get_ctt_size(fp, tp, NULL, &increment); + dp = (ushort_t *)((uintptr_t)fp->ctf_buf + + fp->ctf_txlate[CTF_TYPE_TO_INDEX(type)] + + increment); + if (nargs != 0 && dp[nargs - 1] == 0) + nargs--; + + for (nargs = MIN(argc, nargs); nargs != 0; nargs--) + *argv++ = *dp++; + + return (0); +} + +int +ctf_object_iter(ctf_file_t *fp, ctf_object_f *func, void *arg) +{ + int i, ret; + ctf_id_t id; + uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data; + uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data; + + if (fp->ctf_symtab.cts_data == NULL) + return (ctf_set_errno(fp, ECTF_NOSYMTAB)); + + for (i = 0; i < fp->ctf_nsyms; i++) { + char *name; + if (fp->ctf_sxlate[i] == -1u) + continue; + id = *(ushort_t *)((uintptr_t)fp->ctf_buf + + fp->ctf_sxlate[i]); + + /* + * Validate whether or not we're looking at a data object as + * oposed to a function. + */ + if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) { + const Elf32_Sym *symp = (Elf32_Sym *)symbase + i; + if (ELF32_ST_TYPE(symp->st_info) != STT_OBJECT) + continue; + if (fp->ctf_strtab.cts_data != NULL && + symp->st_name != 0) + name = (char *)(strbase + symp->st_name); + else + name = NULL; + } else { + const Elf64_Sym *symp = (Elf64_Sym *)symbase + i; + if (ELF64_ST_TYPE(symp->st_info) != STT_OBJECT) + continue; + if (fp->ctf_strtab.cts_data != NULL && + symp->st_name != 0) + name = (char *)(strbase + symp->st_name); + else + name = NULL; + } + + if ((ret = func(name, id, i, arg)) != 0) + return (ret); + } + + return (0); +} + +int +ctf_function_iter(ctf_file_t *fp, ctf_function_f *func, void *arg) +{ + int i, ret; + uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data; + uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data; + + if (fp->ctf_symtab.cts_data == NULL) + return (ctf_set_errno(fp, ECTF_NOSYMTAB)); + + for (i = 0; i < fp->ctf_nsyms; i++) { + char *name; + ushort_t info, *dp; + ctf_funcinfo_t fi; + if (fp->ctf_sxlate[i] == -1u) + continue; + + dp = (ushort_t *)((uintptr_t)fp->ctf_buf + + fp->ctf_sxlate[i]); + info = *dp; + if (info == 0) + continue; + + /* + * This may be a function or it may be a data object. We have to + * consult the symbol table to be certain. Functions are encoded + * with their info, data objects with their actual type. + */ + if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) { + const Elf32_Sym *symp = (Elf32_Sym *)symbase + i; + if (ELF32_ST_TYPE(symp->st_info) != STT_FUNC) + continue; + if (fp->ctf_strtab.cts_data != NULL) + name = (char *)(strbase + symp->st_name); + else + name = NULL; + } else { + const Elf64_Sym *symp = (Elf64_Sym *)symbase + i; + if (ELF64_ST_TYPE(symp->st_info) != STT_FUNC) + continue; + if (fp->ctf_strtab.cts_data != NULL) + name = (char *)(strbase + symp->st_name); + else + name = NULL; + } + + if (LCTF_INFO_KIND(fp, info) != CTF_K_FUNCTION) + continue; + dp++; + fi.ctc_return = *dp; + dp++; + fi.ctc_argc = LCTF_INFO_VLEN(fp, info); + fi.ctc_flags = 0; + + if (fi.ctc_argc != 0 && dp[fi.ctc_argc - 1] == 0) { + fi.ctc_flags |= CTF_FUNC_VARARG; + fi.ctc_argc--; + } + + if ((ret = func(name, i, &fi, arg)) != 0) + return (ret); + + } + + return (0); +} + +char * +ctf_symbol_name(ctf_file_t *fp, ulong_t idx, char *buf, size_t len) +{ + const char *name; + uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data; + uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data; + + if (fp->ctf_symtab.cts_data == NULL) { + (void) ctf_set_errno(fp, ECTF_NOSYMTAB); + return (NULL); + } + + if (fp->ctf_strtab.cts_data == NULL) { + (void) ctf_set_errno(fp, ECTF_STRTAB); + return (NULL); + } + + if (idx > fp->ctf_nsyms) { + (void) ctf_set_errno(fp, ECTF_NOTDATA); + return (NULL); + } + + if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) { + const Elf32_Sym *symp = (Elf32_Sym *)symbase + idx; + if (ELF32_ST_TYPE(symp->st_info) != STT_OBJECT && + ELF32_ST_TYPE(symp->st_info) != STT_FUNC) { + (void) ctf_set_errno(fp, ECTF_NOTDATA); + return (NULL); + } + if (symp->st_name == 0) { + (void) ctf_set_errno(fp, ENOENT); + return (NULL); + } + name = (const char *)(strbase + symp->st_name); + } else { + const Elf64_Sym *symp = (Elf64_Sym *)symbase + idx; + if (ELF64_ST_TYPE(symp->st_info) != STT_FUNC && + ELF64_ST_TYPE(symp->st_info) != STT_OBJECT) { + (void) ctf_set_errno(fp, ECTF_NOTDATA); + return (NULL); + } + if (symp->st_name == 0) { + (void) ctf_set_errno(fp, ENOENT); + return (NULL); + } + name = (const char *)(strbase + symp->st_name); + } + + (void) strlcpy(buf, name, len); + + return (buf); +} + +int +ctf_string_iter(ctf_file_t *fp, ctf_string_f *func, void *arg) +{ + int rc; + const char *strp = fp->ctf_str[CTF_STRTAB_0].cts_strs; + size_t strl = fp->ctf_str[CTF_STRTAB_0].cts_len; + + while (strl > 0) { + size_t len; + + if ((rc = func(strp, arg)) != 0) + return (rc); + + len = strlen(strp) + 1; + strl -= len; + strp += len; + } + + return (0); +} + +/* + * fp isn't strictly necessary at the moment. However, if we ever rev the file + * format, the valid values for kind will change. + */ +const char * +ctf_kind_name(ctf_file_t *fp, int kind) +{ + switch (kind) { + case CTF_K_INTEGER: + return ("integer"); + case CTF_K_FLOAT: + return ("float"); + case CTF_K_POINTER: + return ("pointer"); + case CTF_K_ARRAY: + return ("array"); + case CTF_K_FUNCTION: + return ("function"); + case CTF_K_STRUCT: + return ("struct"); + case CTF_K_UNION: + return ("union"); + case CTF_K_ENUM: + return ("enum"); + case CTF_K_FORWARD: + return ("forward"); + case CTF_K_TYPEDEF: + return ("typedef"); + case CTF_K_VOLATILE: + return ("volatile"); + case CTF_K_CONST: + return ("const"); + case CTF_K_RESTRICT: + return ("restrict"); + case CTF_K_UNKNOWN: + default: + return ("unknown"); + } +} + +ctf_id_t +ctf_max_id(ctf_file_t *fp) +{ + int child = (fp->ctf_flags & LCTF_CHILD); + return (fp->ctf_typemax + (child ? CTF_CHILD_START : 0)); +} + +ulong_t +ctf_nr_syms(ctf_file_t *fp) +{ + return (fp->ctf_nsyms); +} diff --git a/usr/src/common/ctf/ctf_util.c b/usr/src/common/ctf/ctf_util.c index 740d403e8c..550195b5e1 100644 --- a/usr/src/common/ctf/ctf_util.c +++ b/usr/src/common/ctf/ctf_util.c @@ -23,10 +23,12 @@ * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2015, Joyent, Inc. + */ #include +#include /* * Simple doubly-linked list append routine. This implementation assumes that @@ -71,6 +73,24 @@ ctf_list_prepend(ctf_list_t *lp, void *new) lp->l_prev = p; } +void +ctf_list_insert_before(ctf_list_t *head, void *item, void *nitem) +{ + ctf_list_t *lp = item; + ctf_list_t *new = nitem; + ctf_list_t *prev = lp->l_prev; + + lp->l_prev = new; + new->l_next = lp; + new->l_prev = prev; + if (prev != NULL) { + prev->l_next = new; + } else { + ASSERT(head->l_next == lp); + head->l_next = new; + } +} + /* * Delete the specified existing element from the given ctf_list_t. The * existing pointer should be pointing at a struct with embedded ctf_list_t. @@ -150,3 +170,22 @@ ctf_set_errno(ctf_file_t *fp, int err) fp->ctf_errno = err; return (CTF_ERR); } + +boolean_t +ctf_sym_valid(uintptr_t strbase, int type, uint16_t shndx, uint64_t val, + uint32_t noff) +{ + const char *name; + + if (type != STT_OBJECT && type != STT_FUNC) + return (B_FALSE); + if (shndx == SHN_UNDEF || noff == 0) + return (B_FALSE); + if (type == STT_OBJECT && shndx == SHN_ABS && val == 0) + return (B_FALSE); + name = (char *)(strbase + noff); + if (strcmp(name, "_START_") == 0 || strcmp(name, "_END_") == 0) + return (B_FALSE); + + return (B_TRUE); +} diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile index 7463954834..7c461eb3fc 100644 --- a/usr/src/lib/Makefile +++ b/usr/src/lib/Makefile @@ -22,7 +22,7 @@ # # Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2012 by Delphix. All rights reserved. -# Copyright (c) 2012, Joyent, Inc. All rights reserved. +# Copyright 2015, Joyent, Inc. # Copyright (c) 2013 Gary Mills # Copyright 2014 Garrett D'Amore # Copyright (c) 2015 Gary Mills @@ -123,6 +123,7 @@ SUBDIRS += \ libdoor \ libdtrace \ libdtrace_jni \ + libdwarf \ libefi \ libelfsign \ libeti \ @@ -390,6 +391,7 @@ HDRSUBDIRS= \ libdhcputil \ libdisasm \ libdiskmgt \ + libdwarf \ libdladm \ libdll \ libdlpi \ @@ -590,6 +592,7 @@ libcmd: libsum libast libcmdutils: libavl libcpc: libpctx libcrypt: libgen +libctf: libdwarf libdevid: libdevinfo libdevinfo: libsec libgen libdhcpagent: libdhcputil libuuid libdlpi libcontract diff --git a/usr/src/lib/Makefile.lib b/usr/src/lib/Makefile.lib index 86cc330f41..384c579cfc 100644 --- a/usr/src/lib/Makefile.lib +++ b/usr/src/lib/Makefile.lib @@ -21,6 +21,7 @@ # Copyright 2015 Gary Mills # Copyright 2015 Igor Kozhukhov # Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, Joyent, Inc. # # # Definitions common to libraries. @@ -248,3 +249,15 @@ TARGETMACH= $(MACH) # shouldn't override this - they should override $(CLOBBERFILES) instead. # CLOBBERTARGFILES= $(LIBS) $(DYNLIB) $(CLOBBERFILES) + +# +# Define the default ctfdiff invocation used to check a list of types +# supplied by a user of a library. The goal is to validate that a given +# series of types is the same in both a 32-bit and 64-bit artifact. This +# is only defined if we have a 64-bit build to do. +# +TYPECHECK_LIB32 = $(TYPECHECK_LIB:%=$(MACH)/%) +TYPECHECK_LIB64 = $(TYPECHECK_LIB:%=$(MACH64)/%) +TYPECHECK_LIST= $(TYPELIST:%=-T %) +$(BUILD64)TYPECHECK.lib = $(CTFDIFF) -t -I $(TYPECHECK_LIST) $(TYPECHECK_LIB32) $(TYPECHECK_LIB64) +TYPECHECK = $(TYPECHECK_LIB:%=%.typecheck) diff --git a/usr/src/lib/Makefile.targ b/usr/src/lib/Makefile.targ index 4769c64d54..0744402619 100644 --- a/usr/src/lib/Makefile.targ +++ b/usr/src/lib/Makefile.targ @@ -99,11 +99,14 @@ $(DYNLIBCCC): pics .WAIT $$(PICS) $$(ALTPICS) $$(EXTPICS) $(POST_PROCESS_SO) $(LINTLIB): $$(SRCS) - $(LINT.c) -o $(LIBNAME) $(SRCS) > $(LINTOUT) 2>&1 + $(LINT.c) -o $(LIBNAME) $(SRCS) > $(LINTOUT) 2>&1 lintcheck: $$(SRCS) $(LINT.c) $(LINTCHECKFLAGS) $(SRCS) $(LDLIBS) +$(TYPECHECK): $(TYPECHECK_LIB32) $(TYPECHECK_LIB64) + $(TYPECHECK.lib) + clobber: clean -$(RM) $(CLOBBERTARGFILES) diff --git a/usr/src/lib/libctf/Makefile.com b/usr/src/lib/libctf/Makefile.com index 4d1e01d4eb..0169c2a367 100644 --- a/usr/src/lib/libctf/Makefile.com +++ b/usr/src/lib/libctf/Makefile.com @@ -23,43 +23,9 @@ # Use is subject to license terms. # -LIBRARY = libctf.a -VERS = .1 - -COMMON_OBJS = \ - ctf_create.o \ - ctf_decl.o \ - ctf_error.o \ - ctf_hash.o \ - ctf_labels.o \ - ctf_lookup.o \ - ctf_open.o \ - ctf_types.o \ - ctf_util.o - -LIB_OBJS = \ - ctf_lib.o \ - ctf_subr.o - -OBJECTS = $(COMMON_OBJS) $(LIB_OBJS) - -include ../../Makefile.lib +include ../Makefile.shared.com include ../../Makefile.rootfs -SRCS = $(COMMON_OBJS:%.o=../../../common/ctf/%.c) $(LIB_OBJS:%.o=../common/%.c) -LIBS = $(DYNLIB) $(LINTLIB) - -SRCDIR = ../common - -CPPFLAGS += -I../common -I../../../common/ctf -DCTF_OLD_VERSIONS -CFLAGS += $(CCVERBOSE) - -CERRWARN += -_gcc=-Wno-uninitialized - -LDLIBS += -lc - -$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) - .KEEP_STATE: all: $(LIBS) @@ -67,7 +33,4 @@ all: $(LIBS) lint: lintcheck include ../../Makefile.targ - -objs/%.o pics/%.o: ../../../common/ctf/%.c - $(COMPILE.c) -o $@ $< - $(POST_PROCESS_O) +include ../Makefile.shared.targ diff --git a/usr/src/lib/libctf/Makefile.shared.com b/usr/src/lib/libctf/Makefile.shared.com new file mode 100644 index 0000000000..3f2603a29a --- /dev/null +++ b/usr/src/lib/libctf/Makefile.shared.com @@ -0,0 +1,90 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# Copyright 2018 Joyent, Inc. +# + +# +# This Makefile is shared between the libctf native build in tools and +# the libctf build here for the system. +# +LIBRARY = libctf.a +VERS = .1 + +COMMON_OBJS = \ + ctf_create.o \ + ctf_decl.o \ + ctf_dwarf.o \ + ctf_error.o \ + ctf_hash.o \ + ctf_labels.o \ + ctf_lookup.o \ + ctf_open.o \ + ctf_types.o \ + ctf_util.o + +MERGEQ_OBJS = \ + mergeq.o \ + workq.o + +LIST_OBJS = \ + list.o + +LIB_OBJS = \ + ctf_convert.o \ + ctf_elfwrite.o \ + ctf_diff.o \ + ctf_lib.o \ + ctf_merge.o \ + ctf_subr.o + +OBJECTS = $(COMMON_OBJS) $(LIB_OBJS) $(LIST_OBJS) $(MERGEQ_OBJS) +MAPFILEDIR = $(SRC)/lib/libctf + +include $(SRC)/lib/Makefile.lib + +SRCS = \ + $(COMMON_OBJS:%.o=$(SRC)/common/ctf/%.c) \ + $(LIB_OBJS:%.o=$(SRC)/lib/libctf/common/%.c) \ + $(LIST_OBJS:%.o=$(SRC)/common/list/%.c) \ + $(MERGEQ_OBJS:%.o=$(SRC)/lib/mergeq/%.c) + +LIBS = $(DYNLIB) $(LINTLIB) +LDLIBS += -lc -lelf -ldwarf -lavl + +CSTD = $(CSTD_GNU99) +C99LMODE = -Xc99=%all + +SRCDIR = $(SRC)/lib/libctf/common + +CPPFLAGS += -I$(SRC)/lib/libctf/common \ + -I$(SRC)/common/ctf \ + -I$(SRC)/lib/libdwarf/common \ + -I$(SRC)/lib/mergeq \ + -DCTF_OLD_VERSIONS +CFLAGS += $(CCVERBOSE) + +CERRWARN += -_gcc=-Wno-uninitialized + +$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) diff --git a/usr/src/lib/libctf/Makefile.shared.targ b/usr/src/lib/libctf/Makefile.shared.targ new file mode 100644 index 0000000000..b6520f2366 --- /dev/null +++ b/usr/src/lib/libctf/Makefile.shared.targ @@ -0,0 +1,30 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015, Joyent, Inc. All rights reserved. +# + +# +# This Makefile is shared between both the tools and the normal library build. +# + +pics/%.o: $(SRC)/common/ctf/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +pics/%.o: $(SRC)/common/list/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +pics/%.o: $(SRC)/lib/mergeq/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) diff --git a/usr/src/lib/libctf/common/ctf_convert.c b/usr/src/lib/libctf/common/ctf_convert.c new file mode 100644 index 0000000000..cbb4d48c76 --- /dev/null +++ b/usr/src/lib/libctf/common/ctf_convert.c @@ -0,0 +1,210 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2015 Joyent, Inc. + */ + +/* + * Main conversion entry points. This has been designed such that there can be + * any number of different conversion backends. Currently we only have one that + * understands DWARFv2 (and bits of DWARFv4). Each backend should be placed in + * the ctf_converters list and each will be tried in turn. + */ + +#include +#include + +ctf_convert_f ctf_converters[] = { + ctf_dwarf_convert +}; + +#define NCONVERTS (sizeof (ctf_converters) / sizeof (ctf_convert_f)) + +typedef enum ctf_convert_source { + CTFCONV_SOURCE_NONE = 0x0, + CTFCONV_SOURCE_UNKNOWN = 0x01, + CTFCONV_SOURCE_C = 0x02, + CTFCONV_SOURCE_S = 0x04 +} ctf_convert_source_t; + +static void +ctf_convert_ftypes(Elf *elf, ctf_convert_source_t *types) +{ + int i; + Elf_Scn *scn = NULL, *strscn; + *types = CTFCONV_SOURCE_NONE; + GElf_Shdr shdr; + Elf_Data *data, *strdata; + + while ((scn = elf_nextscn(elf, scn)) != NULL) { + + if (gelf_getshdr(scn, &shdr) == NULL) + return; + + if (shdr.sh_type == SHT_SYMTAB) + break; + } + + if (scn == NULL) + return; + + if ((strscn = elf_getscn(elf, shdr.sh_link)) == NULL) + return; + + if ((data = elf_getdata(scn, NULL)) == NULL) + return; + + if ((strdata = elf_getdata(strscn, NULL)) == NULL) + return; + + for (i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) { + GElf_Sym sym; + const char *file; + size_t len; + + if (gelf_getsym(data, i, &sym) == NULL) + return; + + if (GELF_ST_TYPE(sym.st_info) != STT_FILE) + continue; + + file = (const char *)((uintptr_t)strdata->d_buf + sym.st_name); + len = strlen(file); + if (len < 2 || file[len - 2] != '.') { + *types |= CTFCONV_SOURCE_UNKNOWN; + continue; + } + + switch (file[len - 1]) { + case 'c': + *types |= CTFCONV_SOURCE_C; + break; + case 'h': + /* We traditionally ignore header files... */ + break; + case 's': + *types |= CTFCONV_SOURCE_S; + break; + default: + *types |= CTFCONV_SOURCE_UNKNOWN; + break; + } + } +} + +static ctf_file_t * +ctf_elfconvert(int fd, Elf *elf, const char *label, uint_t nthrs, uint_t flags, + int *errp, char *errbuf, size_t errlen) +{ + int err, i; + ctf_file_t *fp = NULL; + boolean_t notsup = B_TRUE; + ctf_convert_source_t type; + + if (errp == NULL) + errp = &err; + + if (elf == NULL) { + *errp = EINVAL; + return (NULL); + } + + if (flags & ~CTF_CONVERT_F_IGNNONC) { + *errp = EINVAL; + return (NULL); + } + + if (elf_kind(elf) != ELF_K_ELF) { + *errp = ECTF_FMT; + return (NULL); + } + + ctf_convert_ftypes(elf, &type); + ctf_dprintf("got types: %d\n", type); + if (flags & CTF_CONVERT_F_IGNNONC) { + if (type == CTFCONV_SOURCE_NONE || + (type & CTFCONV_SOURCE_UNKNOWN)) { + *errp = ECTF_CONVNOCSRC; + return (NULL); + } + } + + for (i = 0; i < NCONVERTS; i++) { + ctf_conv_status_t cs; + + fp = NULL; + cs = ctf_converters[i](fd, elf, nthrs, errp, &fp, errbuf, + errlen); + if (cs == CTF_CONV_SUCCESS) { + notsup = B_FALSE; + break; + } + if (cs == CTF_CONV_ERROR) { + fp = NULL; + notsup = B_FALSE; + break; + } + } + + if (notsup == B_TRUE) { + if ((flags & CTF_CONVERT_F_IGNNONC) != 0 && + (type & CTFCONV_SOURCE_C) == 0) { + *errp = ECTF_CONVNOCSRC; + return (NULL); + } + *errp = ECTF_NOCONVBKEND; + return (NULL); + } + + /* + * Succsesful conversion. + */ + if (fp != NULL) { + if (label == NULL) + label = ""; + if (ctf_add_label(fp, label, fp->ctf_typemax, 0) == CTF_ERR) { + *errp = ctf_errno(fp); + ctf_close(fp); + return (NULL); + } + if (ctf_update(fp) == CTF_ERR) { + *errp = ctf_errno(fp); + ctf_close(fp); + return (NULL); + } + } + + return (fp); +} + +ctf_file_t * +ctf_fdconvert(int fd, const char *label, uint_t nthrs, uint_t flags, int *errp, + char *errbuf, size_t errlen) +{ + int err; + Elf *elf; + ctf_file_t *fp; + + if (errp == NULL) + errp = &err; + + elf = elf_begin(fd, ELF_C_READ, NULL); + if (elf == NULL) { + *errp = ECTF_FMT; + return (NULL); + } + + fp = ctf_elfconvert(fd, elf, label, nthrs, flags, errp, errbuf, errlen); + + (void) elf_end(elf); + return (fp); +} diff --git a/usr/src/lib/libctf/common/ctf_diff.c b/usr/src/lib/libctf/common/ctf_diff.c new file mode 100644 index 0000000000..c8facbc728 --- /dev/null +++ b/usr/src/lib/libctf/common/ctf_diff.c @@ -0,0 +1,1360 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015 Joyent, Inc. All rights reserved. + */ + +/* + * The following is a basic overview of how we diff types in containers (the + * generally interesting part of diff, and what's used by merge). We maintain + * two mapping tables, a table of forward mappings (src->dest), and a reverse + * mapping (dest->src). Both are initialized to contain no mapping, and can also + * be updated to contain a negative mapping. + * + * What we do first is iterate over each type in the src container, and compare + * it with a type in the destination container. This may involve doing recursive + * comparisons -- which can involve cycles. To deal with this, whenever we + * encounter something which may be cyclic, we insert a guess. In other words, + * we assume that it may be true. This is necessary for the classic case of the + * following structure: + * + * struct foo { + * struct foo *foo_next; + * }; + * + * If it turns out that we were wrong, we discard our guesses. + * + * If we find that a given type in src has no corresponding entry in dst, we + * then mark its map as CTF_ERR (-1) to indicate that it has *no* match, as + * opposed to the default value of 0, which indicates an unknown match. + * Once we've done the first iteration through src, we know at that point in + * time whether everything in dst is similar or not and can simply walk over it + * and don't have to do any additional checks. + */ + +#include +#include +#include + +typedef struct ctf_diff_func { + const char *cdf_name; + ulong_t cdf_symidx; + ulong_t cdf_matchidx; +} ctf_diff_func_t; + +typedef struct ctf_diff_obj { + const char *cdo_name; + ulong_t cdo_symidx; + ctf_id_t cdo_id; + ulong_t cdo_matchidx; +} ctf_diff_obj_t; + +typedef struct ctf_diff_guess { + struct ctf_diff_guess *cdg_next; + ctf_id_t cdg_iid; + ctf_id_t cdg_oid; +} ctf_diff_guess_t; + +/* typedef in libctf.h */ +struct ctf_diff { + uint_t cds_flags; + boolean_t cds_tvalid; /* types valid */ + ctf_file_t *cds_ifp; + ctf_file_t *cds_ofp; + ctf_id_t *cds_forward; + ctf_id_t *cds_reverse; + size_t cds_fsize; + size_t cds_rsize; + ctf_diff_type_f cds_func; + ctf_diff_guess_t *cds_guess; + void *cds_arg; + uint_t cds_nifuncs; + uint_t cds_nofuncs; + uint_t cds_nextifunc; + uint_t cds_nextofunc; + ctf_diff_func_t *cds_ifuncs; + ctf_diff_func_t *cds_ofuncs; + boolean_t cds_ffillip; + boolean_t cds_fvalid; + uint_t cds_niobj; + uint_t cds_noobj; + uint_t cds_nextiobj; + uint_t cds_nextoobj; + ctf_diff_obj_t *cds_iobj; + ctf_diff_obj_t *cds_oobj; + boolean_t cds_ofillip; + boolean_t cds_ovalid; +}; + +#define TINDEX(tid) (tid - 1) + +/* + * Team Diff + */ +static int ctf_diff_type(ctf_diff_t *, ctf_file_t *, ctf_id_t, ctf_file_t *, + ctf_id_t); + +static int +ctf_diff_name(ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, ctf_id_t oid) +{ + const char *iname, *oname; + const ctf_type_t *itp, *otp; + + if ((itp = ctf_lookup_by_id(&ifp, iid)) == NULL) + return (CTF_ERR); + + if ((otp = ctf_lookup_by_id(&ofp, oid)) == NULL) + return (ctf_set_errno(ifp, iid)); + + iname = ctf_strptr(ifp, itp->ctt_name); + oname = ctf_strptr(ofp, otp->ctt_name); + + if ((iname == NULL || oname == NULL) && (iname != oname)) + return (B_TRUE); + + /* Two anonymous names are the same */ + if (iname == NULL && oname == NULL) + return (B_FALSE); + + return (strcmp(iname, oname) == 0 ? B_FALSE: B_TRUE); +} + +/* + * For floats and ints + */ +static int +ctf_diff_number(ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, ctf_id_t oid) +{ + ctf_encoding_t ien, den; + + if (ctf_type_encoding(ifp, iid, &ien) != 0) + return (CTF_ERR); + + if (ctf_type_encoding(ofp, oid, &den) != 0) + return (ctf_set_errno(ifp, iid)); + + if (bcmp(&ien, &den, sizeof (ctf_encoding_t)) != 0) + return (B_TRUE); + + return (B_FALSE); +} + +/* + * Two typedefs are equivalent, if after we resolve a chain of typedefs, they + * point to equivalent types. This means that if a size_t is defined as follows: + * + * size_t -> ulong_t -> unsigned long + * size_t -> unsigned long + * + * That we'll ultimately end up treating them the same. + */ +static int +ctf_diff_typedef(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, + ctf_file_t *ofp, ctf_id_t oid) +{ + ctf_id_t iref = CTF_ERR, oref = CTF_ERR; + + while (ctf_type_kind(ifp, iid) == CTF_K_TYPEDEF) { + iref = ctf_type_reference(ifp, iid); + if (iref == CTF_ERR) + return (CTF_ERR); + iid = iref; + } + + while (ctf_type_kind(ofp, oid) == CTF_K_TYPEDEF) { + oref = ctf_type_reference(ofp, oid); + if (oref == CTF_ERR) + return (CTF_ERR); + oid = oref; + } + + VERIFY(iref != CTF_ERR && oref != CTF_ERR); + return (ctf_diff_type(cds, ifp, iref, ofp, oref)); +} + +/* + * Two qualifiers are equivalent iff they point to two equivalent types. + */ +static int +ctf_diff_qualifier(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, + ctf_file_t *ofp, ctf_id_t oid) +{ + ctf_id_t iref, oref; + + iref = ctf_type_reference(ifp, iid); + if (iref == CTF_ERR) + return (CTF_ERR); + + oref = ctf_type_reference(ofp, oid); + if (oref == CTF_ERR) + return (ctf_set_errno(ifp, ctf_errno(ofp))); + + return (ctf_diff_type(cds, ifp, iref, ofp, oref)); +} + +/* + * Two arrays are the same iff they have the same type for contents, the same + * type for the index, and the same number of elements. + */ +static int +ctf_diff_array(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, + ctf_id_t oid) +{ + int ret; + ctf_arinfo_t iar, oar; + + if (ctf_array_info(ifp, iid, &iar) == CTF_ERR) + return (CTF_ERR); + + if (ctf_array_info(ofp, oid, &oar) == CTF_ERR) + return (ctf_set_errno(ifp, ctf_errno(ofp))); + + ret = ctf_diff_type(cds, ifp, iar.ctr_contents, ofp, oar.ctr_contents); + if (ret != B_FALSE) + return (ret); + + if (iar.ctr_nelems != oar.ctr_nelems) + return (B_TRUE); + + /* + * If we're ignoring integer types names, then we're trying to do a bit + * of a logical diff and we don't really care about the fact that the + * index element might not be the same here, what we care about are the + * number of elements and that they're the same type. + */ + if ((cds->cds_flags & CTF_DIFF_F_IGNORE_INTNAMES) == 0) { + ret = ctf_diff_type(cds, ifp, iar.ctr_index, ofp, + oar.ctr_index); + if (ret != B_FALSE) + return (ret); + } + + return (B_FALSE); +} + +/* + * Two function pointers are the same if the following is all true: + * + * o They have the same return type + * o They have the same number of arguments + * o The arguments are of the same type + * o They have the same flags + */ +static int +ctf_diff_fptr(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, + ctf_id_t oid) +{ + int ret, i; + ctf_funcinfo_t ifunc, ofunc; + ctf_id_t *iids, *oids; + + if (ctf_func_info_by_id(ifp, iid, &ifunc) == CTF_ERR) + return (CTF_ERR); + + if (ctf_func_info_by_id(ofp, oid, &ofunc) == CTF_ERR) + return (ctf_set_errno(ifp, ctf_errno(ofp))); + + if (ifunc.ctc_argc != ofunc.ctc_argc) + return (B_TRUE); + + if (ifunc.ctc_flags != ofunc.ctc_flags) + return (B_TRUE); + + ret = ctf_diff_type(cds, ifp, ifunc.ctc_return, ofp, ofunc.ctc_return); + if (ret != B_FALSE) + return (ret); + + iids = ctf_alloc(sizeof (ctf_id_t) * ifunc.ctc_argc); + if (iids == NULL) + return (ctf_set_errno(ifp, ENOMEM)); + + oids = ctf_alloc(sizeof (ctf_id_t) * ifunc.ctc_argc); + if (oids == NULL) { + ctf_free(iids, sizeof (ctf_id_t) * ifunc.ctc_argc); + return (ctf_set_errno(ifp, ENOMEM)); + } + + if (ctf_func_args_by_id(ifp, iid, ifunc.ctc_argc, iids) == CTF_ERR) { + ret = CTF_ERR; + goto out; + } + + if (ctf_func_args_by_id(ofp, oid, ofunc.ctc_argc, oids) == CTF_ERR) { + ret = ctf_set_errno(ifp, ctf_errno(ofp)); + goto out; + } + + ret = B_TRUE; + for (i = 0; i < ifunc.ctc_argc; i++) { + ret = ctf_diff_type(cds, ifp, iids[i], ofp, oids[i]); + if (ret != B_FALSE) + goto out; + } + ret = B_FALSE; + +out: + ctf_free(iids, sizeof (ctf_id_t) * ifunc.ctc_argc); + ctf_free(oids, sizeof (ctf_id_t) * ofunc.ctc_argc); + return (ret); +} + +/* + * Two structures are the same if every member is identical to its corresponding + * type, at the same offset, and has the same name, as well as them having the + * same overall size. + */ +static int +ctf_diff_struct(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, + ctf_id_t oid) +{ + ctf_file_t *oifp; + const ctf_type_t *itp, *otp; + ssize_t isize, iincr, osize, oincr; + const ctf_member_t *imp, *omp; + const ctf_lmember_t *ilmp, *olmp; + int n; + ctf_diff_guess_t *cdg; + + oifp = ifp; + + if ((itp = ctf_lookup_by_id(&ifp, iid)) == NULL) + return (CTF_ERR); + + if ((otp = ctf_lookup_by_id(&ofp, oid)) == NULL) + return (ctf_set_errno(oifp, ctf_errno(ofp))); + + if (ctf_type_size(ifp, iid) != ctf_type_size(ofp, oid)) + return (B_TRUE); + + if (LCTF_INFO_VLEN(ifp, itp->ctt_info) != + LCTF_INFO_VLEN(ofp, otp->ctt_info)) + return (B_TRUE); + + (void) ctf_get_ctt_size(ifp, itp, &isize, &iincr); + (void) ctf_get_ctt_size(ofp, otp, &osize, &oincr); + + if (ifp->ctf_version == CTF_VERSION_1 || isize < CTF_LSTRUCT_THRESH) { + imp = (const ctf_member_t *)((uintptr_t)itp + iincr); + ilmp = NULL; + } else { + imp = NULL; + ilmp = (const ctf_lmember_t *)((uintptr_t)itp + iincr); + } + + if (ofp->ctf_version == CTF_VERSION_1 || osize < CTF_LSTRUCT_THRESH) { + omp = (const ctf_member_t *)((uintptr_t)otp + oincr); + olmp = NULL; + } else { + omp = NULL; + olmp = (const ctf_lmember_t *)((uintptr_t)otp + oincr); + } + + /* + * Insert our assumption that they're equal for the moment. + */ + cdg = ctf_alloc(sizeof (ctf_diff_guess_t)); + if (cdg == NULL) + return (ctf_set_errno(ifp, ENOMEM)); + cdg->cdg_iid = iid; + cdg->cdg_oid = oid; + cdg->cdg_next = cds->cds_guess; + cds->cds_guess = cdg; + cds->cds_forward[TINDEX(iid)] = oid; + cds->cds_reverse[TINDEX(oid)] = iid; + + for (n = LCTF_INFO_VLEN(ifp, itp->ctt_info); n != 0; n--) { + const char *iname, *oname; + ulong_t ioff, ooff; + ctf_id_t itype, otype; + int ret; + + if (imp != NULL) { + iname = ctf_strptr(ifp, imp->ctm_name); + ioff = imp->ctm_offset; + itype = imp->ctm_type; + } else { + iname = ctf_strptr(ifp, ilmp->ctlm_name); + ioff = CTF_LMEM_OFFSET(ilmp); + itype = ilmp->ctlm_type; + } + + if (omp != NULL) { + oname = ctf_strptr(ofp, omp->ctm_name); + ooff = omp->ctm_offset; + otype = omp->ctm_type; + } else { + oname = ctf_strptr(ofp, olmp->ctlm_name); + ooff = CTF_LMEM_OFFSET(olmp); + otype = olmp->ctlm_type; + } + + if (ioff != ooff) { + return (B_TRUE); + } + if (strcmp(iname, oname) != 0) { + return (B_TRUE); + } + ret = ctf_diff_type(cds, ifp, itype, ofp, otype); + if (ret != B_FALSE) { + return (ret); + } + + /* Advance our pointers */ + if (imp != NULL) + imp++; + if (ilmp != NULL) + ilmp++; + if (omp != NULL) + omp++; + if (olmp != NULL) + olmp++; + } + + return (B_FALSE); +} + +/* + * Two unions are the same if they have the same set of members. This is similar + * to, but slightly different from a struct. The offsets of members don't + * matter. However, there is no guarantee of ordering so we have to fall back to + * doing an O(N^2) scan. + */ +typedef struct ctf_diff_union_member { + ctf_diff_t *cdum_cds; + ctf_file_t *cdum_fp; + ctf_file_t *cdum_iterfp; + const char *cdum_name; + ctf_id_t cdum_type; + int cdum_ret; +} ctf_diff_union_member_t; + +typedef struct ctf_diff_union_fp { + ctf_diff_t *cduf_cds; + ctf_file_t *cduf_curfp; + ctf_file_t *cduf_altfp; + ctf_id_t cduf_type; + int cduf_ret; +} ctf_diff_union_fp_t; + +/* ARGSUSED */ +static int +ctf_diff_union_check_member(const char *name, ctf_id_t id, ulong_t off, + void *arg) +{ + int ret; + ctf_diff_union_member_t *cdump = arg; + + if (strcmp(name, cdump->cdum_name) != 0) + return (0); + + ret = ctf_diff_type(cdump->cdum_cds, cdump->cdum_fp, cdump->cdum_type, + cdump->cdum_iterfp, id); + if (ret == CTF_ERR) { + cdump->cdum_ret = CTF_ERR; + return (1); + } + + if (ret == B_FALSE) { + cdump->cdum_ret = B_FALSE; + /* Return non-zero to stop iteration as we have a match */ + return (1); + } + + return (0); +} + +/* ARGSUSED */ +static int +ctf_diff_union_check_fp(const char *name, ctf_id_t id, ulong_t off, void *arg) +{ + int ret; + ctf_diff_union_member_t cdum; + ctf_diff_union_fp_t *cdufp = arg; + + cdum.cdum_cds = cdufp->cduf_cds; + cdum.cdum_fp = cdufp->cduf_curfp; + cdum.cdum_iterfp = cdufp->cduf_altfp; + cdum.cdum_name = name; + cdum.cdum_type = id; + cdum.cdum_ret = B_TRUE; + + ret = ctf_member_iter(cdum.cdum_iterfp, cdufp->cduf_type, + ctf_diff_union_check_member, &cdum); + if (ret == 0 || cdum.cdum_ret == CTF_ERR) { + /* No match found or error, terminate now */ + cdufp->cduf_ret = cdum.cdum_ret; + return (1); + } else if (ret == CTF_ERR) { + (void) ctf_set_errno(cdum.cdum_fp, ctf_errno(cdum.cdum_iterfp)); + cdufp->cduf_ret = CTF_ERR; + return (1); + } else { + ASSERT(cdum.cdum_ret == B_FALSE); + cdufp->cduf_ret = cdum.cdum_ret; + return (0); + } +} + +static int +ctf_diff_union(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, + ctf_id_t oid) +{ + ctf_file_t *oifp; + const ctf_type_t *itp, *otp; + ctf_diff_union_fp_t cduf; + ctf_diff_guess_t *cdg; + int ret; + + oifp = ifp; + if ((itp = ctf_lookup_by_id(&ifp, iid)) == NULL) + return (CTF_ERR); + if ((otp = ctf_lookup_by_id(&ofp, oid)) == NULL) + return (ctf_set_errno(oifp, ctf_errno(ofp))); + + if (LCTF_INFO_VLEN(ifp, itp->ctt_info) != + LCTF_INFO_VLEN(ofp, otp->ctt_info)) + return (B_TRUE); + + cdg = ctf_alloc(sizeof (ctf_diff_guess_t)); + if (cdg == NULL) + return (ctf_set_errno(ifp, ENOMEM)); + cdg->cdg_iid = iid; + cdg->cdg_oid = oid; + cdg->cdg_next = cds->cds_guess; + cds->cds_guess = cdg; + cds->cds_forward[TINDEX(iid)] = oid; + cds->cds_reverse[TINDEX(oid)] = iid; + + cduf.cduf_cds = cds; + cduf.cduf_curfp = ifp; + cduf.cduf_altfp = ofp; + cduf.cduf_type = oid; + cduf.cduf_ret = B_TRUE; + ret = ctf_member_iter(ifp, iid, ctf_diff_union_check_fp, &cduf); + if (ret != CTF_ERR) + ret = cduf.cduf_ret; + + return (ret); +} + +/* + * Two enums are equivalent if they share the same underlying type and they have + * the same set of members. + */ +static int +ctf_diff_enum(ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, ctf_id_t oid) +{ + ctf_file_t *oifp; + const ctf_type_t *itp, *otp; + ssize_t iincr, oincr; + const ctf_enum_t *iep, *oep; + int n; + + oifp = ifp; + if ((itp = ctf_lookup_by_id(&ifp, iid)) == NULL) + return (CTF_ERR); + if ((otp = ctf_lookup_by_id(&ofp, oid)) == NULL) + return (ctf_set_errno(oifp, ctf_errno(ofp))); + + if (LCTF_INFO_VLEN(ifp, itp->ctt_info) != + LCTF_INFO_VLEN(ofp, otp->ctt_info)) + return (B_TRUE); + + (void) ctf_get_ctt_size(ifp, itp, NULL, &iincr); + (void) ctf_get_ctt_size(ofp, otp, NULL, &oincr); + iep = (const ctf_enum_t *)((uintptr_t)itp + iincr); + oep = (const ctf_enum_t *)((uintptr_t)otp + oincr); + + for (n = LCTF_INFO_VLEN(ifp, itp->ctt_info); n != 0; + n--, iep++, oep++) { + if (strcmp(ctf_strptr(ifp, iep->cte_name), + ctf_strptr(ofp, oep->cte_name)) != 0) + return (B_TRUE); + + if (iep->cte_value != oep->cte_value) + return (B_TRUE); + } + + return (B_FALSE); +} + +/* + * Two forwards are equivalent in one of two cases. If both are forwards, than + * they are the same. Otherwise, they're equivalent if one is a struct or union + * and the other is a forward. + */ +static int +ctf_diff_forward(ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, ctf_id_t oid) +{ + int ikind, okind; + + ikind = ctf_type_kind(ifp, iid); + okind = ctf_type_kind(ofp, oid); + + if (ikind == okind) { + ASSERT(ikind == CTF_K_FORWARD); + return (B_FALSE); + } else if (ikind == CTF_K_FORWARD) { + return (okind != CTF_K_UNION && okind != CTF_K_STRUCT); + } else { + return (ikind != CTF_K_UNION && ikind != CTF_K_STRUCT); + } +} + +/* + * Are two types equivalent? + */ +int +ctf_diff_type(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, + ctf_id_t oid) +{ + int ret, ikind, okind; + + /* Do a quick short circuit */ + if (ifp == ofp && iid == oid) + return (B_FALSE); + + /* + * Check if it's something we've already encountered in a forward + * reference or forward negative table. Also double check the reverse + * table. + */ + if (cds->cds_forward[TINDEX(iid)] == oid) + return (B_FALSE); + if (cds->cds_forward[TINDEX(iid)] != 0) + return (B_TRUE); + if (cds->cds_reverse[TINDEX(oid)] == iid) + return (B_FALSE); + if ((cds->cds_flags & CTF_DIFF_F_IGNORE_INTNAMES) == 0 && + cds->cds_reverse[TINDEX(oid)] != 0) + return (B_TRUE); + + ikind = ctf_type_kind(ifp, iid); + okind = ctf_type_kind(ofp, oid); + + if (ikind != okind && + ikind != CTF_K_FORWARD && okind != CTF_K_FORWARD) + return (B_TRUE); + + /* Check names */ + if ((ret = ctf_diff_name(ifp, iid, ofp, oid)) != B_FALSE) { + if (ikind != okind || ikind != CTF_K_INTEGER || + (cds->cds_flags & CTF_DIFF_F_IGNORE_INTNAMES) == 0) + return (ret); + } + + if (ikind == CTF_K_FORWARD || okind == CTF_K_FORWARD) + return (ctf_diff_forward(ifp, iid, ofp, oid)); + + switch (ikind) { + case CTF_K_INTEGER: + case CTF_K_FLOAT: + ret = ctf_diff_number(ifp, iid, ofp, oid); + break; + case CTF_K_ARRAY: + ret = ctf_diff_array(cds, ifp, iid, ofp, oid); + break; + case CTF_K_FUNCTION: + ret = ctf_diff_fptr(cds, ifp, iid, ofp, oid); + break; + case CTF_K_STRUCT: + ret = ctf_diff_struct(cds, ifp, iid, ofp, oid); + break; + case CTF_K_UNION: + ret = ctf_diff_union(cds, ifp, iid, ofp, oid); + break; + case CTF_K_ENUM: + ret = ctf_diff_enum(ifp, iid, ofp, oid); + break; + case CTF_K_FORWARD: + ret = ctf_diff_forward(ifp, iid, ofp, oid); + break; + case CTF_K_TYPEDEF: + ret = ctf_diff_typedef(cds, ifp, iid, ofp, oid); + break; + case CTF_K_POINTER: + case CTF_K_VOLATILE: + case CTF_K_CONST: + case CTF_K_RESTRICT: + ret = ctf_diff_qualifier(cds, ifp, iid, ofp, oid); + break; + case CTF_K_UNKNOWN: + /* + * The current CTF tools use CTF_K_UNKNOWN as a padding type. We + * always declare two instances of CTF_K_UNKNOWN as different, + * even though this leads to additional diff noise. + */ + ret = B_TRUE; + break; + default: + abort(); + } + + return (ret); +} + +/* + * Walk every type in the first container and try to find a match in the second. + * If there is a match, then update both the forward and reverse mapping tables. + * + * The self variable tells us whether or not we should be comparing the input + * ctf container with itself or not. + */ +static int +ctf_diff_pass1(ctf_diff_t *cds, boolean_t self) +{ + int i, j, diff; + int istart, iend, jstart, jend; + + istart = 1; + iend = cds->cds_ifp->ctf_typemax; + if (cds->cds_ifp->ctf_flags & LCTF_CHILD) { + istart += CTF_CHILD_START; + iend += CTF_CHILD_START; + } + + jstart = 1; + jend = cds->cds_ofp->ctf_typemax; + if (cds->cds_ofp->ctf_flags & LCTF_CHILD) { + jstart += CTF_CHILD_START; + jend += CTF_CHILD_START; + } + + for (i = istart; i <= iend; i++) { + diff = B_TRUE; + + /* + * If we're doing a self diff for dedup purposes, then we want + * to ensure that we compare a type i with every type in the + * range, [ 1, i ). Yes, this does mean that when i equals 1, + * we won't compare anything. + */ + if (self == B_TRUE) { + jstart = istart; + jend = i - 1; + } + for (j = jstart; j <= jend; j++) { + ctf_diff_guess_t *cdg, *tofree; + + ASSERT(cds->cds_guess == NULL); + diff = ctf_diff_type(cds, cds->cds_ifp, i, + cds->cds_ofp, j); + if (diff == CTF_ERR) + return (CTF_ERR); + + /* Clean up our guesses */ + cdg = cds->cds_guess; + cds->cds_guess = NULL; + while (cdg != NULL) { + if (diff == B_TRUE) { + cds->cds_forward[TINDEX(cdg->cdg_iid)] = + 0; + cds->cds_reverse[TINDEX(cdg->cdg_oid)] = + 0; + } + tofree = cdg; + cdg = cdg->cdg_next; + ctf_free(tofree, sizeof (ctf_diff_guess_t)); + } + + /* Found a hit, update the tables */ + if (diff == B_FALSE) { + cds->cds_forward[TINDEX(i)] = j; + if (cds->cds_reverse[TINDEX(j)] == 0) + cds->cds_reverse[TINDEX(j)] = i; + break; + } + } + + /* Call the callback at this point */ + if (diff == B_TRUE) { + cds->cds_forward[TINDEX(i)] = CTF_ERR; + cds->cds_func(cds->cds_ifp, i, B_FALSE, NULL, CTF_ERR, + cds->cds_arg); + } else { + cds->cds_func(cds->cds_ifp, i, B_TRUE, cds->cds_ofp, j, + cds->cds_arg); + } + } + + return (0); +} + +/* + * Now we need to walk the second container and emit anything that we didn't + * find as common in the first pass. + */ +static int +ctf_diff_pass2(ctf_diff_t *cds) +{ + int i, start, end; + + start = 0x1; + end = cds->cds_ofp->ctf_typemax; + if (cds->cds_ofp->ctf_flags & LCTF_CHILD) { + start += CTF_CHILD_START; + end += CTF_CHILD_START; + } + + for (i = start; i <= end; i++) { + if (cds->cds_reverse[TINDEX(i)] != 0) + continue; + cds->cds_func(cds->cds_ofp, i, B_FALSE, NULL, CTF_ERR, + cds->cds_arg); + } + + return (0); +} + +int +ctf_diff_init(ctf_file_t *ifp, ctf_file_t *ofp, ctf_diff_t **cdsp) +{ + ctf_diff_t *cds; + size_t fsize, rsize; + + cds = ctf_alloc(sizeof (ctf_diff_t)); + if (cds == NULL) + return (ctf_set_errno(ifp, ENOMEM)); + + bzero(cds, sizeof (ctf_diff_t)); + cds->cds_ifp = ifp; + cds->cds_ofp = ofp; + + fsize = sizeof (ctf_id_t) * ifp->ctf_typemax; + rsize = sizeof (ctf_id_t) * ofp->ctf_typemax; + if (ifp->ctf_flags & LCTF_CHILD) + fsize += CTF_CHILD_START * sizeof (ctf_id_t); + if (ofp->ctf_flags & LCTF_CHILD) + rsize += CTF_CHILD_START * sizeof (ctf_id_t); + + cds->cds_forward = ctf_alloc(fsize); + if (cds->cds_forward == NULL) { + ctf_free(cds, sizeof (ctf_diff_t)); + return (ctf_set_errno(ifp, ENOMEM)); + } + cds->cds_fsize = fsize; + cds->cds_reverse = ctf_alloc(rsize); + if (cds->cds_reverse == NULL) { + ctf_free(cds->cds_forward, fsize); + ctf_free(cds, sizeof (ctf_diff_t)); + return (ctf_set_errno(ifp, ENOMEM)); + } + cds->cds_rsize = rsize; + bzero(cds->cds_forward, fsize); + bzero(cds->cds_reverse, rsize); + + cds->cds_ifp->ctf_refcnt++; + cds->cds_ofp->ctf_refcnt++; + *cdsp = cds; + return (0); +} + +int +ctf_diff_types(ctf_diff_t *cds, ctf_diff_type_f cb, void *arg) +{ + int ret; + + cds->cds_func = cb; + cds->cds_arg = arg; + + ret = ctf_diff_pass1(cds, B_FALSE); + if (ret == 0) + ret = ctf_diff_pass2(cds); + + cds->cds_func = NULL; + cds->cds_arg = NULL; + cds->cds_tvalid = B_TRUE; + return (ret); +} + +/* + * Do a diff where we're comparing a container with itself. In other words we'd + * like to know what types are actually duplicates of existing types in the + * container. + * + * Note this should remain private to libctf and not be exported in the public + * mapfile for the time being. + */ +int +ctf_diff_self(ctf_diff_t *cds, ctf_diff_type_f cb, void *arg) +{ + if (cds->cds_ifp != cds->cds_ofp) + return (EINVAL); + + cds->cds_func = cb; + cds->cds_arg = arg; + + return (ctf_diff_pass1(cds, B_TRUE)); +} + + +void +ctf_diff_fini(ctf_diff_t *cds) +{ + ctf_diff_guess_t *cdg; + size_t fsize, rsize; + + if (cds == NULL) + return; + + cds->cds_ifp->ctf_refcnt--; + cds->cds_ofp->ctf_refcnt--; + + fsize = sizeof (ctf_id_t) * cds->cds_ifp->ctf_typemax; + rsize = sizeof (ctf_id_t) * cds->cds_ofp->ctf_typemax; + if (cds->cds_ifp->ctf_flags & LCTF_CHILD) + fsize += CTF_CHILD_START * sizeof (ctf_id_t); + if (cds->cds_ofp->ctf_flags & LCTF_CHILD) + rsize += CTF_CHILD_START * sizeof (ctf_id_t); + + if (cds->cds_ifuncs != NULL) + ctf_free(cds->cds_ifuncs, + sizeof (ctf_diff_func_t) * cds->cds_nifuncs); + if (cds->cds_ofuncs != NULL) + ctf_free(cds->cds_ofuncs, + sizeof (ctf_diff_func_t) * cds->cds_nofuncs); + if (cds->cds_iobj != NULL) + ctf_free(cds->cds_iobj, + sizeof (ctf_diff_obj_t) * cds->cds_niobj); + if (cds->cds_oobj != NULL) + ctf_free(cds->cds_oobj, + sizeof (ctf_diff_obj_t) * cds->cds_noobj); + cdg = cds->cds_guess; + while (cdg != NULL) { + ctf_diff_guess_t *tofree = cdg; + cdg = cdg->cdg_next; + ctf_free(tofree, sizeof (ctf_diff_guess_t)); + } + if (cds->cds_forward != NULL) + ctf_free(cds->cds_forward, cds->cds_fsize); + if (cds->cds_reverse != NULL) + ctf_free(cds->cds_reverse, cds->cds_rsize); + ctf_free(cds, sizeof (ctf_diff_t)); +} + +uint_t +ctf_diff_getflags(ctf_diff_t *cds) +{ + return (cds->cds_flags); +} + +int +ctf_diff_setflags(ctf_diff_t *cds, uint_t flags) +{ + if ((flags & ~CTF_DIFF_F_IGNORE_INTNAMES) != 0) + return (ctf_set_errno(cds->cds_ifp, EINVAL)); + + cds->cds_flags = flags; + return (0); +} + +static boolean_t +ctf_diff_symid(ctf_diff_t *cds, ctf_id_t iid, ctf_id_t oid) +{ + ctf_file_t *ifp, *ofp; + + ifp = cds->cds_ifp; + ofp = cds->cds_ofp; + + /* + * If we have parent containers on the scene here, we need to go through + * and do a full diff check because a diff for types will not actually + * go through and check types in the parent container. + */ + if (iid == 0 || oid == 0) + return (iid == oid ? B_FALSE: B_TRUE); + + if (!(ifp->ctf_flags & LCTF_CHILD) && !(ofp->ctf_flags & LCTF_CHILD)) { + if (cds->cds_forward[TINDEX(iid)] != oid) + return (B_TRUE); + return (B_FALSE); + } + + return (ctf_diff_type(cds, ifp, iid, ofp, oid)); +} + +/* ARGSUSED */ +static void +ctf_diff_void_cb(ctf_file_t *ifp, ctf_id_t iid, boolean_t same, ctf_file_t *ofp, + ctf_id_t oid, void *arg) +{ +} + +/* ARGSUSED */ +static int +ctf_diff_func_count(const char *name, ulong_t symidx, ctf_funcinfo_t *fip, + void *arg) +{ + uint32_t *ip = arg; + + *ip = *ip + 1; + return (0); +} + +/* ARGSUSED */ +static int +ctf_diff_func_fill_cb(const char *name, ulong_t symidx, ctf_funcinfo_t *fip, + void *arg) +{ + uint_t *next, max; + ctf_diff_func_t *funcptr; + ctf_diff_t *cds = arg; + + if (cds->cds_ffillip == B_TRUE) { + max = cds->cds_nifuncs; + next = &cds->cds_nextifunc; + funcptr = cds->cds_ifuncs + *next; + } else { + max = cds->cds_nofuncs; + next = &cds->cds_nextofunc; + funcptr = cds->cds_ofuncs + *next; + + } + + VERIFY(*next < max); + funcptr->cdf_name = name; + funcptr->cdf_symidx = symidx; + funcptr->cdf_matchidx = ULONG_MAX; + *next = *next + 1; + + return (0); +} + +int +ctf_diff_func_fill(ctf_diff_t *cds) +{ + int ret; + uint32_t ifcount, ofcount, idcnt, cti; + ulong_t i, j; + ctf_id_t *iids, *oids; + + ifcount = 0; + ofcount = 0; + idcnt = 0; + iids = NULL; + oids = NULL; + + ret = ctf_function_iter(cds->cds_ifp, ctf_diff_func_count, &ifcount); + if (ret != 0) + return (ret); + ret = ctf_function_iter(cds->cds_ofp, ctf_diff_func_count, &ofcount); + if (ret != 0) + return (ret); + + cds->cds_ifuncs = ctf_alloc(sizeof (ctf_diff_func_t) * ifcount); + if (cds->cds_ifuncs == NULL) + return (ctf_set_errno(cds->cds_ifp, ENOMEM)); + + cds->cds_nifuncs = ifcount; + cds->cds_nextifunc = 0; + + cds->cds_ofuncs = ctf_alloc(sizeof (ctf_diff_func_t) * ofcount); + if (cds->cds_ofuncs == NULL) + return (ctf_set_errno(cds->cds_ifp, ENOMEM)); + + cds->cds_nofuncs = ofcount; + cds->cds_nextofunc = 0; + + cds->cds_ffillip = B_TRUE; + if ((ret = ctf_function_iter(cds->cds_ifp, ctf_diff_func_fill_cb, + cds)) != 0) + return (ret); + + cds->cds_ffillip = B_FALSE; + if ((ret = ctf_function_iter(cds->cds_ofp, ctf_diff_func_fill_cb, + cds)) != 0) + return (ret); + + /* + * Everything is initialized to not match. This could probably be faster + * with something that used a hash. But this part of the diff isn't used + * by merge. + */ + for (i = 0; i < cds->cds_nifuncs; i++) { + for (j = 0; j < cds->cds_nofuncs; j++) { + ctf_diff_func_t *ifd, *ofd; + ctf_funcinfo_t ifip, ofip; + boolean_t match; + + ifd = &cds->cds_ifuncs[i]; + ofd = &cds->cds_ofuncs[j]; + if (strcmp(ifd->cdf_name, ofd->cdf_name) != 0) + continue; + + ret = ctf_func_info(cds->cds_ifp, ifd->cdf_symidx, + &ifip); + if (ret != 0) + goto out; + ret = ctf_func_info(cds->cds_ofp, ofd->cdf_symidx, + &ofip); + if (ret != 0) { + ret = ctf_set_errno(cds->cds_ifp, + ctf_errno(cds->cds_ofp)); + goto out; + } + + if (ifip.ctc_argc != ofip.ctc_argc && + ifip.ctc_flags != ofip.ctc_flags) + continue; + + /* Validate return type and arguments are the same */ + if (ctf_diff_symid(cds, ifip.ctc_return, + ofip.ctc_return)) + continue; + + if (ifip.ctc_argc > idcnt) { + if (iids != NULL) + ctf_free(iids, + sizeof (ctf_id_t) * idcnt); + if (oids != NULL) + ctf_free(oids, + sizeof (ctf_id_t) * idcnt); + iids = oids = NULL; + idcnt = ifip.ctc_argc; + iids = ctf_alloc(sizeof (ctf_id_t) * idcnt); + if (iids == NULL) { + ret = ctf_set_errno(cds->cds_ifp, + ENOMEM); + goto out; + } + oids = ctf_alloc(sizeof (ctf_id_t) * idcnt); + if (iids == NULL) { + ret = ctf_set_errno(cds->cds_ifp, + ENOMEM); + goto out; + } + } + + if ((ret = ctf_func_args(cds->cds_ifp, ifd->cdf_symidx, + ifip.ctc_argc, iids)) != 0) + goto out; + if ((ret = ctf_func_args(cds->cds_ofp, ofd->cdf_symidx, + ofip.ctc_argc, oids)) != 0) + goto out; + + match = B_TRUE; + for (cti = 0; cti < ifip.ctc_argc; cti++) { + if (ctf_diff_symid(cds, iids[cti], oids[cti])) { + match = B_FALSE; + break; + } + } + + if (match == B_FALSE) + continue; + + ifd->cdf_matchidx = j; + ofd->cdf_matchidx = i; + break; + } + } + + ret = 0; + +out: + if (iids != NULL) + ctf_free(iids, sizeof (ctf_id_t) * idcnt); + if (oids != NULL) + ctf_free(oids, sizeof (ctf_id_t) * idcnt); + + return (ret); +} + +/* + * In general, two functions are the same, if they have the same name and their + * arguments have the same types, including the return type. Like types, we + * basically have to do this in two passes. In the first phase we walk every + * type in the first container and try to find a match in the second. + */ +int +ctf_diff_functions(ctf_diff_t *cds, ctf_diff_func_f cb, void *arg) +{ + int ret; + ulong_t i; + + if (cds->cds_tvalid == B_FALSE) { + if ((ret = ctf_diff_types(cds, ctf_diff_void_cb, NULL)) != 0) + return (ret); + } + + if (cds->cds_fvalid == B_FALSE) { + if ((ret = ctf_diff_func_fill(cds)) != 0) + return (ret); + cds->cds_fvalid = B_TRUE; + } + + for (i = 0; i < cds->cds_nifuncs; i++) { + if (cds->cds_ifuncs[i].cdf_matchidx == ULONG_MAX) { + cb(cds->cds_ifp, cds->cds_ifuncs[i].cdf_symidx, + B_FALSE, NULL, ULONG_MAX, arg); + } else { + ulong_t idx = cds->cds_ifuncs[i].cdf_matchidx; + cb(cds->cds_ifp, cds->cds_ifuncs[i].cdf_symidx, B_TRUE, + cds->cds_ofp, cds->cds_ofuncs[idx].cdf_symidx, arg); + } + } + + for (i = 0; i < cds->cds_nofuncs; i++) { + if (cds->cds_ofuncs[i].cdf_matchidx != ULONG_MAX) + continue; + cb(cds->cds_ofp, cds->cds_ofuncs[i].cdf_symidx, B_FALSE, + NULL, ULONG_MAX, arg); + } + + return (0); +} + +static int +ctf_diff_obj_fill_cb(const char *name, ctf_id_t id, ulong_t symidx, void *arg) +{ + uint_t *next, max; + ctf_diff_obj_t *objptr; + ctf_diff_t *cds = arg; + + if (cds->cds_ofillip == B_TRUE) { + max = cds->cds_niobj; + next = &cds->cds_nextiobj; + objptr = cds->cds_iobj + *next; + } else { + max = cds->cds_noobj; + next = &cds->cds_nextoobj; + objptr = cds->cds_oobj+ *next; + + } + + VERIFY(*next < max); + objptr->cdo_name = name; + objptr->cdo_symidx = symidx; + objptr->cdo_id = id; + objptr->cdo_matchidx = ULONG_MAX; + *next = *next + 1; + + return (0); +} + +/* ARGSUSED */ +static int +ctf_diff_obj_count(const char *name, ctf_id_t id, ulong_t symidx, void *arg) +{ + uint32_t *count = arg; + + *count = *count + 1; + + return (0); +} + + +static int +ctf_diff_obj_fill(ctf_diff_t *cds) +{ + int ret; + uint32_t iocount, oocount; + ulong_t i, j; + + iocount = 0; + oocount = 0; + + ret = ctf_object_iter(cds->cds_ifp, ctf_diff_obj_count, &iocount); + if (ret != 0) + return (ret); + + ret = ctf_object_iter(cds->cds_ofp, ctf_diff_obj_count, &oocount); + if (ret != 0) + return (ret); + + cds->cds_iobj = ctf_alloc(sizeof (ctf_diff_obj_t) * iocount); + if (cds->cds_iobj == NULL) + return (ctf_set_errno(cds->cds_ifp, ENOMEM)); + cds->cds_niobj = iocount; + cds->cds_nextiobj = 0; + + cds->cds_oobj = ctf_alloc(sizeof (ctf_diff_obj_t) * oocount); + if (cds->cds_oobj == NULL) + return (ctf_set_errno(cds->cds_ifp, ENOMEM)); + cds->cds_noobj = oocount; + cds->cds_nextoobj = 0; + + cds->cds_ofillip = B_TRUE; + if ((ret = ctf_object_iter(cds->cds_ifp, ctf_diff_obj_fill_cb, + cds)) != 0) + return (ret); + + cds->cds_ofillip = B_FALSE; + if ((ret = ctf_object_iter(cds->cds_ofp, ctf_diff_obj_fill_cb, + cds)) != 0) + return (ret); + + for (i = 0; i < cds->cds_niobj; i++) { + for (j = 0; j < cds->cds_noobj; j++) { + ctf_diff_obj_t *id, *od; + + id = &cds->cds_iobj[i]; + od = &cds->cds_oobj[j]; + + if (id->cdo_name == NULL || od->cdo_name == NULL) + continue; + if (strcmp(id->cdo_name, od->cdo_name) != 0) + continue; + + if (ctf_diff_symid(cds, id->cdo_id, od->cdo_id)) { + continue; + } + + id->cdo_matchidx = j; + od->cdo_matchidx = i; + break; + } + } + + return (0); +} + +int +ctf_diff_objects(ctf_diff_t *cds, ctf_diff_obj_f cb, void *arg) +{ + int ret; + ulong_t i; + + if (cds->cds_tvalid == B_FALSE) { + if ((ret = ctf_diff_types(cds, ctf_diff_void_cb, NULL)) != 0) + return (ret); + } + + if (cds->cds_ovalid == B_FALSE) { + if ((ret = ctf_diff_obj_fill(cds)) != 0) + return (ret); + cds->cds_ovalid = B_TRUE; + } + + for (i = 0; i < cds->cds_niobj; i++) { + ctf_diff_obj_t *o = &cds->cds_iobj[i]; + + if (cds->cds_iobj[i].cdo_matchidx == ULONG_MAX) { + cb(cds->cds_ifp, o->cdo_symidx, o->cdo_id, B_FALSE, + NULL, ULONG_MAX, CTF_ERR, arg); + } else { + ctf_diff_obj_t *alt = &cds->cds_oobj[o->cdo_matchidx]; + cb(cds->cds_ifp, o->cdo_symidx, o->cdo_id, B_TRUE, + cds->cds_ofp, alt->cdo_symidx, alt->cdo_id, arg); + } + } + + for (i = 0; i < cds->cds_noobj; i++) { + ctf_diff_obj_t *o = &cds->cds_oobj[i]; + if (o->cdo_matchidx != ULONG_MAX) + continue; + cb(cds->cds_ofp, o->cdo_symidx, o->cdo_id, B_FALSE, NULL, + ULONG_MAX, CTF_ERR, arg); + } + + return (0); +} diff --git a/usr/src/lib/libctf/common/ctf_dwarf.c b/usr/src/lib/libctf/common/ctf_dwarf.c new file mode 100644 index 0000000000..18be598ed9 --- /dev/null +++ b/usr/src/lib/libctf/common/ctf_dwarf.c @@ -0,0 +1,2995 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * Copyright 2012 Jason King. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright 2018 Joyent, Inc. + */ + +/* + * CTF DWARF conversion theory. + * + * DWARF data contains a series of compilation units. Each compilation unit + * generally refers to an object file or what once was, in the case of linked + * binaries and shared objects. Each compilation unit has a series of what DWARF + * calls a DIE (Debugging Information Entry). The set of entries that we care + * about have type information stored in a series of attributes. Each DIE also + * has a tag that identifies the kind of attributes that it has. + * + * A given DIE may itself have children. For example, a DIE that represents a + * structure has children which represent members. Whenever we encounter a DIE + * that has children or other values or types associated with it, we recursively + * process those children first so that way we can then refer to the generated + * CTF type id while processing its parent. This reduces the amount of unknowns + * and fixups that we need. It also ensures that we don't accidentally add types + * that an overzealous compiler might add to the DWARF data but aren't used by + * anything in the system. + * + * Once we do a conversion, we store a mapping in an AVL tree that goes from the + * DWARF's die offset, which is relative to the given compilation unit, to a + * ctf_id_t. + * + * Unfortunately, some compilers actually will emit duplicate entries for a + * given type that look similar, but aren't quite. To that end, we go through + * and do a variant on a merge once we're done processing a single compilation + * unit which deduplicates all of the types that are in the unit. + * + * Finally, if we encounter an object that has multiple compilation units, then + * we'll convert all of the compilation units separately and then do a merge, so + * that way we can result in one single ctf_file_t that represents everything + * for the object. + * + * Conversion Steps + * ---------------- + * + * Because a given object we've been given to convert may have multiple + * compilation units, we break the work into two halves. The first half + * processes each compilation unit (potentially in parallel) and then the second + * half optionally merges all of the dies in the first half. First, we'll cover + * what's involved in converting a single ctf_cu_t's dwarf to CTF. This covers + * the work done in ctf_dwarf_convert_one(). + * + * An individual ctf_cu_t, which represents a compilation unit, is converted to + * CTF in a series of multiple passes. + * + * Pass 1: During the first pass we walk all of the top-level dies and if we + * find a function, variable, struct, union, enum or typedef, we recursively + * transform all of its types. We don't recurse or process everything, because + * we don't want to add some of the types that compilers may add which are + * effectively unused. + * + * During pass 1, if we encounter any structures or unions we mark them for + * fixing up later. This is necessary because we may not be able to determine + * the full size of a structure at the beginning of time. This will happen if + * the DWARF attribute DW_AT_byte_size is not present for a member. Because of + * this possibility we defer adding members to structures or even converting + * them during pass 1 and save that for pass 2. Adding all of the base + * structures without any of their members helps deal with any circular + * dependencies that we might encounter. + * + * Pass 2: This pass is used to do the first half of fixing up structures and + * unions. Rather than walk the entire type space again, we actually walk the + * list of structures and unions that we marked for later fixing up. Here, we + * iterate over every structure and add members to the underlying ctf_file_t, + * but not to the structs themselves. One might wonder why we don't, and the + * main reason is that libctf requires a ctf_update() be done before adding the + * members to structures or unions. + * + * Pass 3: This pass is used to do the second half of fixing up structures and + * unions. During this part we always go through and add members to structures + * and unions that we added to the container in the previous pass. In addition, + * we set the structure and union's actual size, which may have additional + * padding added by the compiler, it isn't simply the last offset. DWARF always + * guarantees an attribute exists for this. Importantly no ctf_id_t's change + * during pass 2. + * + * Pass 4: The next phase is to add CTF entries for all of the symbols and + * variables that are present in this die. During pass 1 we added entries to a + * map for each variable and function. During this pass, we iterate over the + * symbol table and when we encounter a symbol that we have in our lists of + * translated information which matches, we then add it to the ctf_file_t. + * + * Pass 5: Here we go and look for any weak symbols and functions and see if + * they match anything that we recognize. If so, then we add type information + * for them at this point based on the matching type. + * + * Pass 6: This pass is actually a variant on a merge. The traditional merge + * process expects there to be no duplicate types. As such, at the end of + * conversion, we do a dedup on all of the types in the system. The + * deduplication process is described in lib/libctf/common/ctf_merge.c. + * + * Once pass 6 is done, we've finished processing the individual compilation + * unit. + * + * The following steps reflect the general process of doing a conversion. + * + * 1) Walk the dwarf section and determine the number of compilation units + * 2) Create a ctf_cu_t for each compilation unit + * 3) Add all ctf_cu_t's to a workq + * 4) Have the workq process each die with ctf_dwarf_convert_one. This itself + * is comprised of several steps, which were already enumerated. + * 5) If we have multiple cu's, we do a ctf merge of all the dies. The mechanics + * of the merge are discussed in lib/libctf/common/ctf_merge.c. + * 6) Free everything up and return a ctf_file_t to the user. If we only had a + * single compilation unit, then we give that to the user. Otherwise, we + * return the merged ctf_file_t. + * + * Threading + * --------- + * + * The process has been designed to be amenable to threading. Each compilation + * unit has its own type stream, therefore the logical place to divide and + * conquer is at the compilation unit. Each ctf_cu_t has been built to be able + * to be processed independently of the others. It has its own libdwarf handle, + * as a given libdwarf handle may only be used by a single thread at a time. + * This allows the various ctf_cu_t's to be processed in parallel by different + * threads. + * + * All of the ctf_cu_t's are loaded into a workq which allows for a number of + * threads to be specified and used as a thread pool to process all of the + * queued work. We set the number of threads to use in the workq equal to the + * number of threads that the user has specified. + * + * After all of the compilation units have been drained, we use the same number + * of threads when performing a merge of multiple compilation units, if they + * exist. + * + * While all of these different parts do support and allow for multiple threads, + * it's important that when only a single thread is specified, that it be the + * calling thread. This allows the conversion routines to be used in a context + * that doesn't allow additional threads, such as rtld. + * + * Common DWARF Mechanics and Notes + * -------------------------------- + * + * At this time, we really only support DWARFv2, though support for DWARFv4 is + * mostly there. There is no intent to support DWARFv3. + * + * Generally types for something are stored in the DW_AT_type attribute. For + * example, a function's return type will be stored in the local DW_AT_type + * attribute while the arguments will be in child DIEs. There are also various + * times when we don't have any DW_AT_type. In that case, the lack of a type + * implies, at least for C, that its C type is void. Because DWARF doesn't emit + * one, we have a synthetic void type that we create and manipulate instead and + * pass it off to consumers on an as-needed basis. If nothing has a void type, + * it will not be emitted. + * + * Architecture Specific Parts + * --------------------------- + * + * The CTF tooling encodes various information about the various architectures + * in the system. Importantly, the tool assumes that every architecture has a + * data model where long and pointer are the same size. This is currently the + * case, as the two data models illumos supports are ILP32 and LP64. + * + * In addition, we encode the mapping of various floating point sizes to various + * types for each architecture. If a new architecture is being added, it should + * be added to the list. The general design of the ctf conversion tools is to be + * architecture independent. eg. any of the tools here should be able to convert + * any architecture's DWARF into ctf; however, this has not been rigorously + * tested and more importantly, the ctf routines don't currently write out the + * data in an endian-aware form, they only use that of the currently running + * library. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DWARF_VERSION_TWO 2 +#define DWARF_VARARGS_NAME "..." + +/* + * Dwarf may refer recursively to other types that we've already processed. To + * see if we've already converted them, we look them up in an AVL tree that's + * sorted by the DWARF id. + */ +typedef struct ctf_dwmap { + avl_node_t cdm_avl; + Dwarf_Off cdm_off; + Dwarf_Die cdm_die; + ctf_id_t cdm_id; + boolean_t cdm_fix; +} ctf_dwmap_t; + +typedef struct ctf_dwvar { + ctf_list_t cdv_list; + char *cdv_name; + ctf_id_t cdv_type; + boolean_t cdv_global; +} ctf_dwvar_t; + +typedef struct ctf_dwfunc { + ctf_list_t cdf_list; + char *cdf_name; + ctf_funcinfo_t cdf_fip; + ctf_id_t *cdf_argv; + boolean_t cdf_global; +} ctf_dwfunc_t; + +typedef struct ctf_dwbitf { + ctf_list_t cdb_list; + ctf_id_t cdb_base; + uint_t cdb_nbits; + ctf_id_t cdb_id; +} ctf_dwbitf_t; + +/* + * The ctf_cu_t represents a single top-level DWARF die unit. While generally, + * the typical object file has only a single die, if we're asked to convert + * something that's been linked from multiple sources, multiple dies will exist. + */ +typedef struct ctf_die { + Elf *cu_elf; /* shared libelf handle */ + char *cu_name; /* basename of the DIE */ + ctf_merge_t *cu_cmh; /* merge handle */ + ctf_list_t cu_vars; /* List of variables */ + ctf_list_t cu_funcs; /* List of functions */ + ctf_list_t cu_bitfields; /* Bit field members */ + Dwarf_Debug cu_dwarf; /* libdwarf handle */ + Dwarf_Die cu_cu; /* libdwarf compilation unit */ + Dwarf_Off cu_cuoff; /* cu's offset */ + Dwarf_Off cu_maxoff; /* maximum offset */ + ctf_file_t *cu_ctfp; /* output CTF file */ + avl_tree_t cu_map; /* map die offsets to CTF types */ + char *cu_errbuf; /* error message buffer */ + size_t cu_errlen; /* error message buffer length */ + size_t cu_ptrsz; /* object's pointer size */ + boolean_t cu_bigend; /* is it big endian */ + boolean_t cu_doweaks; /* should we convert weak symbols? */ + uint_t cu_mach; /* machine type */ + ctf_id_t cu_voidtid; /* void pointer */ + ctf_id_t cu_longtid; /* id for a 'long' */ +} ctf_cu_t; + +static int ctf_dwarf_offset(ctf_cu_t *, Dwarf_Die, Dwarf_Off *); +static int ctf_dwarf_convert_die(ctf_cu_t *, Dwarf_Die); +static int ctf_dwarf_convert_type(ctf_cu_t *, Dwarf_Die, ctf_id_t *, int); + +static int ctf_dwarf_function_count(ctf_cu_t *, Dwarf_Die, ctf_funcinfo_t *, + boolean_t); +static int ctf_dwarf_convert_fargs(ctf_cu_t *, Dwarf_Die, ctf_funcinfo_t *, + ctf_id_t *); + +typedef int (ctf_dwarf_symtab_f)(ctf_cu_t *, const GElf_Sym *, ulong_t, + const char *, const char *, void *); + +/* + * This is a generic way to set a CTF Conversion backend error depending on what + * we were doing. Unless it was one of a specific set of errors that don't + * indicate a programming / translation bug, eg. ENOMEM, then we transform it + * into a CTF backend error and fill in the error buffer. + */ +static int +ctf_dwarf_error(ctf_cu_t *cup, ctf_file_t *cfp, int err, const char *fmt, ...) +{ + va_list ap; + int ret; + size_t off = 0; + ssize_t rem = cup->cu_errlen; + if (cfp != NULL) + err = ctf_errno(cfp); + + if (err == ENOMEM) + return (err); + + ret = snprintf(cup->cu_errbuf, rem, "die %s: ", cup->cu_name); + if (ret < 0) + goto err; + off += ret; + rem = MAX(rem - ret, 0); + + va_start(ap, fmt); + ret = vsnprintf(cup->cu_errbuf + off, rem, fmt, ap); + va_end(ap); + if (ret < 0) + goto err; + + off += ret; + rem = MAX(rem - ret, 0); + if (fmt[strlen(fmt) - 1] != '\n') { + (void) snprintf(cup->cu_errbuf + off, rem, + ": %s\n", ctf_errmsg(err)); + } + va_end(ap); + return (ECTF_CONVBKERR); + +err: + cup->cu_errbuf[0] = '\0'; + return (ECTF_CONVBKERR); +} + +/* + * DWARF often opts to put no explicit type to describe a void type. eg. if we + * have a reference type whose DW_AT_type member doesn't exist, then we should + * instead assume it points to void. Because this isn't represented, we + * instead cause it to come into existence. + */ +static ctf_id_t +ctf_dwarf_void(ctf_cu_t *cup) +{ + if (cup->cu_voidtid == CTF_ERR) { + ctf_encoding_t enc = { CTF_INT_SIGNED, 0, 0 }; + cup->cu_voidtid = ctf_add_integer(cup->cu_ctfp, CTF_ADD_ROOT, + "void", &enc); + if (cup->cu_voidtid == CTF_ERR) { + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to create void type: %s\n", + ctf_errmsg(ctf_errno(cup->cu_ctfp))); + } + } + + return (cup->cu_voidtid); +} + +/* + * There are many different forms that an array index may take. However, we just + * always force it to be of a type long no matter what. Therefore we use this to + * have a single instance of long across everything. + */ +static ctf_id_t +ctf_dwarf_long(ctf_cu_t *cup) +{ + if (cup->cu_longtid == CTF_ERR) { + ctf_encoding_t enc; + + enc.cte_format = CTF_INT_SIGNED; + enc.cte_offset = 0; + /* All illumos systems are LP */ + enc.cte_bits = cup->cu_ptrsz * 8; + cup->cu_longtid = ctf_add_integer(cup->cu_ctfp, CTF_ADD_NONROOT, + "long", &enc); + if (cup->cu_longtid == CTF_ERR) { + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to create long type: %s\n", + ctf_errmsg(ctf_errno(cup->cu_ctfp))); + } + + } + + return (cup->cu_longtid); +} + +static int +ctf_dwmap_comp(const void *a, const void *b) +{ + const ctf_dwmap_t *ca = a; + const ctf_dwmap_t *cb = b; + + if (ca->cdm_off > cb->cdm_off) + return (1); + if (ca->cdm_off < cb->cdm_off) + return (-1); + return (0); +} + +static int +ctf_dwmap_add(ctf_cu_t *cup, ctf_id_t id, Dwarf_Die die, boolean_t fix) +{ + int ret; + avl_index_t index; + ctf_dwmap_t *dwmap; + Dwarf_Off off; + + VERIFY(id > 0 && id < CTF_MAX_TYPE); + + if ((ret = ctf_dwarf_offset(cup, die, &off)) != 0) + return (ret); + + if ((dwmap = ctf_alloc(sizeof (ctf_dwmap_t))) == NULL) + return (ENOMEM); + + dwmap->cdm_die = die; + dwmap->cdm_off = off; + dwmap->cdm_id = id; + dwmap->cdm_fix = fix; + + ctf_dprintf("dwmap: %p %" DW_PR_DUx "->%d\n", dwmap, off, id); + VERIFY(avl_find(&cup->cu_map, dwmap, &index) == NULL); + avl_insert(&cup->cu_map, dwmap, index); + return (0); +} + +static int +ctf_dwarf_attribute(ctf_cu_t *cup, Dwarf_Die die, Dwarf_Half name, + Dwarf_Attribute *attrp) +{ + int ret; + Dwarf_Error derr; + + if ((ret = dwarf_attr(die, name, attrp, &derr)) == DW_DLV_OK) + return (0); + if (ret == DW_DLV_NO_ENTRY) { + *attrp = NULL; + return (ENOENT); + } + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to get attribute for type: %s\n", + dwarf_errmsg(derr)); + return (ECTF_CONVBKERR); +} + +static int +ctf_dwarf_ref(ctf_cu_t *cup, Dwarf_Die die, Dwarf_Half name, Dwarf_Off *refp) +{ + int ret; + Dwarf_Attribute attr; + Dwarf_Error derr; + + if ((ret = ctf_dwarf_attribute(cup, die, name, &attr)) != 0) + return (ret); + + if (dwarf_formref(attr, refp, &derr) == DW_DLV_OK) { + dwarf_dealloc(cup->cu_dwarf, attr, DW_DLA_ATTR); + return (0); + } + + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to get unsigned attribute for type: %s\n", + dwarf_errmsg(derr)); + return (ECTF_CONVBKERR); +} + +static int +ctf_dwarf_refdie(ctf_cu_t *cup, Dwarf_Die die, Dwarf_Half name, + Dwarf_Die *diep) +{ + int ret; + Dwarf_Off off; + Dwarf_Error derr; + + if ((ret = ctf_dwarf_ref(cup, die, name, &off)) != 0) + return (ret); + + off += cup->cu_cuoff; + if ((ret = dwarf_offdie(cup->cu_dwarf, off, diep, &derr)) != + DW_DLV_OK) { + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to get die from offset %" DW_PR_DUu ": %s\n", + off, dwarf_errmsg(derr)); + return (ECTF_CONVBKERR); + } + + return (0); +} + +static int +ctf_dwarf_signed(ctf_cu_t *cup, Dwarf_Die die, Dwarf_Half name, + Dwarf_Signed *valp) +{ + int ret; + Dwarf_Attribute attr; + Dwarf_Error derr; + + if ((ret = ctf_dwarf_attribute(cup, die, name, &attr)) != 0) + return (ret); + + if (dwarf_formsdata(attr, valp, &derr) == DW_DLV_OK) { + dwarf_dealloc(cup->cu_dwarf, attr, DW_DLA_ATTR); + return (0); + } + + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to get unsigned attribute for type: %s\n", + dwarf_errmsg(derr)); + return (ECTF_CONVBKERR); +} + +static int +ctf_dwarf_unsigned(ctf_cu_t *cup, Dwarf_Die die, Dwarf_Half name, + Dwarf_Unsigned *valp) +{ + int ret; + Dwarf_Attribute attr; + Dwarf_Error derr; + + if ((ret = ctf_dwarf_attribute(cup, die, name, &attr)) != 0) + return (ret); + + if (dwarf_formudata(attr, valp, &derr) == DW_DLV_OK) { + dwarf_dealloc(cup->cu_dwarf, attr, DW_DLA_ATTR); + return (0); + } + + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to get unsigned attribute for type: %s\n", + dwarf_errmsg(derr)); + return (ECTF_CONVBKERR); +} + +static int +ctf_dwarf_boolean(ctf_cu_t *cup, Dwarf_Die die, Dwarf_Half name, + Dwarf_Bool *val) +{ + int ret; + Dwarf_Attribute attr; + Dwarf_Error derr; + + if ((ret = ctf_dwarf_attribute(cup, die, name, &attr)) != 0) + return (ret); + + if (dwarf_formflag(attr, val, &derr) == DW_DLV_OK) { + dwarf_dealloc(cup->cu_dwarf, attr, DW_DLA_ATTR); + return (0); + } + + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to get boolean attribute for type: %s\n", + dwarf_errmsg(derr)); + + return (ECTF_CONVBKERR); +} + +static int +ctf_dwarf_string(ctf_cu_t *cup, Dwarf_Die die, Dwarf_Half name, char **strp) +{ + int ret; + char *s; + Dwarf_Attribute attr; + Dwarf_Error derr; + + *strp = NULL; + if ((ret = ctf_dwarf_attribute(cup, die, name, &attr)) != 0) + return (ret); + + if (dwarf_formstring(attr, &s, &derr) == DW_DLV_OK) { + if ((*strp = ctf_strdup(s)) == NULL) + ret = ENOMEM; + else + ret = 0; + dwarf_dealloc(cup->cu_dwarf, attr, DW_DLA_ATTR); + return (ret); + } + + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to get string attribute for type: %s\n", + dwarf_errmsg(derr)); + return (ECTF_CONVBKERR); +} + +static int +ctf_dwarf_member_location(ctf_cu_t *cup, Dwarf_Die die, Dwarf_Unsigned *valp) +{ + int ret; + Dwarf_Error derr; + Dwarf_Attribute attr; + Dwarf_Locdesc *loc; + Dwarf_Signed locnum; + + if ((ret = ctf_dwarf_attribute(cup, die, DW_AT_data_member_location, + &attr)) != 0) + return (ret); + + if (dwarf_loclist(attr, &loc, &locnum, &derr) != DW_DLV_OK) { + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to obtain location list for member offset: %s", + dwarf_errmsg(derr)); + dwarf_dealloc(cup->cu_dwarf, attr, DW_DLA_ATTR); + return (ECTF_CONVBKERR); + } + dwarf_dealloc(cup->cu_dwarf, attr, DW_DLA_ATTR); + + if (locnum != 1 || loc->ld_s->lr_atom != DW_OP_plus_uconst) { + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to parse location structure for member"); + dwarf_dealloc(cup->cu_dwarf, loc->ld_s, DW_DLA_LOC_BLOCK); + dwarf_dealloc(cup->cu_dwarf, loc, DW_DLA_LOCDESC); + return (ECTF_CONVBKERR); + } + + *valp = loc->ld_s->lr_number; + + dwarf_dealloc(cup->cu_dwarf, loc->ld_s, DW_DLA_LOC_BLOCK); + dwarf_dealloc(cup->cu_dwarf, loc, DW_DLA_LOCDESC); + return (0); +} + + +static int +ctf_dwarf_offset(ctf_cu_t *cup, Dwarf_Die die, Dwarf_Off *offsetp) +{ + Dwarf_Error derr; + + if (dwarf_dieoffset(die, offsetp, &derr) == DW_DLV_OK) + return (0); + + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to get die offset: %s\n", + dwarf_errmsg(derr)); + return (ECTF_CONVBKERR); +} + +/* simpler variant for debugging output */ +static Dwarf_Off +ctf_die_offset(Dwarf_Die die) +{ + Dwarf_Off off = -1; + Dwarf_Error derr; + + (void) dwarf_dieoffset(die, &off, &derr); + return (off); +} + +static int +ctf_dwarf_tag(ctf_cu_t *cup, Dwarf_Die die, Dwarf_Half *tagp) +{ + Dwarf_Error derr; + + if (dwarf_tag(die, tagp, &derr) == DW_DLV_OK) + return (0); + + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to get tag type: %s\n", + dwarf_errmsg(derr)); + return (ECTF_CONVBKERR); +} + +static int +ctf_dwarf_sib(ctf_cu_t *cup, Dwarf_Die base, Dwarf_Die *sibp) +{ + Dwarf_Error derr; + int ret; + + *sibp = NULL; + ret = dwarf_siblingof(cup->cu_dwarf, base, sibp, &derr); + if (ret == DW_DLV_OK || ret == DW_DLV_NO_ENTRY) + return (0); + + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to sibling from die: %s\n", + dwarf_errmsg(derr)); + return (ECTF_CONVBKERR); +} + +static int +ctf_dwarf_child(ctf_cu_t *cup, Dwarf_Die base, Dwarf_Die *childp) +{ + Dwarf_Error derr; + int ret; + + *childp = NULL; + ret = dwarf_child(base, childp, &derr); + if (ret == DW_DLV_OK || ret == DW_DLV_NO_ENTRY) + return (0); + + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to child from die: %s\n", + dwarf_errmsg(derr)); + return (ECTF_CONVBKERR); +} + +/* + * Compilers disagree on what to do to determine if something has global + * visiblity. Traditionally gcc has used DW_AT_external to indicate this while + * Studio has used DW_AT_visibility. We check DW_AT_visibility first and then + * fall back to DW_AT_external. Lack of DW_AT_external implies that it is not. + */ +static int +ctf_dwarf_isglobal(ctf_cu_t *cup, Dwarf_Die die, boolean_t *igp) +{ + int ret; + Dwarf_Signed vis; + Dwarf_Bool ext; + + if ((ret = ctf_dwarf_signed(cup, die, DW_AT_visibility, &vis)) == 0) { + *igp = vis == DW_VIS_exported; + return (0); + } else if (ret != ENOENT) { + return (ret); + } + + if ((ret = ctf_dwarf_boolean(cup, die, DW_AT_external, &ext)) != 0) { + if (ret == ENOENT) { + *igp = B_FALSE; + return (0); + } + return (ret); + } + *igp = ext != 0 ? B_TRUE : B_FALSE; + return (0); +} + +static int +ctf_dwarf_die_elfenc(Elf *elf, ctf_cu_t *cup, char *errbuf, size_t errlen) +{ + GElf_Ehdr ehdr; + + if (gelf_getehdr(elf, &ehdr) == NULL) { + (void) snprintf(errbuf, errlen, + "failed to get ELF header: %s\n", + elf_errmsg(elf_errno())); + return (ECTF_CONVBKERR); + } + + cup->cu_mach = ehdr.e_machine; + + if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) { + cup->cu_ptrsz = 4; + VERIFY(ctf_setmodel(cup->cu_ctfp, CTF_MODEL_ILP32) == 0); + } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { + cup->cu_ptrsz = 8; + VERIFY(ctf_setmodel(cup->cu_ctfp, CTF_MODEL_LP64) == 0); + } else { + (void) snprintf(errbuf, errlen, + "unknown ELF class %d", ehdr.e_ident[EI_CLASS]); + return (ECTF_CONVBKERR); + } + + if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) { + cup->cu_bigend = B_FALSE; + } else if (ehdr.e_ident[EI_DATA] == ELFDATA2MSB) { + cup->cu_bigend = B_TRUE; + } else { + (void) snprintf(errbuf, errlen, + "unknown ELF data encoding: %hhu", ehdr.e_ident[EI_DATA]); + return (ECTF_CONVBKERR); + } + + return (0); +} + +typedef struct ctf_dwarf_fpent { + size_t cdfe_size; + uint_t cdfe_enc[3]; +} ctf_dwarf_fpent_t; + +typedef struct ctf_dwarf_fpmap { + uint_t cdf_mach; + ctf_dwarf_fpent_t cdf_ents[4]; +} ctf_dwarf_fpmap_t; + +static const ctf_dwarf_fpmap_t ctf_dwarf_fpmaps[] = { + { EM_SPARC, { + { 4, { CTF_FP_SINGLE, CTF_FP_CPLX, CTF_FP_IMAGRY } }, + { 8, { CTF_FP_DOUBLE, CTF_FP_DCPLX, CTF_FP_DIMAGRY } }, + { 16, { CTF_FP_LDOUBLE, CTF_FP_LDCPLX, CTF_FP_LDIMAGRY } }, + { 0, { 0 } } + } }, + { EM_SPARC32PLUS, { + { 4, { CTF_FP_SINGLE, CTF_FP_CPLX, CTF_FP_IMAGRY } }, + { 8, { CTF_FP_DOUBLE, CTF_FP_DCPLX, CTF_FP_DIMAGRY } }, + { 16, { CTF_FP_LDOUBLE, CTF_FP_LDCPLX, CTF_FP_LDIMAGRY } }, + { 0, { 0 } } + } }, + { EM_SPARCV9, { + { 4, { CTF_FP_SINGLE, CTF_FP_CPLX, CTF_FP_IMAGRY } }, + { 8, { CTF_FP_DOUBLE, CTF_FP_DCPLX, CTF_FP_DIMAGRY } }, + { 16, { CTF_FP_LDOUBLE, CTF_FP_LDCPLX, CTF_FP_LDIMAGRY } }, + { 0, { 0 } } + } }, + { EM_386, { + { 4, { CTF_FP_SINGLE, CTF_FP_CPLX, CTF_FP_IMAGRY } }, + { 8, { CTF_FP_DOUBLE, CTF_FP_DCPLX, CTF_FP_DIMAGRY } }, + { 12, { CTF_FP_LDOUBLE, CTF_FP_LDCPLX, CTF_FP_LDIMAGRY } }, + { 0, { 0 } } + } }, + { EM_X86_64, { + { 4, { CTF_FP_SINGLE, CTF_FP_CPLX, CTF_FP_IMAGRY } }, + { 8, { CTF_FP_DOUBLE, CTF_FP_DCPLX, CTF_FP_DIMAGRY } }, + { 16, { CTF_FP_LDOUBLE, CTF_FP_LDCPLX, CTF_FP_LDIMAGRY } }, + { 0, { 0 } } + } }, + { EM_NONE } +}; + +static int +ctf_dwarf_float_base(ctf_cu_t *cup, Dwarf_Signed type, ctf_encoding_t *enc) +{ + const ctf_dwarf_fpmap_t *map = &ctf_dwarf_fpmaps[0]; + const ctf_dwarf_fpent_t *ent; + uint_t col = 0, mult = 1; + + for (map = &ctf_dwarf_fpmaps[0]; map->cdf_mach != EM_NONE; map++) { + if (map->cdf_mach == cup->cu_mach) + break; + } + + if (map->cdf_mach == EM_NONE) { + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "Unsupported machine type: %d\n", cup->cu_mach); + return (ENOTSUP); + } + + if (type == DW_ATE_complex_float) { + mult = 2; + col = 1; + } else if (type == DW_ATE_imaginary_float || + type == DW_ATE_SUN_imaginary_float) { + col = 2; + } + + ent = &map->cdf_ents[0]; + for (ent = &map->cdf_ents[0]; ent->cdfe_size != 0; ent++) { + if (ent->cdfe_size * mult * 8 == enc->cte_bits) { + enc->cte_format = ent->cdfe_enc[col]; + return (0); + } + } + + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to find valid fp mapping for encoding %d, size %d bits\n", + type, enc->cte_bits); + return (EINVAL); +} + +static int +ctf_dwarf_dwarf_base(ctf_cu_t *cup, Dwarf_Die die, int *kindp, + ctf_encoding_t *enc) +{ + int ret; + Dwarf_Signed type; + + if ((ret = ctf_dwarf_signed(cup, die, DW_AT_encoding, &type)) != 0) + return (ret); + + switch (type) { + case DW_ATE_unsigned: + case DW_ATE_address: + *kindp = CTF_K_INTEGER; + enc->cte_format = 0; + break; + case DW_ATE_unsigned_char: + *kindp = CTF_K_INTEGER; + enc->cte_format = CTF_INT_CHAR; + break; + case DW_ATE_signed: + *kindp = CTF_K_INTEGER; + enc->cte_format = CTF_INT_SIGNED; + break; + case DW_ATE_signed_char: + *kindp = CTF_K_INTEGER; + enc->cte_format = CTF_INT_SIGNED | CTF_INT_CHAR; + break; + case DW_ATE_boolean: + *kindp = CTF_K_INTEGER; + enc->cte_format = CTF_INT_SIGNED | CTF_INT_BOOL; + break; + case DW_ATE_float: + case DW_ATE_complex_float: + case DW_ATE_imaginary_float: + case DW_ATE_SUN_imaginary_float: + case DW_ATE_SUN_interval_float: + *kindp = CTF_K_FLOAT; + if ((ret = ctf_dwarf_float_base(cup, type, enc)) != 0) + return (ret); + break; + default: + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "encountered unkown DWARF encoding: %d", type); + return (ECTF_CONVBKERR); + } + + return (0); +} + +/* + * Different compilers (at least GCC and Studio) use different names for types. + * This parses the types and attempts to unify them. If this fails, we just fall + * back to using the DWARF itself. + */ +static int +ctf_dwarf_parse_base(const char *name, int *kindp, ctf_encoding_t *enc, + char **newnamep) +{ + char buf[256]; + char *base, *c, *last; + int nlong = 0, nshort = 0, nchar = 0, nint = 0; + int sign = 1; + + if (strlen(name) + 1 > sizeof (buf)) + return (EINVAL); + + (void) strlcpy(buf, name, sizeof (buf)); + for (c = strtok_r(buf, " ", &last); c != NULL; + c = strtok_r(NULL, " ", &last)) { + if (strcmp(c, "signed") == 0) { + sign = 1; + } else if (strcmp(c, "unsigned") == 0) { + sign = 0; + } else if (strcmp(c, "long") == 0) { + nlong++; + } else if (strcmp(c, "char") == 0) { + nchar++; + } else if (strcmp(c, "short") == 0) { + nshort++; + } else if (strcmp(c, "int") == 0) { + nint++; + } else { + /* + * If we don't recognize any of the tokens, we'll tell + * the caller to fall back to the dwarf-provided + * encoding information. + */ + return (EINVAL); + } + } + + if (nchar > 1 || nshort > 1 || nint > 1 || nlong > 2) + return (EINVAL); + + if (nchar > 0) { + if (nlong > 0 || nshort > 0 || nint > 0) + return (EINVAL); + base = "char"; + } else if (nshort > 0) { + if (nlong > 0) + return (EINVAL); + base = "short"; + } else if (nlong > 0) { + base = "long"; + } else { + base = "int"; + } + + if (nchar > 0) + enc->cte_format = CTF_INT_CHAR; + else + enc->cte_format = 0; + + if (sign > 0) + enc->cte_format |= CTF_INT_SIGNED; + + (void) snprintf(buf, sizeof (buf), "%s%s%s", + (sign ? "" : "unsigned "), + (nlong > 1 ? "long " : ""), + base); + + *newnamep = ctf_strdup(buf); + if (*newnamep == NULL) + return (ENOMEM); + *kindp = CTF_K_INTEGER; + return (0); +} + +static int +ctf_dwarf_create_base(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp, int isroot, + Dwarf_Off off) +{ + int ret; + char *name, *nname; + Dwarf_Unsigned sz; + int kind; + ctf_encoding_t enc; + ctf_id_t id; + + if ((ret = ctf_dwarf_string(cup, die, DW_AT_name, &name)) != 0) + return (ret); + if ((ret = ctf_dwarf_unsigned(cup, die, DW_AT_byte_size, &sz)) != 0) { + goto out; + } + ctf_dprintf("Creating base type %s from off %llu, size: %d\n", name, + off, sz); + + bzero(&enc, sizeof (ctf_encoding_t)); + enc.cte_bits = sz * 8; + if ((ret = ctf_dwarf_parse_base(name, &kind, &enc, &nname)) == 0) { + ctf_free(name, strlen(name) + 1); + name = nname; + } else { + if (ret != EINVAL) + return (ret); + ctf_dprintf("falling back to dwarf for base type %s\n", name); + if ((ret = ctf_dwarf_dwarf_base(cup, die, &kind, &enc)) != 0) + return (ret); + } + + id = ctf_add_encoded(cup->cu_ctfp, isroot, name, &enc, kind); + if (id == CTF_ERR) { + ret = ctf_errno(cup->cu_ctfp); + } else { + *idp = id; + ret = ctf_dwmap_add(cup, id, die, B_FALSE); + } +out: + ctf_free(name, strlen(name) + 1); + return (ret); +} + +/* + * Getting a member's offset is a surprisingly intricate dance. It works as + * follows: + * + * 1) If we're in DWARFv4, then we either have a DW_AT_data_bit_offset or we + * have a DW_AT_data_member_location. We won't have both. Thus we check first + * for DW_AT_data_bit_offset, and if it exists, we're set. + * + * Next, if we have a bitfield and we don't have a DW_AT_data_bit_offset, then + * we have to grab the data location and use the following dance: + * + * 2) Gather the set of DW_AT_byte_size, DW_AT_bit_offset, and DW_AT_bit_size. + * Of course, the DW_AT_byte_size may be omitted, even though it isn't always. + * When it's been omitted, we then have to say that the size is that of the + * underlying type, which forces that to be after a ctf_update(). Here, we have + * to do different things based on whether or not we're using big endian or + * little endian to obtain the proper offset. + */ +static int +ctf_dwarf_member_offset(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t mid, + ulong_t *offp) +{ + int ret; + Dwarf_Unsigned loc, bitsz, bytesz; + Dwarf_Signed bitoff; + size_t off; + ssize_t tsz; + + if ((ret = ctf_dwarf_unsigned(cup, die, DW_AT_data_bit_offset, + &loc)) == 0) { + *offp = loc; + return (0); + } else if (ret != ENOENT) { + return (ret); + } + + if ((ret = ctf_dwarf_member_location(cup, die, &loc)) != 0) + return (ret); + off = loc * 8; + + if ((ret = ctf_dwarf_signed(cup, die, DW_AT_bit_offset, + &bitoff)) != 0) { + if (ret != ENOENT) + return (ret); + *offp = off; + return (0); + } + + /* At this point we have to have DW_AT_bit_size */ + if ((ret = ctf_dwarf_unsigned(cup, die, DW_AT_bit_size, &bitsz)) != 0) + return (ret); + + if ((ret = ctf_dwarf_unsigned(cup, die, DW_AT_byte_size, + &bytesz)) != 0) { + if (ret != ENOENT) + return (ret); + if ((tsz = ctf_type_size(cup->cu_ctfp, mid)) == CTF_ERR) { + int e = ctf_errno(cup->cu_ctfp); + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to get type size: %s", ctf_errmsg(e)); + return (ECTF_CONVBKERR); + } + } else { + tsz = bytesz; + } + tsz *= 8; + if (cup->cu_bigend == B_TRUE) { + *offp = off + bitoff; + } else { + *offp = off + tsz - bitoff - bitsz; + } + + return (0); +} + +/* + * We need to determine if the member in question is a bitfield. If it is, then + * we need to go through and create a new type that's based on the actual base + * type, but has a different size. We also rename the type as a result to help + * deal with future collisions. + * + * Here we need to look and see if we have a DW_AT_bit_size value. If we have a + * bit size member and it does not equal the byte size member, then we need to + * create a bitfield type based on this. + * + * Note: When we support DWARFv4, there may be a chance that we need to also + * search for the DW_AT_byte_size if we don't have a DW_AT_bit_size member. + */ +static int +ctf_dwarf_member_bitfield(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp) +{ + int ret; + Dwarf_Unsigned bitsz; + ctf_encoding_t e; + ctf_dwbitf_t *cdb; + ctf_dtdef_t *dtd; + ctf_id_t base = *idp; + int kind; + + if ((ret = ctf_dwarf_unsigned(cup, die, DW_AT_bit_size, &bitsz)) != 0) { + if (ret == ENOENT) + return (0); + return (ret); + } + + ctf_dprintf("Trying to deal with bitfields on %d:%d\n", base, bitsz); + /* + * Given that we now have a bitsize, time to go do something about it. + * We're going to create a new type based on the current one, but first + * we need to find the base type. This means we need to traverse any + * typedef's, consts, and volatiles until we get to what should be + * something of type integer or enumeration. + */ + VERIFY(bitsz < UINT32_MAX); + dtd = ctf_dtd_lookup(cup->cu_ctfp, base); + VERIFY(dtd != NULL); + kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info); + while (kind == CTF_K_TYPEDEF || kind == CTF_K_CONST || + kind == CTF_K_VOLATILE) { + dtd = ctf_dtd_lookup(cup->cu_ctfp, dtd->dtd_data.ctt_type); + VERIFY(dtd != NULL); + kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info); + } + ctf_dprintf("got kind %d\n", kind); + VERIFY(kind == CTF_K_INTEGER || kind == CTF_K_ENUM); + + /* + * As surprising as it may be, it is strictly possible to create a + * bitfield that is based on an enum. Of course, the C standard leaves + * enums sizing as an ABI concern more or less. To that effect, today on + * all illumos platforms the size of an enum is generally that of an + * int as our supported data models and ABIs all agree on that. So what + * we'll do is fake up a CTF encoding here to use. In this case, we'll + * treat it as an unsigned value of whatever size the underlying enum + * currently has (which is in the ctt_size member of its dynamic type + * data). + */ + if (kind == CTF_K_INTEGER) { + e = dtd->dtd_u.dtu_enc; + } else { + bzero(&e, sizeof (ctf_encoding_t)); + e.cte_bits = dtd->dtd_data.ctt_size * NBBY; + } + + for (cdb = ctf_list_next(&cup->cu_bitfields); cdb != NULL; + cdb = ctf_list_next(cdb)) { + if (cdb->cdb_base == base && cdb->cdb_nbits == bitsz) + break; + } + + /* + * Create a new type if none exists. We name all types in a way that is + * guaranteed not to conflict with the corresponding C type. We do this + * by using the ':' operator. + */ + if (cdb == NULL) { + size_t namesz; + char *name; + + e.cte_bits = bitsz; + namesz = snprintf(NULL, 0, "%s:%d", dtd->dtd_name, + (uint32_t)bitsz); + name = ctf_alloc(namesz + 1); + if (name == NULL) + return (ENOMEM); + cdb = ctf_alloc(sizeof (ctf_dwbitf_t)); + if (cdb == NULL) { + ctf_free(name, namesz + 1); + return (ENOMEM); + } + (void) snprintf(name, namesz + 1, "%s:%d", dtd->dtd_name, + (uint32_t)bitsz); + + cdb->cdb_base = base; + cdb->cdb_nbits = bitsz; + cdb->cdb_id = ctf_add_integer(cup->cu_ctfp, CTF_ADD_NONROOT, + name, &e); + if (cdb->cdb_id == CTF_ERR) { + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to get add bitfield type %s: %s", name, + ctf_errmsg(ctf_errno(cup->cu_ctfp))); + ctf_free(name, namesz + 1); + ctf_free(cdb, sizeof (ctf_dwbitf_t)); + return (ECTF_CONVBKERR); + } + ctf_free(name, namesz + 1); + ctf_list_append(&cup->cu_bitfields, cdb); + } + + *idp = cdb->cdb_id; + + return (0); +} + +static int +ctf_dwarf_fixup_sou(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t base, boolean_t add) +{ + int ret, kind; + Dwarf_Die child, memb; + Dwarf_Unsigned size; + ulong_t nsz; + + kind = ctf_type_kind(cup->cu_ctfp, base); + VERIFY(kind != CTF_ERR); + VERIFY(kind == CTF_K_STRUCT || kind == CTF_K_UNION); + + /* + * Members are in children. However, gcc also allows empty ones. + */ + if ((ret = ctf_dwarf_child(cup, die, &child)) != 0) + return (ret); + if (child == NULL) + return (0); + + memb = child; + while (memb != NULL) { + Dwarf_Die sib, tdie; + Dwarf_Half tag; + ctf_id_t mid; + char *mname; + ulong_t memboff = 0; + + if ((ret = ctf_dwarf_tag(cup, memb, &tag)) != 0) + return (ret); + + if (tag != DW_TAG_member) + continue; + + if ((ret = ctf_dwarf_refdie(cup, memb, DW_AT_type, &tdie)) != 0) + return (ret); + + if ((ret = ctf_dwarf_convert_type(cup, tdie, &mid, + CTF_ADD_NONROOT)) != 0) + return (ret); + ctf_dprintf("Got back type id: %d\n", mid); + + /* + * If we're not adding a member, just go ahead and return. + */ + if (add == B_FALSE) { + if ((ret = ctf_dwarf_member_bitfield(cup, memb, + &mid)) != 0) + return (ret); + goto next; + } + + if ((ret = ctf_dwarf_string(cup, memb, DW_AT_name, + &mname)) != 0 && ret != ENOENT) + return (ret); + if (ret == ENOENT) + mname = NULL; + + if (kind == CTF_K_UNION) { + memboff = 0; + } else if ((ret = ctf_dwarf_member_offset(cup, memb, mid, + &memboff)) != 0) { + if (mname != NULL) + ctf_free(mname, strlen(mname) + 1); + return (ret); + } + + if ((ret = ctf_dwarf_member_bitfield(cup, memb, &mid)) != 0) + return (ret); + + ret = ctf_add_member(cup->cu_ctfp, base, mname, mid, memboff); + if (ret == CTF_ERR) { + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to add member %s: %s", + mname, ctf_errmsg(ctf_errno(cup->cu_ctfp))); + if (mname != NULL) + ctf_free(mname, strlen(mname) + 1); + return (ECTF_CONVBKERR); + } + + if (mname != NULL) + ctf_free(mname, strlen(mname) + 1); + +next: + if ((ret = ctf_dwarf_sib(cup, memb, &sib)) != 0) + return (ret); + memb = sib; + } + + /* + * If we're not adding members, then we don't know the final size of the + * structure, so end here. + */ + if (add == B_FALSE) + return (0); + + /* Finally set the size of the structure to the actual byte size */ + if ((ret = ctf_dwarf_unsigned(cup, die, DW_AT_byte_size, &size)) != 0) + return (ret); + nsz = size; + if ((ctf_set_size(cup->cu_ctfp, base, nsz)) == CTF_ERR) { + int e = ctf_errno(cup->cu_ctfp); + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to set type size for %d to 0x%x: %s", base, + (uint32_t)size, ctf_errmsg(e)); + return (ECTF_CONVBKERR); + } + + return (0); +} + +static int +ctf_dwarf_create_sou(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp, + int kind, int isroot) +{ + int ret; + char *name; + ctf_id_t base; + Dwarf_Die child; + Dwarf_Bool decl; + + /* + * Deal with the terribly annoying case of anonymous structs and unions. + * If they don't have a name, set the name to the empty string. + */ + if ((ret = ctf_dwarf_string(cup, die, DW_AT_name, &name)) != 0 && + ret != ENOENT) + return (ret); + if (ret == ENOENT) + name = NULL; + + /* + * We need to check if we just have a declaration here. If we do, then + * instead of creating an actual structure or union, we're just going to + * go ahead and create a forward. During a dedup or merge, the forward + * will be replaced with the real thing. + */ + if ((ret = ctf_dwarf_boolean(cup, die, DW_AT_declaration, + &decl)) != 0) { + if (ret != ENOENT) + return (ret); + decl = 0; + } + + if (decl != 0) { + base = ctf_add_forward(cup->cu_ctfp, isroot, name, kind); + } else if (kind == CTF_K_STRUCT) { + base = ctf_add_struct(cup->cu_ctfp, isroot, name); + } else { + base = ctf_add_union(cup->cu_ctfp, isroot, name); + } + ctf_dprintf("added sou %s (%d) (%d)\n", name, kind, base); + if (name != NULL) + ctf_free(name, strlen(name) + 1); + if (base == CTF_ERR) + return (ctf_errno(cup->cu_ctfp)); + *idp = base; + + /* + * If it's just a declaration, we're not going to mark it for fix up or + * do anything else. + */ + if (decl == B_TRUE) + return (ctf_dwmap_add(cup, base, die, B_FALSE)); + if ((ret = ctf_dwmap_add(cup, base, die, B_TRUE)) != 0) + return (ret); + + /* + * Members are in children. However, gcc also allows empty ones. + */ + if ((ret = ctf_dwarf_child(cup, die, &child)) != 0) + return (ret); + if (child == NULL) + return (0); + + return (0); +} + +static int +ctf_dwarf_create_array_range(ctf_cu_t *cup, Dwarf_Die range, ctf_id_t *idp, + ctf_id_t base, int isroot) +{ + int ret; + Dwarf_Die sib; + Dwarf_Unsigned val; + Dwarf_Signed sval; + ctf_arinfo_t ar; + + ctf_dprintf("creating array range\n"); + + if ((ret = ctf_dwarf_sib(cup, range, &sib)) != 0) + return (ret); + if (sib != NULL) { + ctf_id_t id; + if ((ret = ctf_dwarf_create_array_range(cup, sib, &id, + base, CTF_ADD_NONROOT)) != 0) + return (ret); + ar.ctr_contents = id; + } else { + ar.ctr_contents = base; + } + + if ((ar.ctr_index = ctf_dwarf_long(cup)) == CTF_ERR) + return (ctf_errno(cup->cu_ctfp)); + + /* + * Array bounds can be signed or unsigned, but there are several kinds + * of signless forms (data1, data2, etc) that take their sign from the + * routine that is trying to interpret them. That is, data1 can be + * either signed or unsigned, depending on whether you use the signed or + * unsigned accessor function. GCC will use the signless forms to store + * unsigned values which have their high bit set, so we need to try to + * read them first as unsigned to get positive values. We could also + * try signed first, falling back to unsigned if we got a negative + * value. + */ + if ((ret = ctf_dwarf_unsigned(cup, range, DW_AT_upper_bound, + &val)) == 0) { + ar.ctr_nelems = val + 1; + } else if (ret != ENOENT) { + return (ret); + } else if ((ret = ctf_dwarf_signed(cup, range, DW_AT_upper_bound, + &sval)) == 0) { + ar.ctr_nelems = sval + 1; + } else if (ret != ENOENT) { + return (ret); + } else { + ar.ctr_nelems = 0; + } + + if ((*idp = ctf_add_array(cup->cu_ctfp, isroot, &ar)) == CTF_ERR) + return (ctf_errno(cup->cu_ctfp)); + + return (0); +} + +/* + * Try and create an array type. First, the kind of the array is specified in + * the DW_AT_type entry. Next, the number of entries is stored in a more + * complicated form, we should have a child that has the DW_TAG_subrange type. + */ +static int +ctf_dwarf_create_array(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp, int isroot) +{ + int ret; + Dwarf_Die tdie, rdie; + ctf_id_t tid; + Dwarf_Half rtag; + + if ((ret = ctf_dwarf_refdie(cup, die, DW_AT_type, &tdie)) != 0) + return (ret); + if ((ret = ctf_dwarf_convert_type(cup, tdie, &tid, + CTF_ADD_NONROOT)) != 0) + return (ret); + + if ((ret = ctf_dwarf_child(cup, die, &rdie)) != 0) + return (ret); + if ((ret = ctf_dwarf_tag(cup, rdie, &rtag)) != 0) + return (ret); + if (rtag != DW_TAG_subrange_type) { + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "encountered array without DW_TAG_subrange_type child\n"); + return (ECTF_CONVBKERR); + } + + /* + * The compiler may opt to describe a multi-dimensional array as one + * giant array or it may opt to instead encode it as a series of + * subranges. If it's the latter, then for each subrange we introduce a + * type. We can always use the base type. + */ + if ((ret = ctf_dwarf_create_array_range(cup, rdie, idp, tid, + isroot)) != 0) + return (ret); + ctf_dprintf("Got back id %d\n", *idp); + return (ctf_dwmap_add(cup, *idp, die, B_FALSE)); +} + +static int +ctf_dwarf_create_reference(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp, + int kind, int isroot) +{ + int ret; + ctf_id_t id; + Dwarf_Die tdie; + char *name; + size_t namelen; + + if ((ret = ctf_dwarf_string(cup, die, DW_AT_name, &name)) != 0 && + ret != ENOENT) + return (ret); + if (ret == ENOENT) { + name = NULL; + namelen = 0; + } else { + namelen = strlen(name); + } + + ctf_dprintf("reference kind %d %s\n", kind, name != NULL ? name : "<>"); + + if ((ret = ctf_dwarf_refdie(cup, die, DW_AT_type, &tdie)) != 0) { + if (ret != ENOENT) { + ctf_free(name, namelen); + return (ret); + } + if ((id = ctf_dwarf_void(cup)) == CTF_ERR) { + ctf_free(name, namelen); + return (ctf_errno(cup->cu_ctfp)); + } + } else { + if ((ret = ctf_dwarf_convert_type(cup, tdie, &id, + CTF_ADD_NONROOT)) != 0) { + ctf_free(name, namelen); + return (ret); + } + } + + if ((*idp = ctf_add_reftype(cup->cu_ctfp, isroot, name, id, kind)) == + CTF_ERR) { + ctf_free(name, namelen); + return (ctf_errno(cup->cu_ctfp)); + } + + ctf_free(name, namelen); + return (ctf_dwmap_add(cup, *idp, die, B_FALSE)); +} + +static int +ctf_dwarf_create_enum(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp, int isroot) +{ + int ret; + ctf_id_t id; + Dwarf_Die child; + char *name; + + if ((ret = ctf_dwarf_string(cup, die, DW_AT_name, &name)) != 0 && + ret != ENOENT) + return (ret); + if (ret == ENOENT) + name = NULL; + id = ctf_add_enum(cup->cu_ctfp, isroot, name); + ctf_dprintf("added enum %s (%d)\n", name, id); + if (name != NULL) + ctf_free(name, strlen(name) + 1); + if (id == CTF_ERR) + return (ctf_errno(cup->cu_ctfp)); + *idp = id; + if ((ret = ctf_dwmap_add(cup, id, die, B_FALSE)) != 0) + return (ret); + + if ((ret = ctf_dwarf_child(cup, die, &child)) != 0) { + if (ret == ENOENT) + ret = 0; + return (ret); + } + + while (child != NULL) { + Dwarf_Half tag; + Dwarf_Signed sval; + Dwarf_Unsigned uval; + Dwarf_Die arg = child; + int eval; + + if ((ret = ctf_dwarf_sib(cup, arg, &child)) != 0) + return (ret); + + if ((ret = ctf_dwarf_tag(cup, arg, &tag)) != 0) + return (ret); + + if (tag != DW_TAG_enumerator) { + if ((ret = ctf_dwarf_convert_type(cup, arg, NULL, + CTF_ADD_NONROOT)) != 0) + return (ret); + continue; + } + + /* + * DWARF v4 section 5.7 tells us we'll always have names. + */ + if ((ret = ctf_dwarf_string(cup, arg, DW_AT_name, &name)) != 0) + return (ret); + + /* + * We have to be careful here: newer GCCs generate DWARF where + * an unsigned value will happily pass ctf_dwarf_signed(). + * Since negative values will fail ctf_dwarf_unsigned(), we try + * that first to make sure we get the right value. + */ + if ((ret = ctf_dwarf_unsigned(cup, arg, DW_AT_const_value, + &uval)) == 0) { + eval = (int)uval; + } else if ((ret = ctf_dwarf_signed(cup, arg, DW_AT_const_value, + &sval)) == 0) { + eval = sval; + } + + if (ret != 0) { + if (ret != ENOENT) + return (ret); + + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "encountered enumeration without constant value\n"); + return (ECTF_CONVBKERR); + } + + ret = ctf_add_enumerator(cup->cu_ctfp, id, name, eval); + if (ret == CTF_ERR) { + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to add enumarator %s (%d) to %d\n", + name, eval, id); + ctf_free(name, strlen(name) + 1); + return (ctf_errno(cup->cu_ctfp)); + } + ctf_free(name, strlen(name) + 1); + } + + return (0); +} + +/* + * For a function pointer, walk over and process all of its children, unless we + * encounter one that's just a declaration. In which case, we error on it. + */ +static int +ctf_dwarf_create_fptr(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp, int isroot) +{ + int ret; + Dwarf_Bool b; + ctf_funcinfo_t fi; + Dwarf_Die retdie; + ctf_id_t *argv = NULL; + + bzero(&fi, sizeof (ctf_funcinfo_t)); + + if ((ret = ctf_dwarf_boolean(cup, die, DW_AT_declaration, &b)) != 0) { + if (ret != ENOENT) + return (ret); + } else { + if (b != 0) + return (EPROTOTYPE); + } + + /* + * Return type is in DW_AT_type, if none, it returns void. + */ + if ((ret = ctf_dwarf_refdie(cup, die, DW_AT_type, &retdie)) != 0) { + if (ret != ENOENT) + return (ret); + if ((fi.ctc_return = ctf_dwarf_void(cup)) == CTF_ERR) + return (ctf_errno(cup->cu_ctfp)); + } else { + if ((ret = ctf_dwarf_convert_type(cup, retdie, &fi.ctc_return, + CTF_ADD_NONROOT)) != 0) + return (ret); + } + + if ((ret = ctf_dwarf_function_count(cup, die, &fi, B_TRUE)) != 0) { + return (ret); + } + + if (fi.ctc_argc != 0) { + argv = ctf_alloc(sizeof (ctf_id_t) * fi.ctc_argc); + if (argv == NULL) + return (ENOMEM); + + if ((ret = ctf_dwarf_convert_fargs(cup, die, &fi, argv)) != 0) { + ctf_free(argv, sizeof (ctf_id_t) * fi.ctc_argc); + return (ret); + } + } + + if ((*idp = ctf_add_funcptr(cup->cu_ctfp, isroot, &fi, argv)) == + CTF_ERR) { + ctf_free(argv, sizeof (ctf_id_t) * fi.ctc_argc); + return (ctf_errno(cup->cu_ctfp)); + } + + ctf_free(argv, sizeof (ctf_id_t) * fi.ctc_argc); + return (ctf_dwmap_add(cup, *idp, die, B_FALSE)); +} + +static int +ctf_dwarf_convert_type(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp, + int isroot) +{ + int ret; + Dwarf_Off offset; + Dwarf_Half tag; + ctf_dwmap_t lookup, *map; + ctf_id_t id; + + if (idp == NULL) + idp = &id; + + if ((ret = ctf_dwarf_offset(cup, die, &offset)) != 0) + return (ret); + + if (offset > cup->cu_maxoff) { + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "die offset %llu beyond maximum for header %llu\n", + offset, cup->cu_maxoff); + return (ECTF_CONVBKERR); + } + + /* + * If we've already added an entry for this offset, then we're done. + */ + lookup.cdm_off = offset; + if ((map = avl_find(&cup->cu_map, &lookup, NULL)) != NULL) { + *idp = map->cdm_id; + return (0); + } + + if ((ret = ctf_dwarf_tag(cup, die, &tag)) != 0) + return (ret); + + ret = ENOTSUP; + switch (tag) { + case DW_TAG_base_type: + ctf_dprintf("base\n"); + ret = ctf_dwarf_create_base(cup, die, idp, isroot, offset); + break; + case DW_TAG_array_type: + ctf_dprintf("array\n"); + ret = ctf_dwarf_create_array(cup, die, idp, isroot); + break; + case DW_TAG_enumeration_type: + ctf_dprintf("enum\n"); + ret = ctf_dwarf_create_enum(cup, die, idp, isroot); + break; + case DW_TAG_pointer_type: + ctf_dprintf("pointer\n"); + ret = ctf_dwarf_create_reference(cup, die, idp, CTF_K_POINTER, + isroot); + break; + case DW_TAG_structure_type: + ctf_dprintf("struct\n"); + ret = ctf_dwarf_create_sou(cup, die, idp, CTF_K_STRUCT, + isroot); + break; + case DW_TAG_subroutine_type: + ctf_dprintf("fptr\n"); + ret = ctf_dwarf_create_fptr(cup, die, idp, isroot); + break; + case DW_TAG_typedef: + ctf_dprintf("typedef\n"); + ret = ctf_dwarf_create_reference(cup, die, idp, CTF_K_TYPEDEF, + isroot); + break; + case DW_TAG_union_type: + ctf_dprintf("union\n"); + ret = ctf_dwarf_create_sou(cup, die, idp, CTF_K_UNION, + isroot); + break; + case DW_TAG_const_type: + ctf_dprintf("const\n"); + ret = ctf_dwarf_create_reference(cup, die, idp, CTF_K_CONST, + isroot); + break; + case DW_TAG_volatile_type: + ctf_dprintf("volatile\n"); + ret = ctf_dwarf_create_reference(cup, die, idp, CTF_K_VOLATILE, + isroot); + break; + case DW_TAG_restrict_type: + ctf_dprintf("restrict\n"); + ret = ctf_dwarf_create_reference(cup, die, idp, CTF_K_RESTRICT, + isroot); + break; + default: + ctf_dprintf("ignoring tag type %x\n", tag); + ret = 0; + break; + } + ctf_dprintf("ctf_dwarf_convert_type tag specific handler returned %d\n", + ret); + + return (ret); +} + +static int +ctf_dwarf_walk_lexical(ctf_cu_t *cup, Dwarf_Die die) +{ + int ret; + Dwarf_Die child; + + if ((ret = ctf_dwarf_child(cup, die, &child)) != 0) + return (ret); + + if (child == NULL) + return (0); + + return (ctf_dwarf_convert_die(cup, die)); +} + +static int +ctf_dwarf_function_count(ctf_cu_t *cup, Dwarf_Die die, ctf_funcinfo_t *fip, + boolean_t fptr) +{ + int ret; + Dwarf_Die child, sib, arg; + + if ((ret = ctf_dwarf_child(cup, die, &child)) != 0) + return (ret); + + arg = child; + while (arg != NULL) { + Dwarf_Half tag; + + if ((ret = ctf_dwarf_tag(cup, arg, &tag)) != 0) + return (ret); + + /* + * We have to check for a varargs type decleration. This will + * happen in one of two ways. If we have a function pointer + * type, then it'll be done with a tag of type + * DW_TAG_unspecified_parameters. However, it only means we have + * a variable number of arguments, if we have more than one + * argument found so far. Otherwise, when we have a function + * type, it instead uses a formal parameter whose name is '...' + * to indicate a variable arguments member. + * + * Also, if we have a function pointer, then we have to expect + * that we might not get a name at all. + */ + if (tag == DW_TAG_formal_parameter && fptr == B_FALSE) { + char *name; + if ((ret = ctf_dwarf_string(cup, die, DW_AT_name, + &name)) != 0) + return (ret); + if (strcmp(name, DWARF_VARARGS_NAME) == 0) + fip->ctc_flags |= CTF_FUNC_VARARG; + else + fip->ctc_argc++; + ctf_free(name, strlen(name) + 1); + } else if (tag == DW_TAG_formal_parameter) { + fip->ctc_argc++; + } else if (tag == DW_TAG_unspecified_parameters && + fip->ctc_argc > 0) { + fip->ctc_flags |= CTF_FUNC_VARARG; + } + if ((ret = ctf_dwarf_sib(cup, arg, &sib)) != 0) + return (ret); + arg = sib; + } + + return (0); +} + +static int +ctf_dwarf_convert_fargs(ctf_cu_t *cup, Dwarf_Die die, ctf_funcinfo_t *fip, + ctf_id_t *argv) +{ + int ret; + int i = 0; + Dwarf_Die child, sib, arg; + + if ((ret = ctf_dwarf_child(cup, die, &child)) != 0) + return (ret); + + arg = child; + while (arg != NULL) { + Dwarf_Half tag; + + if ((ret = ctf_dwarf_tag(cup, arg, &tag)) != 0) + return (ret); + if (tag == DW_TAG_formal_parameter) { + Dwarf_Die tdie; + + if ((ret = ctf_dwarf_refdie(cup, arg, DW_AT_type, + &tdie)) != 0) + return (ret); + + if ((ret = ctf_dwarf_convert_type(cup, tdie, &argv[i], + CTF_ADD_ROOT)) != 0) + return (ret); + i++; + + /* + * Once we hit argc entries, we're done. This ensures we + * don't accidentally hit a varargs which should be the + * last entry. + */ + if (i == fip->ctc_argc) + break; + } + + if ((ret = ctf_dwarf_sib(cup, arg, &sib)) != 0) + return (ret); + arg = sib; + } + + return (0); +} + +static int +ctf_dwarf_convert_function(ctf_cu_t *cup, Dwarf_Die die) +{ + int ret; + char *name; + ctf_dwfunc_t *cdf; + Dwarf_Die tdie; + + /* + * Functions that don't have a name are generally functions that have + * been inlined and thus most information about them has been lost. If + * we can't get a name, then instead of returning ENOENT, we silently + * swallow the error. + */ + if ((ret = ctf_dwarf_string(cup, die, DW_AT_name, &name)) != 0) { + if (ret == ENOENT) + return (0); + return (ret); + } + + ctf_dprintf("beginning work on function %s\n", name); + if ((cdf = ctf_alloc(sizeof (ctf_dwfunc_t))) == NULL) { + ctf_free(name, strlen(name) + 1); + return (ENOMEM); + } + bzero(cdf, sizeof (ctf_dwfunc_t)); + cdf->cdf_name = name; + + if ((ret = ctf_dwarf_refdie(cup, die, DW_AT_type, &tdie)) == 0) { + if ((ret = ctf_dwarf_convert_type(cup, tdie, + &(cdf->cdf_fip.ctc_return), CTF_ADD_ROOT)) != 0) { + ctf_free(name, strlen(name) + 1); + ctf_free(cdf, sizeof (ctf_dwfunc_t)); + return (ret); + } + } else if (ret != ENOENT) { + ctf_free(name, strlen(name) + 1); + ctf_free(cdf, sizeof (ctf_dwfunc_t)); + return (ret); + } else { + if ((cdf->cdf_fip.ctc_return = ctf_dwarf_void(cup)) == + CTF_ERR) { + ctf_free(name, strlen(name) + 1); + ctf_free(cdf, sizeof (ctf_dwfunc_t)); + return (ctf_errno(cup->cu_ctfp)); + } + } + + /* + * A function has a number of children, some of which may not be ones we + * care about. Children that we care about have a type of + * DW_TAG_formal_parameter. We're going to do two passes, the first to + * count the arguments, the second to process them. Afterwards, we + * should be good to go ahead and add this function. + * + * Note, we already got the return type by going in and grabbing it out + * of the DW_AT_type. + */ + if ((ret = ctf_dwarf_function_count(cup, die, &cdf->cdf_fip, + B_FALSE)) != 0) { + ctf_free(name, strlen(name) + 1); + ctf_free(cdf, sizeof (ctf_dwfunc_t)); + return (ret); + } + + ctf_dprintf("beginning to convert function arguments %s\n", name); + if (cdf->cdf_fip.ctc_argc != 0) { + uint_t argc = cdf->cdf_fip.ctc_argc; + cdf->cdf_argv = ctf_alloc(sizeof (ctf_id_t) * argc); + if (cdf->cdf_argv == NULL) { + ctf_free(name, strlen(name) + 1); + ctf_free(cdf, sizeof (ctf_dwfunc_t)); + return (ENOMEM); + } + if ((ret = ctf_dwarf_convert_fargs(cup, die, + &cdf->cdf_fip, cdf->cdf_argv)) != 0) { + ctf_free(cdf->cdf_argv, sizeof (ctf_id_t) * argc); + ctf_free(name, strlen(name) + 1); + ctf_free(cdf, sizeof (ctf_dwfunc_t)); + return (ret); + } + } else { + cdf->cdf_argv = NULL; + } + + if ((ret = ctf_dwarf_isglobal(cup, die, &cdf->cdf_global)) != 0) { + ctf_free(cdf->cdf_argv, sizeof (ctf_id_t) * + cdf->cdf_fip.ctc_argc); + ctf_free(name, strlen(name) + 1); + ctf_free(cdf, sizeof (ctf_dwfunc_t)); + return (ret); + } + + ctf_list_append(&cup->cu_funcs, cdf); + return (ret); +} + +/* + * Convert variables, but only if they're not prototypes and have names. + */ +static int +ctf_dwarf_convert_variable(ctf_cu_t *cup, Dwarf_Die die) +{ + int ret; + char *name; + Dwarf_Bool b; + Dwarf_Die tdie; + ctf_id_t id; + ctf_dwvar_t *cdv; + + /* Skip "Non-Defining Declarations" */ + if ((ret = ctf_dwarf_boolean(cup, die, DW_AT_declaration, &b)) == 0) { + if (b != 0) + return (0); + } else if (ret != ENOENT) { + return (ret); + } + + /* + * If we find a DIE of "Declarations Completing Non-Defining + * Declarations", we will use the referenced type's DIE. This isn't + * quite correct, e.g. DW_AT_decl_line will be the forward declaration + * not this site. It's sufficient for what we need, however: in + * particular, we should find DW_AT_external as needed there. + */ + if ((ret = ctf_dwarf_refdie(cup, die, DW_AT_specification, + &tdie)) == 0) { + Dwarf_Off offset; + if ((ret = ctf_dwarf_offset(cup, tdie, &offset)) != 0) + return (ret); + ctf_dprintf("die 0x%llx DW_AT_specification -> die 0x%llx\n", + ctf_die_offset(die), ctf_die_offset(tdie)); + die = tdie; + } else if (ret != ENOENT) { + return (ret); + } + + if ((ret = ctf_dwarf_string(cup, die, DW_AT_name, &name)) != 0 && + ret != ENOENT) + return (ret); + if (ret == ENOENT) + return (0); + + if ((ret = ctf_dwarf_refdie(cup, die, DW_AT_type, &tdie)) != 0) { + ctf_free(name, strlen(name) + 1); + return (ret); + } + + if ((ret = ctf_dwarf_convert_type(cup, tdie, &id, + CTF_ADD_ROOT)) != 0) + return (ret); + + if ((cdv = ctf_alloc(sizeof (ctf_dwvar_t))) == NULL) { + ctf_free(name, strlen(name) + 1); + return (ENOMEM); + } + + cdv->cdv_name = name; + cdv->cdv_type = id; + + if ((ret = ctf_dwarf_isglobal(cup, die, &cdv->cdv_global)) != 0) { + ctf_free(cdv, sizeof (ctf_dwvar_t)); + ctf_free(name, strlen(name) + 1); + return (ret); + } + + ctf_list_append(&cup->cu_vars, cdv); + return (0); +} + +/* + * Walk through our set of top-level types and process them. + */ +static int +ctf_dwarf_walk_toplevel(ctf_cu_t *cup, Dwarf_Die die) +{ + int ret; + Dwarf_Off offset; + Dwarf_Half tag; + + if ((ret = ctf_dwarf_offset(cup, die, &offset)) != 0) + return (ret); + + if (offset > cup->cu_maxoff) { + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "die offset %llu beyond maximum for header %llu\n", + offset, cup->cu_maxoff); + return (ECTF_CONVBKERR); + } + + if ((ret = ctf_dwarf_tag(cup, die, &tag)) != 0) + return (ret); + + ret = 0; + switch (tag) { + case DW_TAG_subprogram: + ctf_dprintf("top level func\n"); + ret = ctf_dwarf_convert_function(cup, die); + break; + case DW_TAG_variable: + ctf_dprintf("top level var\n"); + ret = ctf_dwarf_convert_variable(cup, die); + break; + case DW_TAG_lexical_block: + ctf_dprintf("top level block\n"); + ret = ctf_dwarf_walk_lexical(cup, die); + break; + case DW_TAG_enumeration_type: + case DW_TAG_structure_type: + case DW_TAG_typedef: + case DW_TAG_union_type: + ctf_dprintf("top level type\n"); + ret = ctf_dwarf_convert_type(cup, die, NULL, B_TRUE); + break; + default: + break; + } + + return (ret); +} + + +/* + * We're given a node. At this node we need to convert it and then proceed to + * convert any siblings that are associaed with this die. + */ +static int +ctf_dwarf_convert_die(ctf_cu_t *cup, Dwarf_Die die) +{ + while (die != NULL) { + int ret; + Dwarf_Die sib; + + if ((ret = ctf_dwarf_walk_toplevel(cup, die)) != 0) + return (ret); + + if ((ret = ctf_dwarf_sib(cup, die, &sib)) != 0) + return (ret); + die = sib; + } + return (0); +} + +static int +ctf_dwarf_fixup_die(ctf_cu_t *cup, boolean_t addpass) +{ + ctf_dwmap_t *map; + + for (map = avl_first(&cup->cu_map); map != NULL; + map = AVL_NEXT(&cup->cu_map, map)) { + int ret; + if (map->cdm_fix == B_FALSE) + continue; + if ((ret = ctf_dwarf_fixup_sou(cup, map->cdm_die, map->cdm_id, + addpass)) != 0) + return (ret); + } + + return (0); +} + +static ctf_dwfunc_t * +ctf_dwarf_match_func(ctf_cu_t *cup, const char *file, const char *name, + int bind) +{ + ctf_dwfunc_t *cdf; + + if (bind == STB_WEAK) + return (NULL); + + /* Nothing we can do if we can't find a name to compare it to. */ + if (bind == STB_LOCAL && (file == NULL || cup->cu_name == NULL)) + return (NULL); + + for (cdf = ctf_list_next(&cup->cu_funcs); cdf != NULL; + cdf = ctf_list_next(cdf)) { + if (bind == STB_GLOBAL && cdf->cdf_global == B_FALSE) + continue; + if (bind == STB_LOCAL && cdf->cdf_global == B_TRUE) + continue; + if (strcmp(name, cdf->cdf_name) != 0) + continue; + if (bind == STB_LOCAL && strcmp(file, cup->cu_name) != 0) + continue; + return (cdf); + } + + return (NULL); +} +static ctf_dwvar_t * +ctf_dwarf_match_var(ctf_cu_t *cup, const char *file, const char *name, + int bind) +{ + ctf_dwvar_t *cdv; + + /* Nothing we can do if we can't find a name to compare it to. */ + if (bind == STB_LOCAL && (file == NULL || cup->cu_name == NULL)) + return (NULL); + ctf_dprintf("Still considering %s\n", name); + + for (cdv = ctf_list_next(&cup->cu_vars); cdv != NULL; + cdv = ctf_list_next(cdv)) { + if (bind == STB_GLOBAL && cdv->cdv_global == B_FALSE) + continue; + if (bind == STB_LOCAL && cdv->cdv_global == B_TRUE) + continue; + if (strcmp(name, cdv->cdv_name) != 0) + continue; + if (bind == STB_LOCAL && strcmp(file, cup->cu_name) != 0) + continue; + return (cdv); + } + + return (NULL); +} + +static int +ctf_dwarf_symtab_iter(ctf_cu_t *cup, ctf_dwarf_symtab_f *func, void *arg) +{ + int ret; + ulong_t i; + ctf_file_t *fp = cup->cu_ctfp; + const char *file = NULL; + uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data; + uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data; + + for (i = 0; i < fp->ctf_nsyms; i++) { + const char *name; + int type; + GElf_Sym gsym; + const GElf_Sym *gsymp; + + if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) { + const Elf32_Sym *symp = (Elf32_Sym *)symbase + i; + type = ELF32_ST_TYPE(symp->st_info); + if (type == STT_FILE) { + file = (char *)(strbase + symp->st_name); + continue; + } + if (type != STT_OBJECT && type != STT_FUNC) + continue; + if (ctf_sym_valid(strbase, type, symp->st_shndx, + symp->st_value, symp->st_name) == B_FALSE) + continue; + name = (char *)(strbase + symp->st_name); + gsym.st_name = symp->st_name; + gsym.st_value = symp->st_value; + gsym.st_size = symp->st_size; + gsym.st_info = symp->st_info; + gsym.st_other = symp->st_other; + gsym.st_shndx = symp->st_shndx; + gsymp = &gsym; + } else { + const Elf64_Sym *symp = (Elf64_Sym *)symbase + i; + type = ELF64_ST_TYPE(symp->st_info); + if (type == STT_FILE) { + file = (char *)(strbase + symp->st_name); + continue; + } + if (type != STT_OBJECT && type != STT_FUNC) + continue; + if (ctf_sym_valid(strbase, type, symp->st_shndx, + symp->st_value, symp->st_name) == B_FALSE) + continue; + name = (char *)(strbase + symp->st_name); + gsymp = symp; + } + + ret = func(cup, gsymp, i, file, name, arg); + if (ret != 0) + return (ret); + } + + return (0); +} + +static int +ctf_dwarf_conv_funcvars_cb(ctf_cu_t *cup, const GElf_Sym *symp, ulong_t idx, + const char *file, const char *name, void *arg) +{ + int ret, bind, type; + + bind = GELF_ST_BIND(symp->st_info); + type = GELF_ST_TYPE(symp->st_info); + + /* + * Come back to weak symbols in another pass + */ + if (bind == STB_WEAK) + return (0); + + if (type == STT_OBJECT) { + ctf_dwvar_t *cdv = ctf_dwarf_match_var(cup, file, name, + bind); + ctf_dprintf("match for %s (%d): %p\n", name, idx, cdv); + if (cdv == NULL) + return (0); + ret = ctf_add_object(cup->cu_ctfp, idx, cdv->cdv_type); + ctf_dprintf("added object %s\n", name); + } else { + ctf_dwfunc_t *cdf = ctf_dwarf_match_func(cup, file, name, + bind); + if (cdf == NULL) + return (0); + ret = ctf_add_function(cup->cu_ctfp, idx, &cdf->cdf_fip, + cdf->cdf_argv); + } + + if (ret == CTF_ERR) { + return (ctf_errno(cup->cu_ctfp)); + } + + return (0); +} + +static int +ctf_dwarf_conv_funcvars(ctf_cu_t *cup) +{ + return (ctf_dwarf_symtab_iter(cup, ctf_dwarf_conv_funcvars_cb, NULL)); +} + +/* + * If we have a weak symbol, attempt to find the strong symbol it will resolve + * to. Note: the code where this actually happens is in sym_process() in + * cmd/sgs/libld/common/syms.c + * + * Finding the matching symbol is unfortunately not trivial. For a symbol to be + * a candidate, it must: + * + * - have the same type (function, object) + * - have the same value (address) + * - have the same size + * - not be another weak symbol + * - belong to the same section (checked via section index) + * + * To perform this check, we first iterate over the symbol table. For each weak + * symbol that we encounter, we then do a second walk over the symbol table, + * calling ctf_dwarf_conv_check_weak(). If a symbol matches the above, then it's + * either a local or global symbol. If we find a global symbol then we go with + * it and stop searching for additional matches. + * + * If instead, we find a local symbol, things are more complicated. The first + * thing we do is to try and see if we have file information about both symbols + * (STT_FILE). If they both have file information and it matches, then we treat + * that as a good match and stop searching for additional matches. + * + * Otherwise, this means we have a non-matching file and a local symbol. We + * treat this as a candidate and if we find a better match (one of the two cases + * above), use that instead. There are two different ways this can happen. + * Either this is a completely different symbol, or it's a once-global symbol + * that was scoped to local via a mapfile. In the former case, curfile is + * likely inaccurate since the linker does not preserve the needed curfile in + * the order of the symbol table (see the comments about locally scoped symbols + * in libld's update_osym()). As we can't tell this case from the former one, + * we use this symbol iff no other matching symbol is found. + * + * What we really need here is a SUNW section containing weak<->strong mappings + * that we can consume. + */ +typedef struct ctf_dwarf_weak_arg { + const GElf_Sym *cweak_symp; + const char *cweak_file; + boolean_t cweak_candidate; + ulong_t cweak_idx; +} ctf_dwarf_weak_arg_t; + +static int +ctf_dwarf_conv_check_weak(ctf_cu_t *cup, const GElf_Sym *symp, + ulong_t idx, const char *file, const char *name, void *arg) +{ + ctf_dwarf_weak_arg_t *cweak = arg; + const GElf_Sym *wsymp = cweak->cweak_symp; + + ctf_dprintf("comparing weak to %s\n", name); + + if (GELF_ST_BIND(symp->st_info) == STB_WEAK) { + return (0); + } + + if (GELF_ST_TYPE(wsymp->st_info) != GELF_ST_TYPE(symp->st_info)) { + return (0); + } + + if (wsymp->st_value != symp->st_value) { + return (0); + } + + if (wsymp->st_size != symp->st_size) { + return (0); + } + + if (wsymp->st_shndx != symp->st_shndx) { + return (0); + } + + /* + * Check if it's a weak candidate. + */ + if (GELF_ST_BIND(symp->st_info) == STB_LOCAL && + (file == NULL || cweak->cweak_file == NULL || + strcmp(file, cweak->cweak_file) != 0)) { + cweak->cweak_candidate = B_TRUE; + cweak->cweak_idx = idx; + return (0); + } + + /* + * Found a match, break. + */ + cweak->cweak_idx = idx; + return (1); +} + +static int +ctf_dwarf_duplicate_sym(ctf_cu_t *cup, ulong_t idx, ulong_t matchidx) +{ + ctf_id_t id = ctf_lookup_by_symbol(cup->cu_ctfp, matchidx); + + /* + * If we matched something that for some reason didn't have type data, + * we don't consider that a fatal error and silently swallow it. + */ + if (id == CTF_ERR) { + if (ctf_errno(cup->cu_ctfp) == ECTF_NOTYPEDAT) + return (0); + else + return (ctf_errno(cup->cu_ctfp)); + } + + if (ctf_add_object(cup->cu_ctfp, idx, id) == CTF_ERR) + return (ctf_errno(cup->cu_ctfp)); + + return (0); +} + +static int +ctf_dwarf_duplicate_func(ctf_cu_t *cup, ulong_t idx, ulong_t matchidx) +{ + int ret; + ctf_funcinfo_t fip; + ctf_id_t *args = NULL; + + if (ctf_func_info(cup->cu_ctfp, matchidx, &fip) == CTF_ERR) { + if (ctf_errno(cup->cu_ctfp) == ECTF_NOFUNCDAT) + return (0); + else + return (ctf_errno(cup->cu_ctfp)); + } + + if (fip.ctc_argc != 0) { + args = ctf_alloc(sizeof (ctf_id_t) * fip.ctc_argc); + if (args == NULL) + return (ENOMEM); + + if (ctf_func_args(cup->cu_ctfp, matchidx, fip.ctc_argc, args) == + CTF_ERR) { + ctf_free(args, sizeof (ctf_id_t) * fip.ctc_argc); + return (ctf_errno(cup->cu_ctfp)); + } + } + + ret = ctf_add_function(cup->cu_ctfp, idx, &fip, args); + if (args != NULL) + ctf_free(args, sizeof (ctf_id_t) * fip.ctc_argc); + if (ret == CTF_ERR) + return (ctf_errno(cup->cu_ctfp)); + + return (0); +} + +static int +ctf_dwarf_conv_weaks_cb(ctf_cu_t *cup, const GElf_Sym *symp, + ulong_t idx, const char *file, const char *name, void *arg) +{ + int ret, type; + ctf_dwarf_weak_arg_t cweak; + + /* + * We only care about weak symbols. + */ + if (GELF_ST_BIND(symp->st_info) != STB_WEAK) + return (0); + + type = GELF_ST_TYPE(symp->st_info); + ASSERT(type == STT_OBJECT || type == STT_FUNC); + + /* + * For each weak symbol we encounter, we need to do a second iteration + * to try and find a match. We should probably think about other + * techniques to try and save us time in the future. + */ + cweak.cweak_symp = symp; + cweak.cweak_file = file; + cweak.cweak_candidate = B_FALSE; + cweak.cweak_idx = 0; + + ctf_dprintf("Trying to find weak equiv for %s\n", name); + + ret = ctf_dwarf_symtab_iter(cup, ctf_dwarf_conv_check_weak, &cweak); + VERIFY(ret == 0 || ret == 1); + + /* + * Nothing was ever found, we're not going to add anything for this + * entry. + */ + if (ret == 0 && cweak.cweak_candidate == B_FALSE) { + ctf_dprintf("found no weak match for %s\n", name); + return (0); + } + + /* + * Now, finally go and add the type based on the match. + */ + if (type == STT_OBJECT) { + ret = ctf_dwarf_duplicate_sym(cup, idx, cweak.cweak_idx); + } else { + ret = ctf_dwarf_duplicate_func(cup, idx, cweak.cweak_idx); + } + + return (ret); +} + +static int +ctf_dwarf_conv_weaks(ctf_cu_t *cup) +{ + return (ctf_dwarf_symtab_iter(cup, ctf_dwarf_conv_weaks_cb, NULL)); +} + +/* ARGSUSED */ +static int +ctf_dwarf_convert_one(void *arg, void *unused) +{ + int ret; + ctf_file_t *dedup; + ctf_cu_t *cup = arg; + + ctf_dprintf("converting die: %s\n", cup->cu_name); + ctf_dprintf("max offset: %x\n", cup->cu_maxoff); + VERIFY(cup != NULL); + + ret = ctf_dwarf_convert_die(cup, cup->cu_cu); + ctf_dprintf("ctf_dwarf_convert_die (%s) returned %d\n", cup->cu_name, + ret); + if (ret != 0) { + return (ret); + } + if (ctf_update(cup->cu_ctfp) != 0) { + return (ctf_dwarf_error(cup, cup->cu_ctfp, 0, + "failed to update output ctf container")); + } + + ret = ctf_dwarf_fixup_die(cup, B_FALSE); + ctf_dprintf("ctf_dwarf_fixup_die (%s) returned %d\n", cup->cu_name, + ret); + if (ret != 0) { + return (ret); + } + if (ctf_update(cup->cu_ctfp) != 0) { + return (ctf_dwarf_error(cup, cup->cu_ctfp, 0, + "failed to update output ctf container")); + } + + ret = ctf_dwarf_fixup_die(cup, B_TRUE); + ctf_dprintf("ctf_dwarf_fixup_die (%s) returned %d\n", cup->cu_name, + ret); + if (ret != 0) { + return (ret); + } + if (ctf_update(cup->cu_ctfp) != 0) { + return (ctf_dwarf_error(cup, cup->cu_ctfp, 0, + "failed to update output ctf container")); + } + + + if ((ret = ctf_dwarf_conv_funcvars(cup)) != 0) { + return (ctf_dwarf_error(cup, NULL, ret, + "failed to convert strong functions and variables")); + } + + if (ctf_update(cup->cu_ctfp) != 0) { + return (ctf_dwarf_error(cup, cup->cu_ctfp, 0, + "failed to update output ctf container")); + } + + if (cup->cu_doweaks == B_TRUE) { + if ((ret = ctf_dwarf_conv_weaks(cup)) != 0) { + return (ctf_dwarf_error(cup, NULL, ret, + "failed to convert weak functions and variables")); + } + + if (ctf_update(cup->cu_ctfp) != 0) { + return (ctf_dwarf_error(cup, cup->cu_ctfp, 0, + "failed to update output ctf container")); + } + } + + ctf_phase_dump(cup->cu_ctfp, "pre-dedup"); + ctf_dprintf("adding inputs for dedup\n"); + if ((ret = ctf_merge_add(cup->cu_cmh, cup->cu_ctfp)) != 0) { + return (ctf_dwarf_error(cup, NULL, ret, + "failed to add inputs for merge")); + } + + ctf_dprintf("starting merge\n"); + if ((ret = ctf_merge_dedup(cup->cu_cmh, &dedup)) != 0) { + return (ctf_dwarf_error(cup, NULL, ret, + "failed to deduplicate die")); + } + ctf_close(cup->cu_ctfp); + cup->cu_ctfp = dedup; + + return (0); +} + +/* + * Note, we expect that if we're returning a ctf_file_t from one of the dies, + * say in the single node case, it's been saved and the entry here has been set + * to NULL, which ctf_close happily ignores. + */ +static void +ctf_dwarf_free_die(ctf_cu_t *cup) +{ + ctf_dwfunc_t *cdf, *ndf; + ctf_dwvar_t *cdv, *ndv; + ctf_dwbitf_t *cdb, *ndb; + ctf_dwmap_t *map; + void *cookie; + Dwarf_Error derr; + + ctf_dprintf("Beginning to free die: %p\n", cup); + cup->cu_elf = NULL; + ctf_dprintf("Trying to free name: %p\n", cup->cu_name); + if (cup->cu_name != NULL) + ctf_free(cup->cu_name, strlen(cup->cu_name) + 1); + ctf_dprintf("Trying to free merge handle: %p\n", cup->cu_cmh); + if (cup->cu_cmh != NULL) { + ctf_merge_fini(cup->cu_cmh); + cup->cu_cmh = NULL; + } + + ctf_dprintf("Trying to free functions\n"); + for (cdf = ctf_list_next(&cup->cu_funcs); cdf != NULL; cdf = ndf) { + ndf = ctf_list_next(cdf); + ctf_free(cdf->cdf_name, strlen(cdf->cdf_name) + 1); + if (cdf->cdf_fip.ctc_argc != 0) { + ctf_free(cdf->cdf_argv, + sizeof (ctf_id_t) * cdf->cdf_fip.ctc_argc); + } + ctf_free(cdf, sizeof (ctf_dwfunc_t)); + } + + ctf_dprintf("Trying to free variables\n"); + for (cdv = ctf_list_next(&cup->cu_vars); cdv != NULL; cdv = ndv) { + ndv = ctf_list_next(cdv); + ctf_free(cdv->cdv_name, strlen(cdv->cdv_name) + 1); + ctf_free(cdv, sizeof (ctf_dwvar_t)); + } + + ctf_dprintf("Trying to free bitfields\n"); + for (cdb = ctf_list_next(&cup->cu_bitfields); cdb != NULL; cdb = ndb) { + ndb = ctf_list_next(cdb); + ctf_free(cdb, sizeof (ctf_dwbitf_t)); + } + + ctf_dprintf("Trying to clean up dwarf_t: %p\n", cup->cu_dwarf); + (void) dwarf_finish(cup->cu_dwarf, &derr); + cup->cu_dwarf = NULL; + ctf_close(cup->cu_ctfp); + + cookie = NULL; + while ((map = avl_destroy_nodes(&cup->cu_map, &cookie)) != NULL) { + ctf_free(map, sizeof (ctf_dwmap_t)); + } + avl_destroy(&cup->cu_map); + cup->cu_errbuf = NULL; +} + +static void +ctf_dwarf_free_dies(ctf_cu_t *cdies, int ndies) +{ + int i; + + ctf_dprintf("Beginning to free dies\n"); + for (i = 0; i < ndies; i++) { + ctf_dwarf_free_die(&cdies[i]); + } + + ctf_free(cdies, sizeof (ctf_cu_t) * ndies); +} + +static int +ctf_dwarf_count_dies(Dwarf_Debug dw, Dwarf_Error *derr, int *ndies, + char *errbuf, size_t errlen) +{ + int ret; + Dwarf_Half vers; + Dwarf_Unsigned nexthdr; + + while ((ret = dwarf_next_cu_header(dw, NULL, &vers, NULL, NULL, + &nexthdr, derr)) != DW_DLV_NO_ENTRY) { + if (ret != DW_DLV_OK) { + (void) snprintf(errbuf, errlen, + "file does not contain valid DWARF data: %s\n", + dwarf_errmsg(*derr)); + return (ECTF_CONVBKERR); + } + + if (vers != DWARF_VERSION_TWO) { + (void) snprintf(errbuf, errlen, + "unsupported DWARF version: %d\n", vers); + return (ECTF_CONVBKERR); + } + *ndies = *ndies + 1; + } + + if (*ndies == 0) { + (void) snprintf(errbuf, errlen, + "file does not contain valid DWARF data: %s\n", + dwarf_errmsg(*derr)); + return (ECTF_CONVBKERR); + } + + return (0); +} + +static int +ctf_dwarf_init_die(int fd, Elf *elf, ctf_cu_t *cup, int ndie, char *errbuf, + size_t errlen) +{ + int ret; + Dwarf_Unsigned hdrlen, abboff, nexthdr; + Dwarf_Half addrsz; + Dwarf_Unsigned offset = 0; + Dwarf_Error derr; + + while ((ret = dwarf_next_cu_header(cup->cu_dwarf, &hdrlen, NULL, + &abboff, &addrsz, &nexthdr, &derr)) != DW_DLV_NO_ENTRY) { + char *name; + Dwarf_Die cu, child; + + /* Based on the counting above, we should be good to go */ + VERIFY(ret == DW_DLV_OK); + if (ndie > 0) { + ndie--; + offset = nexthdr; + continue; + } + + /* + * Compilers are apparently inconsistent. Some emit no DWARF for + * empty files and others emit empty compilation unit. + */ + cup->cu_voidtid = CTF_ERR; + cup->cu_longtid = CTF_ERR; + cup->cu_elf = elf; + cup->cu_maxoff = nexthdr - 1; + cup->cu_ctfp = ctf_fdcreate(fd, &ret); + if (cup->cu_ctfp == NULL) { + ctf_free(cup, sizeof (ctf_cu_t)); + return (ret); + } + avl_create(&cup->cu_map, ctf_dwmap_comp, sizeof (ctf_dwmap_t), + offsetof(ctf_dwmap_t, cdm_avl)); + cup->cu_errbuf = errbuf; + cup->cu_errlen = errlen; + bzero(&cup->cu_vars, sizeof (ctf_list_t)); + bzero(&cup->cu_funcs, sizeof (ctf_list_t)); + bzero(&cup->cu_bitfields, sizeof (ctf_list_t)); + + if ((ret = ctf_dwarf_die_elfenc(elf, cup, errbuf, + errlen)) != 0) { + avl_destroy(&cup->cu_map); + ctf_free(cup, sizeof (ctf_cu_t)); + return (ret); + } + + if ((ret = ctf_dwarf_sib(cup, NULL, &cu)) != 0) { + avl_destroy(&cup->cu_map); + ctf_free(cup, sizeof (ctf_cu_t)); + return (ret); + } + if (cu == NULL) { + (void) snprintf(errbuf, errlen, + "file does not contain DWARF data\n"); + avl_destroy(&cup->cu_map); + ctf_free(cup, sizeof (ctf_cu_t)); + return (ECTF_CONVBKERR); + } + + if ((ret = ctf_dwarf_child(cup, cu, &child)) != 0) { + avl_destroy(&cup->cu_map); + ctf_free(cup, sizeof (ctf_cu_t)); + return (ret); + } + if (child == NULL) { + (void) snprintf(errbuf, errlen, + "file does not contain DWARF data\n"); + avl_destroy(&cup->cu_map); + ctf_free(cup, sizeof (ctf_cu_t)); + return (ECTF_CONVBKERR); + } + + cup->cu_cuoff = offset; + cup->cu_cu = child; + + if ((cup->cu_cmh = ctf_merge_init(fd, &ret)) == NULL) { + avl_destroy(&cup->cu_map); + ctf_free(cup, sizeof (ctf_cu_t)); + return (ret); + } + + if (ctf_dwarf_string(cup, cu, DW_AT_name, &name) == 0) { + size_t len = strlen(name) + 1; + char *b = basename(name); + cup->cu_name = strdup(b); + ctf_free(name, len); + } + break; + } + + return (0); +} + + +ctf_conv_status_t +ctf_dwarf_convert(int fd, Elf *elf, uint_t nthrs, int *errp, ctf_file_t **fpp, + char *errmsg, size_t errlen) +{ + int err, ret, ndies, i; + Dwarf_Debug dw; + Dwarf_Error derr; + ctf_cu_t *cdies = NULL, *cup; + workq_t *wqp = NULL; + + if (errp == NULL) + errp = &err; + *errp = 0; + *fpp = NULL; + + ret = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dw, &derr); + if (ret != DW_DLV_OK) { + /* + * We may want to expect DWARF data here and fail conversion if + * it's missing. In this case, if we actually have some amount + * of DWARF, but no section, for now, just go ahead and create + * an empty CTF file. + */ + if (ret == DW_DLV_NO_ENTRY || + dwarf_errno(derr) == DW_DLE_DEBUG_INFO_NULL) { + *fpp = ctf_create(errp); + return (*fpp != NULL ? CTF_CONV_SUCCESS : + CTF_CONV_ERROR); + } + (void) snprintf(errmsg, errlen, + "failed to initialize DWARF: %s\n", + dwarf_errmsg(derr)); + *errp = ECTF_CONVBKERR; + return (CTF_CONV_ERROR); + } + + /* + * Iterate over all of the compilation units and create a ctf_cu_t for + * each of them. This is used to determine if we have zero, one, or + * multiple dies to convert. If we have zero, that's an error. If + * there's only one die, that's the simple case. No merge needed and + * only a single Dwarf_Debug as well. + */ + ndies = 0; + ret = ctf_dwarf_count_dies(dw, &derr, &ndies, errmsg, errlen); + if (ret != 0) { + *errp = ret; + goto out; + } + + (void) dwarf_finish(dw, &derr); + cdies = ctf_alloc(sizeof (ctf_cu_t) * ndies); + if (cdies == NULL) { + *errp = ENOMEM; + return (CTF_CONV_ERROR); + } + + for (i = 0; i < ndies; i++) { + cup = &cdies[i]; + ret = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, + &cup->cu_dwarf, &derr); + if (ret != 0) { + ctf_free(cdies, sizeof (ctf_cu_t) * ndies); + (void) snprintf(errmsg, errlen, + "failed to initialize DWARF: %s\n", + dwarf_errmsg(derr)); + *errp = ECTF_CONVBKERR; + return (CTF_CONV_ERROR); + } + + ret = ctf_dwarf_init_die(fd, elf, &cdies[i], i, errmsg, errlen); + if (ret != 0) { + *errp = ret; + goto out; + } + cup->cu_doweaks = ndies > 1 ? B_FALSE : B_TRUE; + } + + ctf_dprintf("found %d DWARF die(s)\n", ndies); + + /* + * If we only have one compilation unit, there's no reason to use + * multiple threads, even if the user requested them. After all, they + * just gave us an upper bound. + */ + if (ndies == 1) + nthrs = 1; + + if (workq_init(&wqp, nthrs) == -1) { + *errp = errno; + goto out; + } + + for (i = 0; i < ndies; i++) { + cup = &cdies[i]; + ctf_dprintf("adding die %s: %p, %x %x\n", cup->cu_name, + cup->cu_cu, cup->cu_cuoff, cup->cu_maxoff); + if (workq_add(wqp, cup) == -1) { + *errp = errno; + goto out; + } + } + + ret = workq_work(wqp, ctf_dwarf_convert_one, NULL, errp); + if (ret == WORKQ_ERROR) { + *errp = errno; + goto out; + } else if (ret == WORKQ_UERROR) { + ctf_dprintf("internal convert failed: %s\n", + ctf_errmsg(*errp)); + goto out; + } + + ctf_dprintf("Determining next phase: have %d dies\n", ndies); + if (ndies != 1) { + ctf_merge_t *cmp; + + cmp = ctf_merge_init(fd, &ret); + if (cmp == NULL) { + *errp = ret; + goto out; + } + + ctf_dprintf("setting threads\n"); + if ((ret = ctf_merge_set_nthreads(cmp, nthrs)) != 0) { + ctf_merge_fini(cmp); + *errp = ret; + goto out; + } + + ctf_dprintf("adding dies\n"); + for (i = 0; i < ndies; i++) { + cup = &cdies[i]; + if ((ret = ctf_merge_add(cmp, cup->cu_ctfp)) != 0) { + ctf_merge_fini(cmp); + *errp = ret; + goto out; + } + } + + ctf_dprintf("performing merge\n"); + ret = ctf_merge_merge(cmp, fpp); + if (ret != 0) { + ctf_dprintf("failed merge!\n"); + *fpp = NULL; + ctf_merge_fini(cmp); + *errp = ret; + goto out; + } + ctf_merge_fini(cmp); + *errp = 0; + ctf_dprintf("successfully converted!\n"); + } else { + *errp = 0; + *fpp = cdies->cu_ctfp; + cdies->cu_ctfp = NULL; + ctf_dprintf("successfully converted!\n"); + } + +out: + workq_fini(wqp); + ctf_dwarf_free_dies(cdies, ndies); + return (*fpp != NULL ? CTF_CONV_SUCCESS : CTF_CONV_ERROR); +} diff --git a/usr/src/lib/libctf/common/ctf_elfwrite.c b/usr/src/lib/libctf/common/ctf_elfwrite.c new file mode 100644 index 0000000000..7f668fe528 --- /dev/null +++ b/usr/src/lib/libctf/common/ctf_elfwrite.c @@ -0,0 +1,422 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Routines for writing ctf data to elf files. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int +ctf_write_elf(ctf_file_t *fp, Elf *src, Elf *dst, int flags) +{ + GElf_Ehdr sehdr, dehdr; + Elf_Scn *sscn, *dscn; + Elf_Data *sdata, *ddata; + GElf_Shdr shdr; + int symtab_idx = -1; + off_t new_offset = 0; + off_t ctfnameoff = 0; + int compress = (flags & CTF_ELFWRITE_F_COMPRESS); + int *secxlate = NULL; + int srcidx, dstidx, pad, i; + int curnmoff = 0; + int changing = 0; + int ret; + size_t nshdr, nphdr, strndx; + void *strdatabuf = NULL, *symdatabuf = NULL; + size_t strdatasz = 0, symdatasz = 0; + + void *cdata = NULL; + size_t elfsize, asize; + + if ((flags & ~(CTF_ELFWRITE_F_COMPRESS)) != 0) { + ret = ctf_set_errno(fp, EINVAL); + goto out; + } + + if (gelf_newehdr(dst, gelf_getclass(src)) == NULL) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + if (gelf_getehdr(src, &sehdr) == NULL) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + (void) memcpy(&dehdr, &sehdr, sizeof (GElf_Ehdr)); + if (gelf_update_ehdr(dst, &dehdr) == 0) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + + /* + * Use libelf to get the number of sections and the string section to + * deal with ELF files that may have a large number of sections. We just + * always use this to make our live easier. + */ + if (elf_getphdrnum(src, &nphdr) != 0) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + if (elf_getshdrnum(src, &nshdr) != 0) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + if (elf_getshdrstrndx(src, &strndx) != 0) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + + /* + * Neither the existing debug sections nor the SUNW_ctf sections (new or + * existing) are SHF_ALLOC'd, so they won't be in areas referenced by + * program headers. As such, we can just blindly copy the program + * headers from the existing file to the new file. + */ + if (nphdr != 0) { + (void) elf_flagelf(dst, ELF_C_SET, ELF_F_LAYOUT); + if (gelf_newphdr(dst, nphdr) == NULL) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + + for (i = 0; i < nphdr; i++) { + GElf_Phdr phdr; + + if (gelf_getphdr(src, i, &phdr) == NULL) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + if (gelf_update_phdr(dst, i, &phdr) == 0) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + } + } + + secxlate = ctf_alloc(sizeof (int) * nshdr); + for (srcidx = dstidx = 0; srcidx < nshdr; srcidx++) { + Elf_Scn *scn = elf_getscn(src, srcidx); + GElf_Shdr shdr; + char *sname; + + if (gelf_getshdr(scn, &shdr) == NULL) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + sname = elf_strptr(src, strndx, shdr.sh_name); + if (sname == NULL) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + + if (strcmp(sname, CTF_ELF_SCN_NAME) == 0) { + secxlate[srcidx] = -1; + } else { + secxlate[srcidx] = dstidx++; + curnmoff += strlen(sname) + 1; + } + + new_offset = (off_t)dehdr.e_phoff; + } + + for (srcidx = 1; srcidx < nshdr; srcidx++) { + char *sname; + + sscn = elf_getscn(src, srcidx); + if (gelf_getshdr(sscn, &shdr) == NULL) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + + if (secxlate[srcidx] == -1) { + changing = 1; + continue; + } + + dscn = elf_newscn(dst); + if (dscn == NULL) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + + /* + * If this file has program headers, we need to explicitly lay + * out sections. If none of the sections prior to this one have + * been removed, then we can just use the existing location. If + * one or more sections have been changed, then we need to + * adjust this one to avoid holes. + */ + if (changing && nphdr != 0) { + pad = new_offset % shdr.sh_addralign; + + if (pad != 0) + new_offset += shdr.sh_addralign - pad; + shdr.sh_offset = new_offset; + } + + shdr.sh_link = secxlate[shdr.sh_link]; + + if (shdr.sh_type == SHT_REL || shdr.sh_type == SHT_RELA) + shdr.sh_info = secxlate[shdr.sh_info]; + + sname = elf_strptr(src, strndx, shdr.sh_name); + if (sname == NULL) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + if ((sdata = elf_getdata(sscn, NULL)) == NULL) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + if ((ddata = elf_newdata(dscn)) == NULL) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + bcopy(sdata, ddata, sizeof (Elf_Data)); + + if (srcidx == strndx) { + char seclen = strlen(CTF_ELF_SCN_NAME); + + strdatasz = ddata->d_size + shdr.sh_size + + seclen + 1; + ddata->d_buf = strdatabuf = ctf_alloc(strdatasz); + if (ddata->d_buf == NULL) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + bcopy(sdata->d_buf, ddata->d_buf, shdr.sh_size); + (void) strcpy((caddr_t)ddata->d_buf + shdr.sh_size, + CTF_ELF_SCN_NAME); + ctfnameoff = (off_t)shdr.sh_size; + shdr.sh_size += seclen + 1; + ddata->d_size += seclen + 1; + + if (nphdr != 0) + changing = 1; + } + + if (shdr.sh_type == SHT_SYMTAB && shdr.sh_entsize != 0) { + int nsym = shdr.sh_size / shdr.sh_entsize; + + symtab_idx = secxlate[srcidx]; + + symdatasz = shdr.sh_size; + ddata->d_buf = symdatabuf = ctf_alloc(symdatasz); + if (ddata->d_buf == NULL) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + (void) bcopy(sdata->d_buf, ddata->d_buf, shdr.sh_size); + + for (i = 0; i < nsym; i++) { + GElf_Sym sym; + short newscn; + + (void) gelf_getsym(ddata, i, &sym); + + if (sym.st_shndx >= SHN_LORESERVE) + continue; + + if ((newscn = secxlate[sym.st_shndx]) != + sym.st_shndx) { + sym.st_shndx = + (newscn == -1 ? 1 : newscn); + + if (gelf_update_sym(ddata, i, &sym) == + 0) { + ret = ctf_set_errno(fp, + ECTF_ELF); + goto out; + } + } + } + } + + if (gelf_update_shdr(dscn, &shdr) == NULL) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + + new_offset = (off_t)shdr.sh_offset; + if (shdr.sh_type != SHT_NOBITS) + new_offset += shdr.sh_size; + } + + if (symtab_idx == -1) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + + /* Add the ctf section */ + if ((dscn = elf_newscn(dst)) == NULL) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + if (gelf_getshdr(dscn, &shdr) == NULL) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + shdr.sh_name = ctfnameoff; + shdr.sh_type = SHT_PROGBITS; + shdr.sh_size = fp->ctf_size; + shdr.sh_link = symtab_idx; + shdr.sh_addralign = 4; + if (changing && nphdr != 0) { + pad = new_offset % shdr.sh_addralign; + + if (pad) + new_offset += shdr.sh_addralign - pad; + + shdr.sh_offset = new_offset; + new_offset += shdr.sh_size; + } + + if ((ddata = elf_newdata(dscn)) == NULL) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + + if (compress != 0) { + int err; + + if (ctf_zopen(&err) == NULL) { + ret = ctf_set_errno(fp, err); + goto out; + } + + if ((err = ctf_compress(fp, &cdata, &asize, &elfsize)) != 0) { + ret = ctf_set_errno(fp, err); + goto out; + } + ddata->d_buf = cdata; + ddata->d_size = elfsize; + } else { + ddata->d_buf = (void *)fp->ctf_base; + ddata->d_size = fp->ctf_size; + } + ddata->d_align = shdr.sh_addralign; + + if (gelf_update_shdr(dscn, &shdr) == 0) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + + /* update the section header location */ + if (nphdr != 0) { + size_t align = gelf_fsize(dst, ELF_T_ADDR, 1, EV_CURRENT); + size_t r = new_offset % align; + + if (r) + new_offset += align - r; + + dehdr.e_shoff = new_offset; + } + + /* commit to disk */ + if (sehdr.e_shstrndx == SHN_XINDEX) + dehdr.e_shstrndx = SHN_XINDEX; + else + dehdr.e_shstrndx = secxlate[sehdr.e_shstrndx]; + if (gelf_update_ehdr(dst, &dehdr) == NULL) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + if (elf_update(dst, ELF_C_WRITE) < 0) { + ret = ctf_set_errno(fp, ECTF_ELF); + goto out; + } + + ret = 0; + +out: + if (strdatabuf != NULL) + ctf_free(strdatabuf, strdatasz); + if (symdatabuf != NULL) + ctf_free(symdatabuf, symdatasz); + if (cdata != NULL) + ctf_data_free(cdata, fp->ctf_size); + if (secxlate != NULL) + ctf_free(secxlate, sizeof (int) * nshdr); + + return (ret); +} + +int +ctf_elffdwrite(ctf_file_t *fp, int ifd, int ofd, int flags) +{ + int ret; + Elf *ielf, *oelf; + + (void) elf_version(EV_CURRENT); + if ((ielf = elf_begin(ifd, ELF_C_READ, NULL)) == NULL) + return (ctf_set_errno(fp, ECTF_ELF)); + + if ((oelf = elf_begin(ofd, ELF_C_WRITE, NULL)) == NULL) + return (ctf_set_errno(fp, ECTF_ELF)); + + ret = ctf_write_elf(fp, ielf, oelf, flags); + + (void) elf_end(ielf); + (void) elf_end(oelf); + + return (ret); +} + +int +ctf_elfwrite(ctf_file_t *fp, const char *input, const char *output, int flags) +{ + struct stat st; + int ifd, ofd, ret; + + if ((ifd = open(input, O_RDONLY)) < 0) + return (ctf_set_errno(fp, errno)); + + if (fstat(ifd, &st) < 0) + return (ctf_set_errno(fp, errno)); + + if ((ofd = open(output, O_RDWR | O_CREAT | O_TRUNC, st.st_mode)) < 0) + return (ctf_set_errno(fp, errno)); + + ret = ctf_elffdwrite(fp, ifd, ofd, flags); + + if (close(ifd) != 0 && ret == 0) + ret = ctf_set_errno(fp, errno); + if (close(ofd) != 0 && ret == 0) + ret = ctf_set_errno(fp, errno); + + return (ret); +} diff --git a/usr/src/lib/libctf/common/ctf_lib.c b/usr/src/lib/libctf/common/ctf_lib.c index e71ebc6d9d..e183b15f52 100644 --- a/usr/src/lib/libctf/common/ctf_lib.c +++ b/usr/src/lib/libctf/common/ctf_lib.c @@ -23,6 +23,9 @@ * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2015, Joyent, Inc. + */ #include #include @@ -33,6 +36,8 @@ #include #include #include +#include +#include #ifdef _LP64 static const char *_libctf_zlib = "/usr/lib/64/libz.so.1"; @@ -42,6 +47,9 @@ static const char *_libctf_zlib = "/usr/lib/libz.so.1"; static struct { int (*z_uncompress)(uchar_t *, ulong_t *, const uchar_t *, ulong_t); + int (*z_initcomp)(z_stream *, int, const char *, int); + int (*z_compress)(z_stream *, int); + int (*z_finicomp)(z_stream *); const char *(*z_error)(int); void *z_dlp; } zlib; @@ -49,6 +57,18 @@ static struct { static size_t _PAGESIZE; static size_t _PAGEMASK; +static uint64_t ctf_phase = 0; + +#define CTF_COMPRESS_CHUNK (64*1024) + +typedef struct ctf_zdata { + void *czd_buf; + void *czd_next; + ctf_file_t *czd_ctfp; + size_t czd_allocsz; + z_stream czd_zstr; +} ctf_zdata_t; + #pragma init(_libctf_init) void _libctf_init(void) @@ -84,9 +104,14 @@ ctf_zopen(int *errp) return (ctf_set_open_errno(errp, ECTF_ZINIT)); zlib.z_uncompress = (int (*)()) dlsym(zlib.z_dlp, "uncompress"); + zlib.z_initcomp = (int (*)()) dlsym(zlib.z_dlp, "deflateInit_"); + zlib.z_compress = (int (*)()) dlsym(zlib.z_dlp, "deflate"); + zlib.z_finicomp = (int (*)()) dlsym(zlib.z_dlp, "deflateEnd"); zlib.z_error = (const char *(*)()) dlsym(zlib.z_dlp, "zError"); - if (zlib.z_uncompress == NULL || zlib.z_error == NULL) { + if (zlib.z_uncompress == NULL || zlib.z_error == NULL || + zlib.z_initcomp == NULL|| zlib.z_compress == NULL || + zlib.z_finicomp == NULL) { (void) dlclose(zlib.z_dlp); bzero(&zlib, sizeof (zlib)); return (ctf_set_open_errno(errp, ECTF_ZINIT)); @@ -111,6 +136,206 @@ z_strerror(int err) return (zlib.z_error(err)); } +static int +ctf_zdata_init(ctf_zdata_t *czd, ctf_file_t *fp) +{ + ctf_header_t *cthp; + + bzero(czd, sizeof (ctf_zdata_t)); + + czd->czd_allocsz = fp->ctf_size; + czd->czd_buf = ctf_data_alloc(czd->czd_allocsz); + if (czd->czd_buf == MAP_FAILED) + return (ctf_set_errno(fp, ENOMEM)); + + bcopy(fp->ctf_base, czd->czd_buf, sizeof (ctf_header_t)); + czd->czd_ctfp = fp; + cthp = czd->czd_buf; + cthp->cth_flags |= CTF_F_COMPRESS; + czd->czd_next = (void *)((uintptr_t)czd->czd_buf + + sizeof (ctf_header_t)); + + if (zlib.z_initcomp(&czd->czd_zstr, Z_BEST_COMPRESSION, + ZLIB_VERSION, sizeof (z_stream)) != Z_OK) + return (ctf_set_errno(fp, ECTF_ZLIB)); + + return (0); +} + +static int +ctf_zdata_grow(ctf_zdata_t *czd) +{ + size_t off; + size_t newsz; + void *ndata; + + off = (uintptr_t)czd->czd_next - (uintptr_t)czd->czd_buf; + newsz = czd->czd_allocsz + CTF_COMPRESS_CHUNK; + ndata = ctf_data_alloc(newsz); + if (ndata == MAP_FAILED) { + return (ctf_set_errno(czd->czd_ctfp, ENOMEM)); + } + + bcopy(czd->czd_buf, ndata, off); + ctf_data_free(czd->czd_buf, czd->czd_allocsz); + czd->czd_allocsz = newsz; + czd->czd_buf = ndata; + czd->czd_next = (void *)((uintptr_t)ndata + off); + + czd->czd_zstr.next_out = (Bytef *)czd->czd_next; + czd->czd_zstr.avail_out = CTF_COMPRESS_CHUNK; + return (0); +} + +static int +ctf_zdata_compress_buffer(ctf_zdata_t *czd, const void *buf, size_t bufsize) +{ + int err; + + czd->czd_zstr.next_out = czd->czd_next; + czd->czd_zstr.avail_out = czd->czd_allocsz - + ((uintptr_t)czd->czd_next - (uintptr_t)czd->czd_buf); + czd->czd_zstr.next_in = (Bytef *)buf; + czd->czd_zstr.avail_in = bufsize; + + while (czd->czd_zstr.avail_in != 0) { + if (czd->czd_zstr.avail_out == 0) { + czd->czd_next = czd->czd_zstr.next_out; + if ((err = ctf_zdata_grow(czd)) != 0) { + return (err); + } + } + + if ((err = zlib.z_compress(&czd->czd_zstr, Z_NO_FLUSH)) != Z_OK) + return (ctf_set_errno(czd->czd_ctfp, ECTF_ZLIB)); + } + czd->czd_next = czd->czd_zstr.next_out; + + return (0); +} + +static int +ctf_zdata_flush(ctf_zdata_t *czd, boolean_t finish) +{ + int err; + int flag = finish == B_TRUE ? Z_FINISH : Z_FULL_FLUSH; + int bret = finish == B_TRUE ? Z_STREAM_END : Z_BUF_ERROR; + + for (;;) { + if (czd->czd_zstr.avail_out == 0) { + czd->czd_next = czd->czd_zstr.next_out; + if ((err = ctf_zdata_grow(czd)) != 0) { + return (err); + } + } + + err = zlib.z_compress(&czd->czd_zstr, flag); + if (err == bret) { + break; + } + if (err != Z_OK) + return (ctf_set_errno(czd->czd_ctfp, ECTF_ZLIB)); + + } + + czd->czd_next = czd->czd_zstr.next_out; + + return (0); +} + +static int +ctf_zdata_end(ctf_zdata_t *czd) +{ + int ret; + + if ((ret = ctf_zdata_flush(czd, B_TRUE)) != 0) + return (ret); + + if ((ret = zlib.z_finicomp(&czd->czd_zstr)) != 0) + return (ctf_set_errno(czd->czd_ctfp, ECTF_ZLIB)); + + return (0); +} + +static void +ctf_zdata_cleanup(ctf_zdata_t *czd) +{ + ctf_data_free(czd->czd_buf, czd->czd_allocsz); + (void) zlib.z_finicomp(&czd->czd_zstr); +} + +/* + * Compress our CTF data and return both the size of the compressed data and the + * size of the allocation. These may be different due to the nature of + * compression. + * + * In addition, we flush the compression between our two phases such that we + * maintain a different dictionary between the CTF data and the string section. + */ +int +ctf_compress(ctf_file_t *fp, void **buf, size_t *allocsz, size_t *elfsize) +{ + int err; + ctf_zdata_t czd; + ctf_header_t *cthp = (ctf_header_t *)fp->ctf_base; + + if ((err = ctf_zdata_init(&czd, fp)) != 0) + return (err); + + if ((err = ctf_zdata_compress_buffer(&czd, fp->ctf_buf, + cthp->cth_stroff)) != 0) { + ctf_zdata_cleanup(&czd); + return (err); + } + + if ((err = ctf_zdata_flush(&czd, B_FALSE)) != 0) { + ctf_zdata_cleanup(&czd); + return (err); + } + + if ((err = ctf_zdata_compress_buffer(&czd, + fp->ctf_buf + cthp->cth_stroff, cthp->cth_strlen)) != 0) { + ctf_zdata_cleanup(&czd); + return (err); + } + + if ((err = ctf_zdata_end(&czd)) != 0) { + ctf_zdata_cleanup(&czd); + return (err); + } + + *buf = czd.czd_buf; + *allocsz = czd.czd_allocsz; + *elfsize = (uintptr_t)czd.czd_next - (uintptr_t)czd.czd_buf; + + return (0); +} + +int +z_compress(void *dst, size_t *dstlen, const void *src, size_t srclen) +{ + z_stream zs; + int err; + + bzero(&zs, sizeof (z_stream)); + zs.next_in = (uchar_t *)src; + zs.avail_in = srclen; + zs.next_out = dst; + zs.avail_out = *dstlen; + + if ((err = zlib.z_initcomp(&zs, Z_BEST_COMPRESSION, ZLIB_VERSION, + sizeof (z_stream))) != Z_OK) + return (err); + + if ((err = zlib.z_compress(&zs, Z_FINISH)) != Z_STREAM_END) { + (void) zlib.z_finicomp(&zs); + return (err == Z_OK ? Z_BUF_ERROR : err); + } + + *dstlen = zs.total_out; + return (zlib.z_finicomp(&zs)); +} + /* * Convert a 32-bit ELF file header into GElf. */ @@ -189,7 +414,7 @@ ctf_sect_munmap(const ctf_sect_t *sp) * responsible for closing the file descriptor when it is no longer needed. */ ctf_file_t * -ctf_fdopen(int fd, int *errp) +ctf_fdcreate_int(int fd, int *errp, ctf_sect_t *ctfp) { ctf_sect_t ctfsect, symsect, strsect; ctf_file_t *fp = NULL; @@ -221,6 +446,9 @@ ctf_fdopen(int fd, int *errp) */ if (nbytes >= sizeof (ctf_preamble_t) && hdr.ctf.ctp_magic == CTF_MAGIC) { + if (ctfp != NULL) + return (ctf_set_open_errno(errp, EINVAL)); + if (hdr.ctf.ctp_version > CTF_VERSION) return (ctf_set_open_errno(errp, ECTF_CTFVERS)); @@ -370,7 +598,8 @@ ctf_fdopen(int fd, int *errp) continue; /* corrupt sh_name field */ if (shp->sh_type == SHT_PROGBITS && - strcmp(strs + shp->sh_name, _CTF_SECTION) == 0) { + strcmp(strs + shp->sh_name, _CTF_SECTION) == 0 && + ctfp == NULL) { ctfsect.cts_name = strs + shp->sh_name; ctfsect.cts_type = shp->sh_type; ctfsect.cts_flags = shp->sh_flags; @@ -397,18 +626,22 @@ ctf_fdopen(int fd, int *errp) free(sp); /* free section header array */ - if (ctfsect.cts_type == SHT_NULL) { - (void) munmap(strs_map, strs_mapsz); - return (ctf_set_open_errno(errp, ECTF_NOCTFDATA)); - } + if (ctfp == NULL) { + if (ctfsect.cts_type == SHT_NULL && ctfp == NULL) { + (void) munmap(strs_map, strs_mapsz); + return (ctf_set_open_errno(errp, + ECTF_NOCTFDATA)); + } - /* - * Now mmap the CTF data, symtab, and strtab sections and - * call ctf_bufopen() to do the rest of the work. - */ - if (ctf_sect_mmap(&ctfsect, fd) == MAP_FAILED) { - (void) munmap(strs_map, strs_mapsz); - return (ctf_set_open_errno(errp, ECTF_MMAP)); + /* + * Now mmap the CTF data, symtab, and strtab sections + * and call ctf_bufopen() to do the rest of the work. + */ + if (ctf_sect_mmap(&ctfsect, fd) == MAP_FAILED) { + (void) munmap(strs_map, strs_mapsz); + return (ctf_set_open_errno(errp, ECTF_MMAP)); + } + ctfp = &ctfsect; } if (symsect.cts_type != SHT_NULL && @@ -418,12 +651,13 @@ ctf_fdopen(int fd, int *errp) (void) ctf_set_open_errno(errp, ECTF_MMAP); goto bad; /* unmap all and abort */ } - fp = ctf_bufopen(&ctfsect, &symsect, &strsect, errp); + fp = ctf_bufopen(ctfp, &symsect, &strsect, errp); } else - fp = ctf_bufopen(&ctfsect, NULL, NULL, errp); + fp = ctf_bufopen(ctfp, NULL, NULL, errp); bad: if (fp == NULL) { - ctf_sect_munmap(&ctfsect); + if (ctfp == NULL) + ctf_sect_munmap(&ctfsect); ctf_sect_munmap(&symsect); ctf_sect_munmap(&strsect); } else @@ -436,6 +670,12 @@ bad: return (ctf_set_open_errno(errp, ECTF_FMT)); } +ctf_file_t * +ctf_fdopen(int fd, int *errp) +{ + return (ctf_fdcreate_int(fd, errp, NULL)); +} + /* * Open the specified file and return a pointer to a CTF container. The file * can be either an ELF file or raw CTF file. This is just a convenient @@ -502,3 +742,25 @@ ctf_version(int version) return (_libctf_version); } + +/* + * A utility function for folks debugging CTF conversion and merging. + */ +void +ctf_phase_dump(ctf_file_t *fp, const char *phase) +{ + int fd; + static char *base; + char path[MAXPATHLEN]; + + if (base == NULL && (base = getenv("LIBCTF_WRITE_PHASES")) == NULL) + return; + + (void) snprintf(path, sizeof (path), "%s/libctf.%s.%d.ctf", base, + phase != NULL ? phase : "", + ctf_phase); + if ((fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0777)) < 0) + return; + (void) ctf_write(fp, fd); + (void) close(fd); +} diff --git a/usr/src/lib/libctf/common/ctf_merge.c b/usr/src/lib/libctf/common/ctf_merge.c new file mode 100644 index 0000000000..c93a2a4f7c --- /dev/null +++ b/usr/src/lib/libctf/common/ctf_merge.c @@ -0,0 +1,1551 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015 Joyent, Inc. + */ + +/* + * To perform a merge of two CTF containers, we first diff the two containers + * types. For every type that's in the src container, but not in the dst + * container, we note it and add it to dst container. If there are any objects + * or functions associated with src, we go through and update the types that + * they refer to such that they all refer to types in the dst container. + * + * The bulk of the logic for the merge, after we've run the diff, occurs in + * ctf_merge_common(). + * + * In terms of exported APIs, we don't really export a simple merge two + * containers, as the general way this is used, in something like ctfmerge(1), + * is to add all the containers and then let us figure out the best way to merge + * it. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct ctf_merge_tinfo { + uint16_t cmt_map; /* Map to the type in out */ + boolean_t cmt_fixup; + boolean_t cmt_forward; + boolean_t cmt_missing; +} ctf_merge_tinfo_t; + +/* + * State required for doing an individual merge of two containers. + */ +typedef struct ctf_merge_types { + ctf_file_t *cm_out; /* Output CTF file */ + ctf_file_t *cm_src; /* Input CTF file */ + ctf_merge_tinfo_t *cm_tmap; /* Type state information */ + boolean_t cm_dedup; /* Are we doing a dedup? */ + boolean_t cm_unique; /* are we doing a uniquify? */ +} ctf_merge_types_t; + +typedef struct ctf_merge_objmap { + list_node_t cmo_node; + const char *cmo_name; /* Symbol name */ + ulong_t cmo_idx; /* Symbol ID */ + ctf_id_t cmo_tid; /* Type ID */ +} ctf_merge_objmap_t; + +typedef struct ctf_merge_funcmap { + list_node_t cmf_node; + const char *cmf_name; /* Symbol name */ + ulong_t cmf_idx; /* Symbol ID */ + ctf_id_t cmf_rtid; /* Type ID */ + uint_t cmf_flags; /* ctf_funcinfo_t ctc_flags */ + uint_t cmf_argc; /* Number of arguments */ + ctf_id_t cmf_args[]; /* Types of arguments */ +} ctf_merge_funcmap_t; + +typedef struct ctf_merge_input { + list_node_t cmi_node; + ctf_file_t *cmi_input; + list_t cmi_omap; + list_t cmi_fmap; + boolean_t cmi_created; +} ctf_merge_input_t; + +struct ctf_merge_handle { + list_t cmh_inputs; /* Input list */ + uint_t cmh_ninputs; /* Number of inputs */ + uint_t cmh_nthreads; /* Number of threads to use */ + ctf_file_t *cmh_unique; /* ctf to uniquify against */ + boolean_t cmh_msyms; /* Should we merge symbols/funcs? */ + int cmh_ofd; /* FD for output file */ + int cmh_flags; /* Flags that control merge behavior */ + char *cmh_label; /* Optional label */ + char *cmh_pname; /* Parent name */ +}; + +static int ctf_merge_add_type(ctf_merge_types_t *, ctf_id_t); + +static ctf_id_t +ctf_merge_gettype(ctf_merge_types_t *cmp, ctf_id_t id) +{ + if (cmp->cm_dedup == B_FALSE) { + VERIFY(cmp->cm_tmap[id].cmt_map != 0); + return (cmp->cm_tmap[id].cmt_map); + } + + while (cmp->cm_tmap[id].cmt_missing == B_FALSE) { + VERIFY(cmp->cm_tmap[id].cmt_map != 0); + id = cmp->cm_tmap[id].cmt_map; + } + VERIFY(cmp->cm_tmap[id].cmt_map != 0); + return (cmp->cm_tmap[id].cmt_map); +} + +static void +ctf_merge_diffcb(ctf_file_t *ifp, ctf_id_t iid, boolean_t same, ctf_file_t *ofp, + ctf_id_t oid, void *arg) +{ + ctf_merge_types_t *cmp = arg; + ctf_merge_tinfo_t *cmt = cmp->cm_tmap; + + if (same == B_TRUE) { + if (ctf_type_kind(ifp, iid) == CTF_K_FORWARD && + ctf_type_kind(ofp, oid) != CTF_K_FORWARD) { + VERIFY(cmt[oid].cmt_map == 0); + + /* + * If we're uniquifying types, it's possible for the + * container that we're uniquifying against to have a + * forward which exists in the container being reduced. + * For example, genunix has the machcpu structure as a + * forward which is actually in unix and we uniquify + * unix against genunix. In such cases, we explicitly do + * not do any mapping of the forward information, lest + * we risk losing the real definition. Instead, mark + * that it's missing. + */ + if (cmp->cm_unique == B_TRUE) { + cmt[oid].cmt_missing = B_TRUE; + return; + } + + cmt[oid].cmt_map = iid; + cmt[oid].cmt_forward = B_TRUE; + ctf_dprintf("merge diff forward mapped %d->%d\n", oid, + iid); + return; + } + + /* + * We could have multiple things that a given type ends up + * matching in the world of forwards and pointers to forwards. + * For now just take the first one... + */ + if (cmt[oid].cmt_map != 0) + return; + cmt[oid].cmt_map = iid; + ctf_dprintf("merge diff mapped %d->%d\n", oid, iid); + } else if (ifp == cmp->cm_src) { + VERIFY(cmt[iid].cmt_map == 0); + cmt[iid].cmt_missing = B_TRUE; + ctf_dprintf("merge diff said %d is missing\n", iid); + } +} + +static int +ctf_merge_add_number(ctf_merge_types_t *cmp, ctf_id_t id) +{ + int ret, flags; + const ctf_type_t *tp; + const char *name; + ctf_encoding_t en; + + if (ctf_type_encoding(cmp->cm_src, id, &en) != 0) + return (CTF_ERR); + + tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id); + name = ctf_strraw(cmp->cm_src, tp->ctt_name); + if (CTF_INFO_ISROOT(tp->ctt_info) != 0) + flags = CTF_ADD_ROOT; + else + flags = CTF_ADD_NONROOT; + + ret = ctf_add_encoded(cmp->cm_out, flags, name, &en, + ctf_type_kind(cmp->cm_src, id)); + + if (ret == CTF_ERR) + return (ret); + + VERIFY(cmp->cm_tmap[id].cmt_map == 0); + cmp->cm_tmap[id].cmt_map = ret; + return (0); +} + +static int +ctf_merge_add_array(ctf_merge_types_t *cmp, ctf_id_t id) +{ + int ret, flags; + const ctf_type_t *tp; + ctf_arinfo_t ar; + + if (ctf_array_info(cmp->cm_src, id, &ar) == CTF_ERR) + return (CTF_ERR); + + tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id); + if (CTF_INFO_ISROOT(tp->ctt_info) != 0) + flags = CTF_ADD_ROOT; + else + flags = CTF_ADD_NONROOT; + + if (cmp->cm_tmap[ar.ctr_contents].cmt_map == 0) { + ret = ctf_merge_add_type(cmp, ar.ctr_contents); + if (ret != 0) + return (ret); + ASSERT(cmp->cm_tmap[ar.ctr_contents].cmt_map != 0); + } + ar.ctr_contents = ctf_merge_gettype(cmp, ar.ctr_contents); + + if (cmp->cm_tmap[ar.ctr_index].cmt_map == 0) { + ret = ctf_merge_add_type(cmp, ar.ctr_index); + if (ret != 0) + return (ret); + ASSERT(cmp->cm_tmap[ar.ctr_index].cmt_map != 0); + } + ar.ctr_index = ctf_merge_gettype(cmp, ar.ctr_index); + + ret = ctf_add_array(cmp->cm_out, flags, &ar); + if (ret == CTF_ERR) + return (ret); + + VERIFY(cmp->cm_tmap[id].cmt_map == 0); + cmp->cm_tmap[id].cmt_map = ret; + + return (0); +} + +static int +ctf_merge_add_reftype(ctf_merge_types_t *cmp, ctf_id_t id) +{ + int ret, flags; + const ctf_type_t *tp; + ctf_id_t reftype; + const char *name; + + tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id); + name = ctf_strraw(cmp->cm_src, tp->ctt_name); + if (CTF_INFO_ISROOT(tp->ctt_info) != 0) + flags = CTF_ADD_ROOT; + else + flags = CTF_ADD_NONROOT; + + reftype = ctf_type_reference(cmp->cm_src, id); + if (reftype == CTF_ERR) + return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src))); + + if (cmp->cm_tmap[reftype].cmt_map == 0) { + ret = ctf_merge_add_type(cmp, reftype); + if (ret != 0) + return (ret); + ASSERT(cmp->cm_tmap[reftype].cmt_map != 0); + } + reftype = ctf_merge_gettype(cmp, reftype); + + ret = ctf_add_reftype(cmp->cm_out, flags, name, reftype, + ctf_type_kind(cmp->cm_src, id)); + if (ret == CTF_ERR) + return (ret); + + VERIFY(cmp->cm_tmap[id].cmt_map == 0); + cmp->cm_tmap[id].cmt_map = ret; + return (0); +} + +static int +ctf_merge_add_typedef(ctf_merge_types_t *cmp, ctf_id_t id) +{ + int ret, flags; + const ctf_type_t *tp; + const char *name; + ctf_id_t reftype; + + tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id); + name = ctf_strraw(cmp->cm_src, tp->ctt_name); + if (CTF_INFO_ISROOT(tp->ctt_info) != 0) + flags = CTF_ADD_ROOT; + else + flags = CTF_ADD_NONROOT; + + reftype = ctf_type_reference(cmp->cm_src, id); + if (reftype == CTF_ERR) + return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src))); + + if (cmp->cm_tmap[reftype].cmt_map == 0) { + ret = ctf_merge_add_type(cmp, reftype); + if (ret != 0) + return (ret); + ASSERT(cmp->cm_tmap[reftype].cmt_map != 0); + } + reftype = ctf_merge_gettype(cmp, reftype); + + ret = ctf_add_typedef(cmp->cm_out, flags, name, reftype); + if (ret == CTF_ERR) + return (ret); + + VERIFY(cmp->cm_tmap[id].cmt_map == 0); + cmp->cm_tmap[id].cmt_map = ret; + return (0); +} + +typedef struct ctf_merge_enum { + ctf_file_t *cme_fp; + ctf_id_t cme_id; +} ctf_merge_enum_t; + +static int +ctf_merge_add_enumerator(const char *name, int value, void *arg) +{ + ctf_merge_enum_t *cmep = arg; + + return (ctf_add_enumerator(cmep->cme_fp, cmep->cme_id, name, value) == + CTF_ERR); +} + +static int +ctf_merge_add_enum(ctf_merge_types_t *cmp, ctf_id_t id) +{ + int flags; + const ctf_type_t *tp; + const char *name; + ctf_id_t enumid; + ctf_merge_enum_t cme; + + tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id); + name = ctf_strraw(cmp->cm_src, tp->ctt_name); + if (CTF_INFO_ISROOT(tp->ctt_info) != 0) + flags = CTF_ADD_ROOT; + else + flags = CTF_ADD_NONROOT; + + enumid = ctf_add_enum(cmp->cm_out, flags, name); + if (enumid == CTF_ERR) + return (enumid); + + cme.cme_fp = cmp->cm_out; + cme.cme_id = enumid; + if (ctf_enum_iter(cmp->cm_src, id, ctf_merge_add_enumerator, + &cme) != 0) + return (CTF_ERR); + + VERIFY(cmp->cm_tmap[id].cmt_map == 0); + cmp->cm_tmap[id].cmt_map = enumid; + return (0); +} + +static int +ctf_merge_add_func(ctf_merge_types_t *cmp, ctf_id_t id) +{ + int ret, flags, i; + const ctf_type_t *tp; + ctf_funcinfo_t ctc; + ctf_id_t *argv; + + tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id); + if (CTF_INFO_ISROOT(tp->ctt_info) != 0) + flags = CTF_ADD_ROOT; + else + flags = CTF_ADD_NONROOT; + + if (ctf_func_info_by_id(cmp->cm_src, id, &ctc) == CTF_ERR) + return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src))); + + argv = ctf_alloc(sizeof (ctf_id_t) * ctc.ctc_argc); + if (argv == NULL) + return (ctf_set_errno(cmp->cm_out, ENOMEM)); + if (ctf_func_args_by_id(cmp->cm_src, id, ctc.ctc_argc, argv) == + CTF_ERR) { + ctf_free(argv, sizeof (ctf_id_t) * ctc.ctc_argc); + return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src))); + } + + if (cmp->cm_tmap[ctc.ctc_return].cmt_map == 0) { + ret = ctf_merge_add_type(cmp, ctc.ctc_return); + if (ret != 0) + return (ret); + ASSERT(cmp->cm_tmap[ctc.ctc_return].cmt_map != 0); + } + ctc.ctc_return = ctf_merge_gettype(cmp, ctc.ctc_return); + + for (i = 0; i < ctc.ctc_argc; i++) { + if (cmp->cm_tmap[argv[i]].cmt_map == 0) { + ret = ctf_merge_add_type(cmp, argv[i]); + if (ret != 0) + return (ret); + ASSERT(cmp->cm_tmap[argv[i]].cmt_map != 0); + } + argv[i] = ctf_merge_gettype(cmp, argv[i]); + } + + ret = ctf_add_funcptr(cmp->cm_out, flags, &ctc, argv); + ctf_free(argv, sizeof (ctf_id_t) * ctc.ctc_argc); + if (ret == CTF_ERR) + return (ret); + + VERIFY(cmp->cm_tmap[id].cmt_map == 0); + cmp->cm_tmap[id].cmt_map = ret; + return (0); +} + +static int +ctf_merge_add_forward(ctf_merge_types_t *cmp, ctf_id_t id) +{ + int ret, flags; + const ctf_type_t *tp; + const char *name; + + tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id); + name = ctf_strraw(cmp->cm_src, tp->ctt_name); + if (CTF_INFO_ISROOT(tp->ctt_info) != 0) + flags = CTF_ADD_ROOT; + else + flags = CTF_ADD_NONROOT; + + /* + * ctf_add_forward tries to check to see if a given forward already + * exists in one of its hash tables. If we're here then we know that we + * have a forward in a container that isn't present in another. + * Therefore, we choose a token hash table to satisfy the API choice + * here. + */ + ret = ctf_add_forward(cmp->cm_out, flags, name, CTF_K_STRUCT); + if (ret == CTF_ERR) + return (CTF_ERR); + + VERIFY(cmp->cm_tmap[id].cmt_map == 0); + cmp->cm_tmap[id].cmt_map = ret; + return (0); +} + +typedef struct ctf_merge_su { + ctf_merge_types_t *cms_cm; + ctf_id_t cms_id; +} ctf_merge_su_t; + +static int +ctf_merge_add_member(const char *name, ctf_id_t type, ulong_t offset, void *arg) +{ + ctf_merge_su_t *cms = arg; + + VERIFY(cms->cms_cm->cm_tmap[type].cmt_map != 0); + type = cms->cms_cm->cm_tmap[type].cmt_map; + + ctf_dprintf("Trying to add member %s to %d\n", name, cms->cms_id); + return (ctf_add_member(cms->cms_cm->cm_out, cms->cms_id, name, + type, offset) == CTF_ERR); +} + +/* + * During the first pass, we always add the generic structure and union but none + * of its members as they might not all have been mapped yet. Instead we just + * mark all structures and unions as needing to be fixed up. + */ +static int +ctf_merge_add_sou(ctf_merge_types_t *cmp, ctf_id_t id, boolean_t forward) +{ + int flags, kind; + const ctf_type_t *tp; + const char *name; + ctf_id_t suid; + + tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id); + name = ctf_strraw(cmp->cm_src, tp->ctt_name); + if (CTF_INFO_ISROOT(tp->ctt_info) != 0) + flags = CTF_ADD_ROOT; + else + flags = CTF_ADD_NONROOT; + kind = ctf_type_kind(cmp->cm_src, id); + + if (kind == CTF_K_STRUCT) + suid = ctf_add_struct(cmp->cm_out, flags, name); + else + suid = ctf_add_union(cmp->cm_out, flags, name); + + if (suid == CTF_ERR) + return (suid); + + /* + * If this is a forward reference then its mapping should already + * exist. + */ + if (forward == B_FALSE) { + VERIFY(cmp->cm_tmap[id].cmt_map == 0); + cmp->cm_tmap[id].cmt_map = suid; + ctf_dprintf("added sou \"%s\" as (%d) %d->%d\n", name, kind, id, + suid); + } else { + VERIFY(cmp->cm_tmap[id].cmt_map == suid); + } + cmp->cm_tmap[id].cmt_fixup = B_TRUE; + + return (0); +} + +static int +ctf_merge_add_type(ctf_merge_types_t *cmp, ctf_id_t id) +{ + int kind, ret; + + /* + * We may end up evaluating a type more than once as we may deal with it + * as we recursively evaluate some kind of reference and then we may see + * it normally. + */ + if (cmp->cm_tmap[id].cmt_map != 0) + return (0); + + kind = ctf_type_kind(cmp->cm_src, id); + switch (kind) { + case CTF_K_INTEGER: + case CTF_K_FLOAT: + ret = ctf_merge_add_number(cmp, id); + break; + case CTF_K_ARRAY: + ret = ctf_merge_add_array(cmp, id); + break; + case CTF_K_POINTER: + case CTF_K_VOLATILE: + case CTF_K_CONST: + case CTF_K_RESTRICT: + ret = ctf_merge_add_reftype(cmp, id); + break; + case CTF_K_TYPEDEF: + ret = ctf_merge_add_typedef(cmp, id); + break; + case CTF_K_ENUM: + ret = ctf_merge_add_enum(cmp, id); + break; + case CTF_K_FUNCTION: + ret = ctf_merge_add_func(cmp, id); + break; + case CTF_K_FORWARD: + ret = ctf_merge_add_forward(cmp, id); + break; + case CTF_K_STRUCT: + case CTF_K_UNION: + ret = ctf_merge_add_sou(cmp, id, B_FALSE); + break; + case CTF_K_UNKNOWN: + /* + * We don't add unknown types, and we later assert that nothing + * should reference them. + */ + return (0); + default: + abort(); + } + + return (ret); +} + +static int +ctf_merge_fixup_sou(ctf_merge_types_t *cmp, ctf_id_t id) +{ + ctf_dtdef_t *dtd; + ctf_merge_su_t cms; + ctf_id_t mapid; + ssize_t size; + + mapid = cmp->cm_tmap[id].cmt_map; + VERIFY(mapid != 0); + dtd = ctf_dtd_lookup(cmp->cm_out, mapid); + VERIFY(dtd != NULL); + + ctf_dprintf("Trying to fix up sou %d\n", id); + cms.cms_cm = cmp; + cms.cms_id = mapid; + if (ctf_member_iter(cmp->cm_src, id, ctf_merge_add_member, &cms) != 0) + return (CTF_ERR); + + if ((size = ctf_type_size(cmp->cm_src, id)) == CTF_ERR) + return (CTF_ERR); + if (ctf_set_size(cmp->cm_out, mapid, size) == CTF_ERR) + return (CTF_ERR); + + return (0); +} + +static int +ctf_merge_fixup_type(ctf_merge_types_t *cmp, ctf_id_t id) +{ + int kind, ret; + + kind = ctf_type_kind(cmp->cm_src, id); + switch (kind) { + case CTF_K_STRUCT: + case CTF_K_UNION: + ret = ctf_merge_fixup_sou(cmp, id); + break; + default: + VERIFY(0); + ret = CTF_ERR; + } + + return (ret); +} + +/* + * Now that we've successfully merged everything, we're going to clean + * up the merge type table. Traditionally if we had just two different + * files that we were working between, the types would be fully + * resolved. However, because we were comparing with ourself every step + * of the way and not our reduced self, we need to go through and update + * every mapped entry to what it now points to in the deduped file. + */ +static void +ctf_merge_fixup_dedup_map(ctf_merge_types_t *cmp) +{ + int i; + + for (i = 1; i < cmp->cm_src->ctf_typemax + 1; i++) { + ctf_id_t tid; + + /* + * Missing types always have their id updated to exactly what it + * should be. + */ + if (cmp->cm_tmap[i].cmt_missing == B_TRUE) { + VERIFY(cmp->cm_tmap[i].cmt_map != 0); + continue; + } + + tid = i; + while (cmp->cm_tmap[tid].cmt_missing == B_FALSE) { + VERIFY(cmp->cm_tmap[tid].cmt_map != 0); + tid = cmp->cm_tmap[tid].cmt_map; + } + VERIFY(cmp->cm_tmap[tid].cmt_map != 0); + cmp->cm_tmap[i].cmt_map = cmp->cm_tmap[tid].cmt_map; + } +} + + +/* + * We're going to do three passes over the containers. + * + * Pass 1 checks for forward references in the output container that we know + * exist in the source container. + * + * Pass 2 adds all the missing types from the source container. As part of this + * we may be adding a type as a forward reference that doesn't exist yet. + * Any types that we encounter in this form, we need to add to a third pass. + * + * Pass 3 is the fixup pass. Here we go through and find all the types that were + * missing in the first. + * + * Importantly, we *must* call ctf_update between the second and third pass, + * otherwise several of the libctf functions will not properly find the data in + * the container. If we're doing a dedup we also fix up the type mapping. + */ +static int +ctf_merge_common(ctf_merge_types_t *cmp) +{ + int ret, i; + + ctf_phase_dump(cmp->cm_src, "merge-common-src"); + ctf_phase_dump(cmp->cm_out, "merge-common-dest"); + + /* Pass 1 */ + for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) { + if (cmp->cm_tmap[i].cmt_forward == B_TRUE) { + ret = ctf_merge_add_sou(cmp, i, B_TRUE); + if (ret != 0) { + return (ret); + } + } + } + + /* Pass 2 */ + for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) { + if (cmp->cm_tmap[i].cmt_missing == B_TRUE) { + ret = ctf_merge_add_type(cmp, i); + if (ret != 0) { + ctf_dprintf("Failed to merge type %d\n", i); + return (ret); + } + } + } + + ret = ctf_update(cmp->cm_out); + if (ret != 0) + return (ret); + + if (cmp->cm_dedup == B_TRUE) { + ctf_merge_fixup_dedup_map(cmp); + } + + ctf_dprintf("Beginning merge pass 3\n"); + /* Pass 3 */ + for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) { + if (cmp->cm_tmap[i].cmt_fixup == B_TRUE) { + ret = ctf_merge_fixup_type(cmp, i); + if (ret != 0) + return (ret); + } + } + + if (cmp->cm_dedup == B_TRUE) { + ctf_merge_fixup_dedup_map(cmp); + } + + return (0); +} + +/* + * Uniquification is slightly different from a stock merge. For starters, we + * don't need to replace any forward references in the output. In this case + * though, the types that already exist are in a parent container to the empty + * output container. + */ +static int +ctf_merge_uniquify_types(ctf_merge_types_t *cmp) +{ + int i, ret; + + for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) { + if (cmp->cm_tmap[i].cmt_missing == B_FALSE) + continue; + ret = ctf_merge_add_type(cmp, i); + if (ret != 0) + return (ret); + } + + ret = ctf_update(cmp->cm_out); + if (ret != 0) + return (ret); + + for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) { + if (cmp->cm_tmap[i].cmt_fixup == B_FALSE) + continue; + ret = ctf_merge_fixup_type(cmp, i); + if (ret != 0) + return (ret); + } + + return (0); +} + +static int +ctf_merge_types_init(ctf_merge_types_t *cmp) +{ + cmp->cm_tmap = ctf_alloc(sizeof (ctf_merge_tinfo_t) * + (cmp->cm_src->ctf_typemax + 1)); + if (cmp->cm_tmap == NULL) + return (ctf_set_errno(cmp->cm_out, ENOMEM)); + bzero(cmp->cm_tmap, sizeof (ctf_merge_tinfo_t) * + (cmp->cm_src->ctf_typemax + 1)); + return (0); +} + +static void +ctf_merge_types_fini(ctf_merge_types_t *cmp) +{ + ctf_free(cmp->cm_tmap, sizeof (ctf_merge_tinfo_t) * + (cmp->cm_src->ctf_typemax + 1)); +} + +/* + * Merge the types contained inside of two input files. The second input file is + * always going to be the destination. We're guaranteed that it's always + * writeable. + */ +static int +ctf_merge_types(void *arg, void *arg2, void **outp, void *unsued) +{ + int ret; + ctf_merge_types_t cm; + ctf_diff_t *cdp; + ctf_merge_objmap_t *cmo; + ctf_merge_funcmap_t *cmf; + ctf_merge_input_t *scmi = arg; + ctf_merge_input_t *dcmi = arg2; + ctf_file_t *out = dcmi->cmi_input; + ctf_file_t *source = scmi->cmi_input; + + ctf_dprintf("merging %p->%p\n", source, out); + + if (!(out->ctf_flags & LCTF_RDWR)) + return (ctf_set_errno(out, ECTF_RDONLY)); + + if (ctf_getmodel(out) != ctf_getmodel(source)) + return (ctf_set_errno(out, ECTF_DMODEL)); + + if ((ret = ctf_diff_init(out, source, &cdp)) != 0) + return (ret); + + cm.cm_out = out; + cm.cm_src = source; + cm.cm_dedup = B_FALSE; + cm.cm_unique = B_FALSE; + ret = ctf_merge_types_init(&cm); + if (ret != 0) { + ctf_diff_fini(cdp); + return (ctf_set_errno(out, ret)); + } + + ret = ctf_diff_types(cdp, ctf_merge_diffcb, &cm); + if (ret != 0) + goto cleanup; + ret = ctf_merge_common(&cm); + ctf_dprintf("merge common returned with %d\n", ret); + if (ret == 0) { + ret = ctf_update(out); + ctf_dprintf("update returned with %d\n", ret); + } else { + goto cleanup; + } + + /* + * Now we need to fix up the object and function maps. + */ + for (cmo = list_head(&scmi->cmi_omap); cmo != NULL; + cmo = list_next(&scmi->cmi_omap, cmo)) { + if (cmo->cmo_tid == 0) + continue; + VERIFY(cm.cm_tmap[cmo->cmo_tid].cmt_map != 0); + cmo->cmo_tid = cm.cm_tmap[cmo->cmo_tid].cmt_map; + } + + for (cmf = list_head(&scmi->cmi_fmap); cmf != NULL; + cmf = list_next(&scmi->cmi_fmap, cmf)) { + int i; + + VERIFY(cm.cm_tmap[cmf->cmf_rtid].cmt_map != 0); + cmf->cmf_rtid = cm.cm_tmap[cmf->cmf_rtid].cmt_map; + for (i = 0; i < cmf->cmf_argc; i++) { + VERIFY(cm.cm_tmap[cmf->cmf_args[i]].cmt_map != 0); + cmf->cmf_args[i] = cm.cm_tmap[cmf->cmf_args[i]].cmt_map; + } + } + + /* + * Now that we've fixed things up, we need to give our function and + * object maps to the destination, such that it can continue to update + * them going forward. + */ + list_move_tail(&dcmi->cmi_fmap, &scmi->cmi_fmap); + list_move_tail(&dcmi->cmi_omap, &scmi->cmi_omap); + +cleanup: + if (ret == 0) + *outp = dcmi; + ctf_merge_types_fini(&cm); + ctf_diff_fini(cdp); + if (ret != 0) + return (ctf_errno(out)); + return (0); +} + +/* + * After performing a pass, we need to go through the object and function type + * maps and potentially fix them up based on the new maps that we haev. + */ +static void +ctf_merge_fixup_nontypes(ctf_merge_types_t *cmp, ctf_merge_input_t *cmi) +{ + ctf_merge_objmap_t *cmo; + ctf_merge_funcmap_t *cmf; + + for (cmo = list_head(&cmi->cmi_omap); cmo != NULL; + cmo = list_next(&cmi->cmi_omap, cmo)) { + if (cmo->cmo_tid == 0) + continue; + VERIFY(cmp->cm_tmap[cmo->cmo_tid].cmt_map != 0); + cmo->cmo_tid = cmp->cm_tmap[cmo->cmo_tid].cmt_map; + } + + for (cmf = list_head(&cmi->cmi_fmap); cmf != NULL; + cmf = list_next(&cmi->cmi_fmap, cmf)) { + int i; + + VERIFY(cmp->cm_tmap[cmf->cmf_rtid].cmt_map != 0); + cmf->cmf_rtid = cmp->cm_tmap[cmf->cmf_rtid].cmt_map; + for (i = 0; i < cmf->cmf_argc; i++) { + VERIFY(cmp->cm_tmap[cmf->cmf_args[i]].cmt_map != + 0); + cmf->cmf_args[i] = + cmp->cm_tmap[cmf->cmf_args[i]].cmt_map; + } + } +} + +static int +ctf_uniquify_types(ctf_merge_t *cmh, ctf_file_t *src, ctf_file_t **outp) +{ + int err, ret; + ctf_file_t *out; + ctf_merge_types_t cm; + ctf_diff_t *cdp; + ctf_merge_input_t *cmi; + ctf_file_t *parent = cmh->cmh_unique; + + *outp = NULL; + out = ctf_fdcreate(cmh->cmh_ofd, &err); + if (out == NULL) + return (ctf_set_errno(src, err)); + + out->ctf_parname = cmh->cmh_pname; + if (ctf_setmodel(out, ctf_getmodel(parent)) != 0) { + (void) ctf_set_errno(src, ctf_errno(out)); + ctf_close(out); + return (CTF_ERR); + } + + if (ctf_import(out, parent) != 0) { + (void) ctf_set_errno(src, ctf_errno(out)); + ctf_close(out); + return (CTF_ERR); + } + + if ((ret = ctf_diff_init(parent, src, &cdp)) != 0) { + ctf_close(out); + return (ctf_set_errno(src, ctf_errno(parent))); + } + + cm.cm_out = parent; + cm.cm_src = src; + cm.cm_dedup = B_FALSE; + cm.cm_unique = B_TRUE; + ret = ctf_merge_types_init(&cm); + if (ret != 0) { + ctf_close(out); + ctf_diff_fini(cdp); + return (ctf_set_errno(src, ret)); + } + + ret = ctf_diff_types(cdp, ctf_merge_diffcb, &cm); + if (ret == 0) { + cm.cm_out = out; + ret = ctf_merge_uniquify_types(&cm); + if (ret == 0) + ret = ctf_update(out); + } + + if (ret != 0) { + ctf_merge_types_fini(&cm); + ctf_diff_fini(cdp); + return (ctf_set_errno(src, ctf_errno(cm.cm_out))); + } + + for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL; + cmi = list_next(&cmh->cmh_inputs, cmi)) { + ctf_merge_fixup_nontypes(&cm, cmi); + } + + ctf_merge_types_fini(&cm); + ctf_diff_fini(cdp); + *outp = out; + return (0); +} + +static void +ctf_merge_fini_input(ctf_merge_input_t *cmi) +{ + ctf_merge_objmap_t *cmo; + ctf_merge_funcmap_t *cmf; + + while ((cmo = list_remove_head(&cmi->cmi_omap)) != NULL) + ctf_free(cmo, sizeof (ctf_merge_objmap_t)); + + while ((cmf = list_remove_head(&cmi->cmi_fmap)) != NULL) + ctf_free(cmf, sizeof (ctf_merge_funcmap_t) + + sizeof (ctf_id_t) * cmf->cmf_argc); + + if (cmi->cmi_created == B_TRUE && cmi->cmi_input != NULL) + ctf_close(cmi->cmi_input); + + ctf_free(cmi, sizeof (ctf_merge_input_t)); +} + +void +ctf_merge_fini(ctf_merge_t *cmh) +{ + size_t len; + ctf_merge_input_t *cmi; + + if (cmh->cmh_label != NULL) { + len = strlen(cmh->cmh_label) + 1; + ctf_free(cmh->cmh_label, len); + } + + if (cmh->cmh_pname != NULL) { + len = strlen(cmh->cmh_pname) + 1; + ctf_free(cmh->cmh_pname, len); + } + + while ((cmi = list_remove_head(&cmh->cmh_inputs)) != NULL) + ctf_merge_fini_input(cmi); + + ctf_free(cmh, sizeof (ctf_merge_t)); +} + +ctf_merge_t * +ctf_merge_init(int fd, int *errp) +{ + int err; + ctf_merge_t *out; + struct stat st; + + if (errp == NULL) + errp = &err; + + if (fd != -1 && fstat(fd, &st) != 0) { + *errp = EINVAL; + return (NULL); + } + + out = ctf_alloc(sizeof (ctf_merge_t)); + if (out == NULL) { + *errp = ENOMEM; + return (NULL); + } + + if (fd == -1) { + out->cmh_msyms = B_FALSE; + } else { + out->cmh_msyms = B_TRUE; + } + + list_create(&out->cmh_inputs, sizeof (ctf_merge_input_t), + offsetof(ctf_merge_input_t, cmi_node)); + out->cmh_ninputs = 0; + out->cmh_nthreads = 1; + out->cmh_unique = NULL; + out->cmh_ofd = fd; + out->cmh_flags = 0; + out->cmh_label = NULL; + out->cmh_pname = NULL; + + return (out); +} + +int +ctf_merge_label(ctf_merge_t *cmh, const char *label) +{ + char *dup; + + if (label == NULL) + return (EINVAL); + + dup = ctf_strdup(label); + if (dup == NULL) + return (EAGAIN); + + if (cmh->cmh_label != NULL) { + size_t len = strlen(cmh->cmh_label) + 1; + ctf_free(cmh->cmh_label, len); + } + + cmh->cmh_label = dup; + return (0); +} + +static int +ctf_merge_add_funcs_cb(const char *name, ulong_t idx, ctf_funcinfo_t *fip, + void *arg) +{ + ctf_merge_input_t *cmi = arg; + ctf_merge_funcmap_t *fmap; + + fmap = ctf_alloc(sizeof (ctf_merge_funcmap_t) + + sizeof (ctf_id_t) * fip->ctc_argc); + if (fmap == NULL) + return (ENOMEM); + + fmap->cmf_idx = idx; + fmap->cmf_rtid = fip->ctc_return; + fmap->cmf_flags = fip->ctc_flags; + fmap->cmf_argc = fip->ctc_argc; + fmap->cmf_name = name; + + if (ctf_func_args(cmi->cmi_input, idx, fmap->cmf_argc, + fmap->cmf_args) != 0) { + ctf_free(fmap, sizeof (ctf_merge_funcmap_t) + + sizeof (ctf_id_t) * fip->ctc_argc); + return (ctf_errno(cmi->cmi_input)); + } + + list_insert_tail(&cmi->cmi_fmap, fmap); + return (0); +} + +static int +ctf_merge_add_objs_cb(const char *name, ctf_id_t id, ulong_t idx, void *arg) +{ + ctf_merge_input_t *cmi = arg; + ctf_merge_objmap_t *cmo; + + cmo = ctf_alloc(sizeof (ctf_merge_objmap_t)); + if (cmo == NULL) + return (ENOMEM); + + cmo->cmo_name = name; + cmo->cmo_idx = idx; + cmo->cmo_tid = id; + list_insert_tail(&cmi->cmi_omap, cmo); + return (0); +} + +/* + * Whenever we create an entry to merge, we then go and add a second empty + * ctf_file_t which we use for the purposes of our merging. It's not the best, + * but it's the best that we've got at the moment. + */ +int +ctf_merge_add(ctf_merge_t *cmh, ctf_file_t *input) +{ + int ret; + ctf_merge_input_t *cmi; + ctf_file_t *empty; + + if (input->ctf_flags & LCTF_CHILD) + return (ECTF_MCHILD); + + cmi = ctf_alloc(sizeof (ctf_merge_input_t)); + if (cmi == NULL) + return (ENOMEM); + + cmi->cmi_created = B_FALSE; + cmi->cmi_input = input; + list_create(&cmi->cmi_fmap, sizeof (ctf_merge_funcmap_t), + offsetof(ctf_merge_funcmap_t, cmf_node)); + list_create(&cmi->cmi_omap, sizeof (ctf_merge_funcmap_t), + offsetof(ctf_merge_objmap_t, cmo_node)); + + if (cmh->cmh_msyms == B_TRUE) { + if ((ret = ctf_function_iter(input, ctf_merge_add_funcs_cb, + cmi)) != 0) { + ctf_merge_fini_input(cmi); + return (ret); + } + + if ((ret = ctf_object_iter(input, ctf_merge_add_objs_cb, + cmi)) != 0) { + ctf_merge_fini_input(cmi); + return (ret); + } + } + + list_insert_tail(&cmh->cmh_inputs, cmi); + cmh->cmh_ninputs++; + + /* And now the empty one to merge into this */ + cmi = ctf_alloc(sizeof (ctf_merge_input_t)); + if (cmi == NULL) + return (ENOMEM); + list_create(&cmi->cmi_fmap, sizeof (ctf_merge_funcmap_t), + offsetof(ctf_merge_funcmap_t, cmf_node)); + list_create(&cmi->cmi_omap, sizeof (ctf_merge_funcmap_t), + offsetof(ctf_merge_objmap_t, cmo_node)); + + empty = ctf_fdcreate(cmh->cmh_ofd, &ret); + if (empty == NULL) + return (ret); + cmi->cmi_input = empty; + cmi->cmi_created = B_TRUE; + + if (ctf_setmodel(empty, ctf_getmodel(input)) == CTF_ERR) { + return (ctf_errno(empty)); + } + + list_insert_tail(&cmh->cmh_inputs, cmi); + cmh->cmh_ninputs++; + ctf_dprintf("added containers %p and %p\n", input, empty); + return (0); +} + +int +ctf_merge_uniquify(ctf_merge_t *cmh, ctf_file_t *u, const char *pname) +{ + char *dup; + + if (u->ctf_flags & LCTF_CHILD) + return (ECTF_MCHILD); + if (pname == NULL) + return (EINVAL); + dup = ctf_strdup(pname); + if (dup == NULL) + return (EINVAL); + if (cmh->cmh_pname != NULL) { + size_t len = strlen(cmh->cmh_pname) + 1; + ctf_free(cmh->cmh_pname, len); + } + cmh->cmh_pname = dup; + cmh->cmh_unique = u; + return (0); +} + +static int +ctf_merge_symbols(ctf_merge_t *cmh, ctf_file_t *fp) +{ + int err; + ulong_t i; + + uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data; + uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data; + + for (i = 0; i < fp->ctf_nsyms; i++) { + const char *name; + ctf_merge_input_t *cmi; + ctf_merge_objmap_t *cmo; + + if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) { + const Elf32_Sym *symp = (Elf32_Sym *)symbase + i; + int type = ELF32_ST_TYPE(symp->st_info); + if (type != STT_OBJECT) + continue; + if (ctf_sym_valid(strbase, type, symp->st_shndx, + symp->st_value, symp->st_name) == B_FALSE) + continue; + name = (char *)(strbase + symp->st_name); + } else { + const Elf64_Sym *symp = (Elf64_Sym *)symbase + i; + int type = ELF64_ST_TYPE(symp->st_info); + if (type != STT_OBJECT) + continue; + if (ctf_sym_valid(strbase, type, symp->st_shndx, + symp->st_value, symp->st_name) == B_FALSE) + continue; + name = (char *)(strbase + symp->st_name); + } + + cmo = NULL; + for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL; + cmi = list_next(&cmh->cmh_inputs, cmi)) { + for (cmo = list_head(&cmi->cmi_omap); cmo != NULL; + cmo = list_next(&cmi->cmi_omap, cmo)) { + if (strcmp(cmo->cmo_name, name) == 0) + goto found; + } + } +found: + if (cmo != NULL) { + if (cmo->cmo_tid == 0) + continue; + if ((err = ctf_add_object(fp, i, cmo->cmo_tid)) != 0) { + ctf_dprintf("Failed to add symbol %s->%d: %s\n", + name, cmo->cmo_tid, + ctf_errmsg(ctf_errno(fp))); + return (err); + } + } + } + + return (0); +} + +static int +ctf_merge_functions(ctf_merge_t *cmh, ctf_file_t *fp) +{ + int err; + ulong_t i; + ctf_funcinfo_t fi; + + uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data; + uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data; + + for (i = 0; i < fp->ctf_nsyms; i++) { + const char *name; + ctf_merge_input_t *cmi; + ctf_merge_funcmap_t *cmf; + + if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) { + const Elf32_Sym *symp = (Elf32_Sym *)symbase + i; + int type = ELF32_ST_TYPE(symp->st_info); + if (ELF32_ST_TYPE(symp->st_info) != STT_FUNC) + continue; + if (ctf_sym_valid(strbase, type, symp->st_shndx, + symp->st_value, symp->st_name) == B_FALSE) + continue; + name = (char *)(strbase + symp->st_name); + } else { + const Elf64_Sym *symp = (Elf64_Sym *)symbase + i; + int type = ELF64_ST_TYPE(symp->st_info); + if (ELF64_ST_TYPE(symp->st_info) != STT_FUNC) + continue; + if (ctf_sym_valid(strbase, type, symp->st_shndx, + symp->st_value, symp->st_name) == B_FALSE) + continue; + name = (char *)(strbase + symp->st_name); + } + + cmf = NULL; + for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL; + cmi = list_next(&cmh->cmh_inputs, cmi)) { + for (cmf = list_head(&cmi->cmi_fmap); cmf != NULL; + cmf = list_next(&cmi->cmi_fmap, cmf)) { + if (strcmp(cmf->cmf_name, name) == 0) + goto found; + } + } +found: + if (cmf != NULL) { + fi.ctc_return = cmf->cmf_rtid; + fi.ctc_argc = cmf->cmf_argc; + fi.ctc_flags = cmf->cmf_flags; + if ((err = ctf_add_function(fp, i, &fi, + cmf->cmf_args)) != 0) + return (err); + } + } + + return (0); + +} + +int +ctf_merge_merge(ctf_merge_t *cmh, ctf_file_t **outp) +{ + int err, merr; + ctf_merge_input_t *cmi; + ctf_id_t ltype; + mergeq_t *mqp; + ctf_merge_input_t *final; + ctf_file_t *out; + + if (cmh->cmh_label != NULL && cmh->cmh_unique != NULL) { + const char *label = ctf_label_topmost(cmh->cmh_unique); + if (label == NULL) + return (ECTF_NOLABEL); + if (strcmp(label, cmh->cmh_label) != 0) + return (ECTF_LCONFLICT); + } + + if (mergeq_init(&mqp, cmh->cmh_nthreads) == -1) { + return (errno); + } + + VERIFY(cmh->cmh_ninputs % 2 == 0); + for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL; + cmi = list_next(&cmh->cmh_inputs, cmi)) { + if (mergeq_add(mqp, cmi) == -1) { + err = errno; + mergeq_fini(mqp); + } + } + + err = mergeq_merge(mqp, ctf_merge_types, NULL, (void **)&final, &merr); + mergeq_fini(mqp); + + if (err == MERGEQ_ERROR) { + return (errno); + } else if (err == MERGEQ_UERROR) { + return (merr); + } + + /* + * Disassociate the generated ctf_file_t from the original input. That + * way when the input gets cleaned up, we don't accidentally kill the + * final reference to the ctf_file_t. If it gets uniquified then we'll + * kill it. + */ + VERIFY(final->cmi_input != NULL); + out = final->cmi_input; + final->cmi_input = NULL; + + ctf_dprintf("preparing to uniquify against: %p\n", cmh->cmh_unique); + if (cmh->cmh_unique != NULL) { + ctf_file_t *u; + err = ctf_uniquify_types(cmh, out, &u); + if (err != 0) { + err = ctf_errno(out); + ctf_close(out); + return (err); + } + ctf_close(out); + out = u; + } + + ltype = out->ctf_typemax; + if ((out->ctf_flags & LCTF_CHILD) && ltype != 0) + ltype += CTF_CHILD_START; + ctf_dprintf("trying to add the label\n"); + if (cmh->cmh_label != NULL && + ctf_add_label(out, cmh->cmh_label, ltype, 0) != 0) { + ctf_close(out); + return (ctf_errno(out)); + } + + ctf_dprintf("merging symbols and the like\n"); + if (cmh->cmh_msyms == B_TRUE) { + err = ctf_merge_symbols(cmh, out); + if (err != 0) { + ctf_close(out); + return (ctf_errno(out)); + } + + err = ctf_merge_functions(cmh, out); + if (err != 0) { + ctf_close(out); + return (ctf_errno(out)); + } + } + + err = ctf_update(out); + if (err != 0) { + ctf_close(out); + return (ctf_errno(out)); + } + + *outp = out; + return (0); +} + +/* + * When we get told that something is unique, eg. same is B_FALSE, then that + * tells us that we need to add it to the output. If same is B_TRUE, then we'll + * want to record it in the mapping table so that we know how to redirect types + * to the extant ones. + */ +static void +ctf_dedup_cb(ctf_file_t *ifp, ctf_id_t iid, boolean_t same, ctf_file_t *ofp, + ctf_id_t oid, void *arg) +{ + ctf_merge_types_t *cmp = arg; + ctf_merge_tinfo_t *cmt = cmp->cm_tmap; + + if (same == B_TRUE) { + /* + * The output id here may itself map to something else. + * Therefore, we need to basically walk a chain and see what it + * points to until it itself points to a base type, eg. -1. + * Otherwise we'll dedup to something which no longer exists. + */ + while (cmt[oid].cmt_missing == B_FALSE) + oid = cmt[oid].cmt_map; + cmt[iid].cmt_map = oid; + ctf_dprintf("%d->%d \n", iid, oid); + } else { + VERIFY(cmt[iid].cmt_map == 0); + cmt[iid].cmt_missing = B_TRUE; + ctf_dprintf("%d is missing\n", iid); + } +} + +/* + * Dedup a CTF container. + * + * DWARF and other encoding formats that we use to create CTF data may create + * multiple copies of a given type. However, after doing a conversion, and + * before doing a merge, we'd prefer, if possible, to have every input container + * to be unique. + * + * Doing a deduplication is like a normal merge. However, when we diff the types + * in the container, rather than doing a normal diff, we instead want to diff + * against any already processed types. eg, for a given type i in a container, + * we want to diff it from 0 to i - 1. + */ +int +ctf_merge_dedup(ctf_merge_t *cmp, ctf_file_t **outp) +{ + int ret; + ctf_diff_t *cdp = NULL; + ctf_merge_input_t *cmi, *cmc; + ctf_file_t *ifp, *ofp; + ctf_merge_types_t cm; + + if (cmp == NULL || outp == NULL) + return (EINVAL); + + ctf_dprintf("encountered %d inputs\n", cmp->cmh_ninputs); + if (cmp->cmh_ninputs != 2) + return (EINVAL); + + ctf_dprintf("passed argument sanity check\n"); + + cmi = list_head(&cmp->cmh_inputs); + VERIFY(cmi != NULL); + cmc = list_next(&cmp->cmh_inputs, cmi); + VERIFY(cmc != NULL); + ifp = cmi->cmi_input; + ofp = cmc->cmi_input; + VERIFY(ifp != NULL); + VERIFY(ofp != NULL); + cm.cm_src = ifp; + cm.cm_out = ofp; + cm.cm_dedup = B_TRUE; + cm.cm_unique = B_FALSE; + + if ((ret = ctf_merge_types_init(&cm)) != 0) { + return (ret); + } + + if ((ret = ctf_diff_init(ifp, ifp, &cdp)) != 0) + goto err; + + ctf_dprintf("Successfully initialized dedup\n"); + if ((ret = ctf_diff_self(cdp, ctf_dedup_cb, &cm)) != 0) + goto err; + + ctf_dprintf("Successfully diffed types\n"); + ret = ctf_merge_common(&cm); + ctf_dprintf("deduping types result: %d\n", ret); + if (ret == 0) + ret = ctf_update(cm.cm_out); + if (ret != 0) + goto err; + + ctf_dprintf("Successfully deduped types\n"); + ctf_phase_dump(cm.cm_out, "dedup-pre-syms"); + + /* + * Now we need to fix up the object and function maps. + */ + ctf_merge_fixup_nontypes(&cm, cmi); + + if (cmp->cmh_msyms == B_TRUE) { + ret = ctf_merge_symbols(cmp, cm.cm_out); + if (ret != 0) { + ret = ctf_errno(cm.cm_out); + ctf_dprintf("failed to dedup symbols: %s\n", + ctf_errmsg(ret)); + goto err; + } + + ret = ctf_merge_functions(cmp, cm.cm_out); + if (ret != 0) { + ret = ctf_errno(cm.cm_out); + ctf_dprintf("failed to dedup functions: %s\n", + ctf_errmsg(ret)); + goto err; + } + } + + ret = ctf_update(cm.cm_out); + if (ret == 0) { + cmc->cmi_input = NULL; + *outp = cm.cm_out; + } +err: + ctf_merge_types_fini(&cm); + ctf_diff_fini(cdp); + return (ret); +} + +int +ctf_merge_set_nthreads(ctf_merge_t *cmp, const uint_t nthrs) +{ + if (nthrs == 0) + return (EINVAL); + cmp->cmh_nthreads = nthrs; + return (0); +} diff --git a/usr/src/lib/libctf/common/ctf_subr.c b/usr/src/lib/libctf/common/ctf_subr.c index 467b6a8181..26f7e8c4db 100644 --- a/usr/src/lib/libctf/common/ctf_subr.c +++ b/usr/src/lib/libctf/common/ctf_subr.c @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include #include #include @@ -56,6 +54,18 @@ ctf_alloc(size_t size) return (malloc(size)); } +void * +mergeq_alloc(size_t size) +{ + return (malloc(size)); +} + +void * +workq_alloc(size_t size) +{ + return (malloc(size)); +} + /*ARGSUSED*/ void ctf_free(void *buf, size_t size) @@ -63,6 +73,20 @@ ctf_free(void *buf, size_t size) free(buf); } +/*ARGSUSED*/ +void +mergeq_free(void *buf, size_t size) +{ + free(buf); +} + +/*ARGSUSED*/ +void +workq_free(void *buf, size_t size) +{ + free(buf); +} + const char * ctf_strerror(int err) { diff --git a/usr/src/lib/libctf/common/libctf.h b/usr/src/lib/libctf/common/libctf.h index 3fd69318de..0951ae0606 100644 --- a/usr/src/lib/libctf/common/libctf.h +++ b/usr/src/lib/libctf/common/libctf.h @@ -23,6 +23,9 @@ * Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2015, Joyent, Inc. + */ /* * This header file defines the interfaces available from the CTF debugger @@ -32,7 +35,7 @@ * the fullness of time after we gain more experience with the interfaces. * * In the meantime, be aware that any program linked with libctf in this - * release of Solaris is almost guaranteed to break in the next release. + * release of illumos is almost guaranteed to break in the next release. * * In short, do not user this header file or libctf for any purpose. */ @@ -40,8 +43,6 @@ #ifndef _LIBCTF_H #define _LIBCTF_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include #ifdef __cplusplus @@ -53,6 +54,44 @@ extern "C" { */ extern int _libctf_debug; +typedef enum ctf_diff_flag { + CTF_DIFF_F_IGNORE_INTNAMES = 0x01 +} ctf_diff_flag_t; + +typedef struct ctf_diff ctf_diff_t; +typedef void (*ctf_diff_type_f)(ctf_file_t *, ctf_id_t, boolean_t, ctf_file_t *, + ctf_id_t, void *); +typedef void (*ctf_diff_func_f)(ctf_file_t *, ulong_t, boolean_t, ctf_file_t *, + ulong_t, void *); +typedef void (*ctf_diff_obj_f)(ctf_file_t *, ulong_t, ctf_id_t, boolean_t, + ctf_file_t *, ulong_t, ctf_id_t, void *); + +extern int ctf_diff_init(ctf_file_t *, ctf_file_t *, ctf_diff_t **); +extern uint_t ctf_diff_getflags(ctf_diff_t *); +extern int ctf_diff_setflags(ctf_diff_t *, uint_t); +extern int ctf_diff_types(ctf_diff_t *, ctf_diff_type_f, void *); +extern int ctf_diff_functions(ctf_diff_t *, ctf_diff_func_f, void *); +extern int ctf_diff_objects(ctf_diff_t *, ctf_diff_obj_f, void *); +extern void ctf_diff_fini(ctf_diff_t *); + +#define CTF_CONVERT_F_IGNNONC 0x01 +extern ctf_file_t *ctf_fdconvert(int, const char *, uint_t, uint_t, int *, + char *, size_t); + +typedef struct ctf_merge_handle ctf_merge_t; +extern ctf_merge_t *ctf_merge_init(int, int *); +extern int ctf_merge_add(ctf_merge_t *, ctf_file_t *); +extern int ctf_merge_set_nthreads(ctf_merge_t *, const uint_t); +extern int ctf_merge_label(ctf_merge_t *, const char *); +extern int ctf_merge_uniquify(ctf_merge_t *, ctf_file_t *, const char *); +extern int ctf_merge_merge(ctf_merge_t *, ctf_file_t **); +extern int ctf_merge_dedup(ctf_merge_t *, ctf_file_t **); +extern void ctf_merge_fini(ctf_merge_t *); + +#define CTF_ELFWRITE_F_COMPRESS 0x1 +extern int ctf_elffdwrite(ctf_file_t *, int, int, int); +extern int ctf_elfwrite(ctf_file_t *, const char *, const char *, int); + #ifdef __cplusplus } #endif diff --git a/usr/src/lib/libctf/common/libctf_impl.h b/usr/src/lib/libctf/common/libctf_impl.h new file mode 100644 index 0000000000..11193e97d0 --- /dev/null +++ b/usr/src/lib/libctf/common/libctf_impl.h @@ -0,0 +1,59 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2015 Joyent, Inc. + */ + +#ifndef _LIBCTF_IMPL_H +#define _LIBCTF_IMPL_H + +/* + * Portions of libctf implementations that are only suitable for CTF's userland + * library, eg. converting and merging related routines. + */ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum ctf_conv_status { + CTF_CONV_SUCCESS = 0, + CTF_CONV_ERROR = 1, + CTF_CONV_NOTSUP = 2 +} ctf_conv_status_t; + +typedef ctf_conv_status_t (*ctf_convert_f)(int, Elf *, uint_t, int *, + ctf_file_t **, char *, size_t); +extern ctf_conv_status_t ctf_dwarf_convert(int, Elf *, uint_t, int *, + ctf_file_t **, char *, size_t); + +/* + * zlib compression routines + */ +extern int ctf_compress(ctf_file_t *fp, void **, size_t *, size_t *); + +extern int ctf_diff_self(ctf_diff_t *, ctf_diff_type_f, void *); + +/* + * Internal debugging aids + */ +extern void ctf_phase_dump(ctf_file_t *, const char *); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBCTF_IMPL_H */ diff --git a/usr/src/lib/libctf/common/mapfile-vers b/usr/src/lib/libctf/common/mapfile-vers index 5573e8db25..b26ee8ceb4 100644 --- a/usr/src/lib/libctf/common/mapfile-vers +++ b/usr/src/lib/libctf/common/mapfile-vers @@ -23,7 +23,7 @@ # # -# Copyright (c) 2013, Joyent, Inc. All rights reserved. +# Copyright 2018 Joyent, Inc. # # @@ -53,9 +53,12 @@ SYMBOL_VERSION SUNWprivate_1.2 { ctf_add_enumerator; ctf_add_float; ctf_add_forward; + ctf_add_funcptr; ctf_add_function; ctf_add_integer; + ctf_add_label; ctf_add_member; + ctf_add_object; ctf_add_pointer; ctf_add_restrict; ctf_add_struct; @@ -64,19 +67,52 @@ SYMBOL_VERSION SUNWprivate_1.2 { ctf_add_union; ctf_add_volatile; ctf_create; + ctf_dataptr; ctf_delete_type; + ctf_diff_fini; + ctf_diff_functions; + ctf_diff_getflags; + ctf_diff_init; + ctf_diff_objects; + ctf_diff_setflags; + ctf_diff_types; ctf_discard; ctf_dup; + ctf_elffdwrite; + ctf_elfwrite; ctf_enum_value; + ctf_fdconvert; + ctf_flags; + ctf_func_args_by_id; + ctf_func_info_by_id; + ctf_function_iter; + ctf_kind_name; ctf_label_info; ctf_label_iter; ctf_label_topmost; + ctf_max_id; ctf_member_info; + ctf_merge_add; + ctf_merge_dedup; + ctf_merge_fini; + ctf_merge_init; + ctf_merge_label; + ctf_merge_merge; + ctf_merge_set_nthreads; + ctf_merge_uniquify; + ctf_nr_syms; + ctf_object_iter; ctf_parent_file; + ctf_parent_label; ctf_parent_name; ctf_set_array; + ctf_set_root; + ctf_set_size; + ctf_string_iter; + ctf_symbol_name; ctf_type_align; ctf_type_cmp; + ctf_type_cname; ctf_type_compat; ctf_type_pointer; ctf_update; diff --git a/usr/src/lib/libdtrace/common/dt_decl.c b/usr/src/lib/libdtrace/common/dt_decl.c index bbb561d027..c9bd469ddb 100644 --- a/usr/src/lib/libdtrace/common/dt_decl.c +++ b/usr/src/lib/libdtrace/common/dt_decl.c @@ -22,7 +22,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014 by Delphix. All rights reserved. - * Copyright (c) 2013 Joyent, Inc. All rights reserved. + * Copyright (c) 2015 Joyent, Inc. All rights reserved. */ #include @@ -652,7 +652,7 @@ dt_decl_member(dt_node_t *dnp) } if (ctf_add_member(dsp->ds_ctfp, dsp->ds_type, - ident, dtt.dtt_type) == CTF_ERR) { + ident, dtt.dtt_type, ULONG_MAX) == CTF_ERR) { xyerror(D_UNKNOWN, "failed to define member '%s': %s\n", idname, ctf_errmsg(ctf_errno(dsp->ds_ctfp))); } diff --git a/usr/src/lib/libdtrace/common/dt_open.c b/usr/src/lib/libdtrace/common/dt_open.c index eb88f7e993..3e3bf9768a 100644 --- a/usr/src/lib/libdtrace/common/dt_open.c +++ b/usr/src/lib/libdtrace/common/dt_open.c @@ -1140,13 +1140,13 @@ alloc: * Add intrinsic pointer types that are needed to initialize printf * format dictionary types (see table in dt_printf.c). */ - (void) ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT, + (void) ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT, NULL, ctf_lookup_by_name(dmp->dm_ctfp, "void")); - (void) ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT, + (void) ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT, NULL, ctf_lookup_by_name(dmp->dm_ctfp, "char")); - (void) ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT, + (void) ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT, NULL, ctf_lookup_by_name(dmp->dm_ctfp, "int")); if (ctf_update(dmp->dm_ctfp) != 0) { @@ -1206,11 +1206,11 @@ alloc: ctc.ctc_argc = 0; ctc.ctc_flags = 0; - dtp->dt_type_func = ctf_add_function(dmp->dm_ctfp, + dtp->dt_type_func = ctf_add_funcptr(dmp->dm_ctfp, CTF_ADD_ROOT, &ctc, NULL); - dtp->dt_type_fptr = ctf_add_pointer(dmp->dm_ctfp, - CTF_ADD_ROOT, dtp->dt_type_func); + dtp->dt_type_fptr = ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT, NULL, + dtp->dt_type_func); /* * We also insert CTF definitions for the special D intrinsic types diff --git a/usr/src/lib/libdtrace/common/dt_parser.c b/usr/src/lib/libdtrace/common/dt_parser.c index 7f771a8079..e652f337d9 100644 --- a/usr/src/lib/libdtrace/common/dt_parser.c +++ b/usr/src/lib/libdtrace/common/dt_parser.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2013, Joyent Inc. All rights reserved. + * Copyright (c) 2015, Joyent Inc. All rights reserved. * Copyright (c) 2012, 2016 by Delphix. All rights reserved. */ @@ -288,7 +288,7 @@ dt_type_pointer(dtrace_typeinfo_t *tip) return (dt_set_errno(dtp, EDT_CTF)); } - ptr = ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT, type); + ptr = ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT, NULL, type); if (ptr == CTF_ERR || ctf_update(dmp->dm_ctfp) == CTF_ERR) { dtp->dt_ctferr = ctf_errno(dmp->dm_ctfp); diff --git a/usr/src/lib/libdwarf/Makefile b/usr/src/lib/libdwarf/Makefile new file mode 100644 index 0000000000..6b7ff6244b --- /dev/null +++ b/usr/src/lib/libdwarf/Makefile @@ -0,0 +1,40 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2015 Joyent, Inc. +# + +include ../Makefile.lib + +SUBDIRS = $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) + +all := TARGET = all +clean := TARGET = clean +clobber := TARGET = clobber +install := TARGET = install +lint := TARGET = lint + +.KEEP_STATE: + +all clean clobber lint install_h: $(SUBDIRS) + +install: install_h $(SUBDIRS) + +check: $(CHECKHDRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + +include ../Makefile.targ diff --git a/usr/src/lib/libdwarf/Makefile.com b/usr/src/lib/libdwarf/Makefile.com new file mode 100644 index 0000000000..10e841cfac --- /dev/null +++ b/usr/src/lib/libdwarf/Makefile.com @@ -0,0 +1,94 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2015 Joyent, Inc. +# + +LIBRARY= libdwarf.a +VERS= .1 + +OBJECTS=dwarf_abbrev.o \ + dwarf_addr_finder.o \ + dwarf_alloc.o \ + dwarf_arange.o \ + dwarf_die_deliv.o \ + dwarf_elf_access.o \ + dwarf_error.o \ + dwarf_form.o \ + dwarf_frame.o \ + dwarf_frame2.o \ + dwarf_frame3.o \ + dwarf_funcs.o \ + dwarf_global.o \ + dwarf_harmless.o \ + dwarf_init_finish.o \ + dwarf_leb.o \ + dwarf_line.o \ + dwarf_line2.o \ + dwarf_loc.o \ + dwarf_macro.o \ + dwarf_names.o \ + dwarf_original_elf_init.o \ + dwarf_print_lines.o \ + dwarf_pubtypes.o \ + dwarf_query.o \ + dwarf_ranges.o \ + dwarf_sort_line.o \ + dwarf_string.o \ + dwarf_stubs.o \ + dwarf_types.o \ + dwarf_util.o \ + dwarf_vars.o \ + dwarf_weaks.o \ + malloc_check.o \ + pro_alloc.o \ + pro_arange.o \ + pro_die.o \ + pro_encode_nm.o \ + pro_error.o \ + pro_expr.o \ + pro_finish.o \ + pro_forms.o \ + pro_frame.o \ + pro_funcs.o \ + pro_init.o \ + pro_line.o \ + pro_macinfo.o \ + pro_pubnames.o \ + pro_reloc.o \ + pro_reloc_stream.o \ + pro_reloc_symbolic.o \ + pro_section.o \ + pro_types.o \ + pro_vars.o \ + pro_weaks.o + +include ../../Makefile.lib +include ../../Makefile.rootfs + +LIBS = $(DYNLIB) +LDLIBS += -lelf -lc + +SRCDIR = ../common +CPPFLAGS += -I$(SRCDIR) -DELF_TARGET_ALL=1 +CERRWARN += -_gcc=-Wno-unused +CERRWARN += -_gcc=-Wno-implicit-function-declaration + +SMATCH = off + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +include ../../Makefile.targ diff --git a/usr/src/lib/libdwarf/THIRDPARTYLICENSE b/usr/src/lib/libdwarf/THIRDPARTYLICENSE new file mode 100644 index 0000000000..b9320c2d56 --- /dev/null +++ b/usr/src/lib/libdwarf/THIRDPARTYLICENSE @@ -0,0 +1,30 @@ + Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, + USA. + + Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan diff --git a/usr/src/lib/libdwarf/THIRDPARTYLICENSE.descrip b/usr/src/lib/libdwarf/THIRDPARTYLICENSE.descrip new file mode 100644 index 0000000000..73abaac973 --- /dev/null +++ b/usr/src/lib/libdwarf/THIRDPARTYLICENSE.descrip @@ -0,0 +1 @@ +LIBDWARF LIBRARY THAT SUPPORTS THE DWARF OPEN SOURCE STANDARD diff --git a/usr/src/lib/libdwarf/amd64/Makefile b/usr/src/lib/libdwarf/amd64/Makefile new file mode 100644 index 0000000000..15a899f96f --- /dev/null +++ b/usr/src/lib/libdwarf/amd64/Makefile @@ -0,0 +1,19 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2015 Joyent, Inc. +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/lib/libdwarf/common/cmplrs/dwarf_addr_finder.h b/usr/src/lib/libdwarf/common/cmplrs/dwarf_addr_finder.h new file mode 100644 index 0000000000..0eda6d1c44 --- /dev/null +++ b/usr/src/lib/libdwarf/common/cmplrs/dwarf_addr_finder.h @@ -0,0 +1,55 @@ +/* + dwarf_addr_finder.h + $Source: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/include/cmplrs/RCS/dwarf_addr_finder.h,v $ + $Date: 2002/06/11 17:49:06 $ + + Defines user interface. + +*/ + +/* return codes for functions +*/ +#define DW_DLV_NO_ENTRY -1 +#define DW_DLV_OK 0 +#define DW_DLV_ERROR 1 + + +/* the following are the 'section' number passed to the called-back + function. + The called-back application must translate this to the + appropriate elf section number/pointer. + + Putting this burden on the application avoids having to store + the numbers in the Dwarf_Debug structure (thereby saving space + for most consumers). +*/ +#define DW_SECTION_INFO 0 +#define DW_SECTION_FRAME 1 +#define DW_SECTION_ARANGES 2 +#define DW_SECTION_LINE 3 +#define DW_SECTION_LOC 4 /* .debug_loc */ + +/* section is one of the above codes: it specifies a section. + secoff is the offset in the dwarf section. + existingAddr is the value at the specified offset (so the + called back routine can sanity check the proceedings). + It's up to the caller to know the size of an address (4 or 8) + and update the right number of bytes. +*/ +typedef int (*Dwarf_addr_callback_func) (int /*section*/, + Dwarf_Off /*secoff*/, Dwarf_Addr /*existingAddr*/); + +/* call this to do the work: it calls back thru cb_func + once per each address to be modified. + Once this returns you are done. + Returns DW_DLV_OK if finished ok. + Returns DW_DLV_ERROR if there was some kind of error, in which + the dwarf error number was passed back thu the dwerr ptr. + Returns DW_DLV_NO_ENTRY if there are no relevant dwarf sections, + so there were no addresses to be modified (and none + called back). +*/ +int _dwarf_addr_finder(dwarf_elf_handle elf_file_ptr, + Dwarf_addr_callback_func cb_func, + int *dwerr); + diff --git a/usr/src/lib/libdwarf/common/config.h b/usr/src/lib/libdwarf/common/config.h new file mode 100644 index 0000000000..42b286cfda --- /dev/null +++ b/usr/src/lib/libdwarf/common/config.h @@ -0,0 +1,143 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ALLOCA_H 1 + +/* Define 1 if want to allow producer to build with 32/64bit section offsets + per dwarf3 */ +#define HAVE_DWARF2_99_EXTENSION 1 + +/* Define to 1 if the elf64_getehdr function is in libelf.a. */ +#define HAVE_ELF64_GETEHDR 1 + +/* Define to 1 if the elf64_getshdr function is in libelf.a. */ +#define HAVE_ELF64_GETSHDR 1 + +/* Define 1 if Elf64_Rela defined. */ +#define HAVE_ELF64_RELA 1 + +/* Define 1 if Elf64_Sym defined. */ +#define HAVE_ELF64_SYM 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ELFACCESS_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ELF_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIBELF_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBELF_LIBELF_H */ + +/* Define 1 if off64 is defined via libelf with GNU_SOURCE. */ +#define HAVE_LIBELF_OFF64_OK 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define 1 if need nonstandard printf format for 64bit */ +/* #undef HAVE_NONSTANDARD_PRINTF_64_FORMAT */ + +/* Define 1 to default to old DW_FRAME_CFA_COL */ +/* #undef HAVE_OLD_FRAME_CFA_COL */ + +/* Define 1 if plain libelf builds. */ +#define HAVE_RAW_LIBELF_OK 1 + +/* Define 1 if R_IA_64_DIR32LSB is defined (might be enum value). */ +/* #undef HAVE_R_IA_64_DIR32LSB */ + +/* Define 1 if want producer to build with IRIX offset sizes */ +/* #undef HAVE_SGI_IRIX_OFFSETS */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define 1 if want producer to build with only 32bit section offsets */ +/* #undef HAVE_STRICT_DWARF2_32BIT_OFFSET */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_IA64_ELF_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define 1 if want to allow Windows full path detection */ +/* #undef HAVE_WINDOWS_PATH */ + +/* See if __uint32_t is predefined in the compiler. */ +/* #undef HAVE___UINT32_T */ + +/* Define 1 if __uint32_t is in sgidefs.h. */ +/* #undef HAVE___UINT32_T_IN_SGIDEFS_H */ + +/* Define 1 if sys/types.h defines __uint32_t. */ +/* #undef HAVE___UINT32_T_IN_SYS_TYPES_H */ + +/* See if __uint64_t is predefined in the compiler. */ +/* #undef HAVE___UINT64_T */ + +/* Define 1 if is in sgidefs.h. */ +/* #undef HAVE___UINT64_T_IN_SGIDEFS_H */ + +/* Define 1 if sys/types.h defines __uint64_t. */ +/* #undef HAVE___UINT64_T_IN_SYS_TYPES_H */ + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# if defined(__sparc) +# define WORDS_BIGENDIAN 1 +# else +# undef WORDS_BIGENDIAN +# endif +#endif diff --git a/usr/src/lib/libdwarf/common/dwarf.h b/usr/src/lib/libdwarf/common/dwarf.h new file mode 100644 index 0000000000..b064c4d86b --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf.h @@ -0,0 +1,1078 @@ +/* + Copyright (C) 2000,2001,2003,2004,2005,2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2007-2010 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + +#ifndef __DWARF_H +#define __DWARF_H +#ifdef __cplusplus +extern "C" { +#endif + +/* + dwarf.h DWARF debugging information values + $Revision: 1.41 $ $Date: 2006/04/17 00:09:56 $ + + The comment "DWARF3" appears where there are + new entries from DWARF3 as of 2004, "DWARF3f" + where there are new entries as of the November 2005 + public review document and other comments apply + where extension entries appear. + + Extensions part of DWARF4 are marked DWARF4. + + A few extension names have omitted the 'vendor id' + (See chapter 7, "Vendor Extensibility"). Please + always use a 'vendor id' string in extension names. + + Vendors should use a vendor string in names and + whereever possible avoid duplicating values used by + other vendor extensions + +*/ + + +#define DW_TAG_array_type 0x01 +#define DW_TAG_class_type 0x02 +#define DW_TAG_entry_point 0x03 +#define DW_TAG_enumeration_type 0x04 +#define DW_TAG_formal_parameter 0x05 +#define DW_TAG_imported_declaration 0x08 +#define DW_TAG_label 0x0a +#define DW_TAG_lexical_block 0x0b +#define DW_TAG_member 0x0d +#define DW_TAG_pointer_type 0x0f +#define DW_TAG_reference_type 0x10 +#define DW_TAG_compile_unit 0x11 +#define DW_TAG_string_type 0x12 +#define DW_TAG_structure_type 0x13 +#define DW_TAG_subroutine_type 0x15 +#define DW_TAG_typedef 0x16 +#define DW_TAG_union_type 0x17 +#define DW_TAG_unspecified_parameters 0x18 +#define DW_TAG_variant 0x19 +#define DW_TAG_common_block 0x1a +#define DW_TAG_common_inclusion 0x1b +#define DW_TAG_inheritance 0x1c +#define DW_TAG_inlined_subroutine 0x1d +#define DW_TAG_module 0x1e +#define DW_TAG_ptr_to_member_type 0x1f +#define DW_TAG_set_type 0x20 +#define DW_TAG_subrange_type 0x21 +#define DW_TAG_with_stmt 0x22 +#define DW_TAG_access_declaration 0x23 +#define DW_TAG_base_type 0x24 +#define DW_TAG_catch_block 0x25 +#define DW_TAG_const_type 0x26 +#define DW_TAG_constant 0x27 +#define DW_TAG_enumerator 0x28 +#define DW_TAG_file_type 0x29 +#define DW_TAG_friend 0x2a +#define DW_TAG_namelist 0x2b + /* Early releases of this header had the following + misspelled with a trailing 's' */ +#define DW_TAG_namelist_item 0x2c /* DWARF3/2 spelling */ +#define DW_TAG_namelist_items 0x2c /* SGI misspelling/typo */ +#define DW_TAG_packed_type 0x2d +#define DW_TAG_subprogram 0x2e + /* The DWARF2 document had two spellings of the following + two TAGs, DWARF3 specifies the longer spelling. */ +#define DW_TAG_template_type_parameter 0x2f /* DWARF3/2 spelling*/ +#define DW_TAG_template_type_param 0x2f /* DWARF2 spelling*/ +#define DW_TAG_template_value_parameter 0x30 /* DWARF3/2 spelling*/ +#define DW_TAG_template_value_param 0x30 /* DWARF2 spelling*/ +#define DW_TAG_thrown_type 0x31 +#define DW_TAG_try_block 0x32 +#define DW_TAG_variant_part 0x33 +#define DW_TAG_variable 0x34 +#define DW_TAG_volatile_type 0x35 +#define DW_TAG_dwarf_procedure 0x36 /* DWARF3 */ +#define DW_TAG_restrict_type 0x37 /* DWARF3 */ +#define DW_TAG_interface_type 0x38 /* DWARF3 */ +#define DW_TAG_namespace 0x39 /* DWARF3 */ +#define DW_TAG_imported_module 0x3a /* DWARF3 */ +#define DW_TAG_unspecified_type 0x3b /* DWARF3 */ +#define DW_TAG_partial_unit 0x3c /* DWARF3 */ +#define DW_TAG_imported_unit 0x3d /* DWARF3 */ + /* Do not use DW_TAG_mutable_type */ +#define DW_TAG_mutable_type 0x3e /* Withdrawn from DWARF3 by DWARF3f. */ +#define DW_TAG_condition 0x3f /* DWARF3f */ +#define DW_TAG_shared_type 0x40 /* DWARF3f */ +#define DW_TAG_type_unit 0x41 /* DWARF4 */ +#define DW_TAG_rvalue_reference_type 0x42 /* DWARF4 */ +#define DW_TAG_template_alias 0x43 /* DWARF4 */ +#define DW_TAG_lo_user 0x4080 + +#define DW_TAG_MIPS_loop 0x4081 + +/* HP extensions: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz */ +#define DW_TAG_HP_array_descriptor 0x4090 /* HP */ + +/* GNU extensions. The first 3 missing the GNU_. */ +#define DW_TAG_format_label 0x4101 /* GNU. Fortran. */ +#define DW_TAG_function_template 0x4102 /* GNU. For C++ */ +#define DW_TAG_class_template 0x4103 /* GNU. For C++ */ +#define DW_TAG_GNU_BINCL 0x4104 /* GNU */ +#define DW_TAG_GNU_EINCL 0x4105 /* GNU */ + + +/* GNU extension. http://gcc.gnu.org/wiki/TemplateParmsDwarf */ +#define DW_TAG_GNU_template_template_parameter 0x4106 /* GNU */ +#define DW_TAG_GNU_template_template_param 0x4106 /* GNU */ +#define DW_TAG_GNU_template_parameter_pack 0x4107 /* GNU */ +#define DW_TAG_GNU_formal_parameter_pack 0x4108 /* GNU */ + +/* ALTIUM extensions */ + /* DSP-C/Starcore __circ qualifier */ +#define DW_TAG_ALTIUM_circ_type 0x5101 /* ALTIUM */ + /* Starcore __mwa_circ qualifier */ +#define DW_TAG_ALTIUM_mwa_circ_type 0x5102 /* ALTIUM */ + /* Starcore __rev_carry qualifier */ +#define DW_TAG_ALTIUM_rev_carry_type 0x5103 /* ALTIUM */ + /* M16 __rom qualifier */ +#define DW_TAG_ALTIUM_rom 0x5111 /* ALTIUM */ + +/* The following 3 are extensions to support UPC */ +#define DW_TAG_upc_shared_type 0x8765 /* UPC */ +#define DW_TAG_upc_strict_type 0x8766 /* UPC */ +#define DW_TAG_upc_relaxed_type 0x8767 /* UPC */ + +/* PGI (STMicroelectronics) extensions. */ +#define DW_TAG_PGI_kanji_type 0xa000 /* PGI */ +#define DW_TAG_PGI_interface_block 0xa020 /* PGI */ +/* The following are SUN extensions */ +#define DW_TAG_SUN_function_template 0x4201 /* SUN */ +#define DW_TAG_SUN_class_template 0x4202 /* SUN */ +#define DW_TAG_SUN_struct_template 0x4203 /* SUN */ +#define DW_TAG_SUN_union_template 0x4204 /* SUN */ +#define DW_TAG_SUN_indirect_inheritance 0x4205 /* SUN */ +#define DW_TAG_SUN_codeflags 0x4206 /* SUN */ +#define DW_TAG_SUN_memop_info 0x4207 /* SUN */ +#define DW_TAG_SUN_omp_child_func 0x4208 /* SUN */ +#define DW_TAG_SUN_rtti_descriptor 0x4209 /* SUN */ +#define DW_TAG_SUN_dtor_info 0x420a /* SUN */ +#define DW_TAG_SUN_dtor 0x420b /* SUN */ +#define DW_TAG_SUN_f90_interface 0x420c /* SUN */ +#define DW_TAG_SUN_fortran_vax_structure 0x420d /* SUN */ +#define DW_TAG_SUN_hi 0x42ff /* SUN */ + + +#define DW_TAG_hi_user 0xffff + +#define DW_children_no 0 +#define DW_children_yes 1 + + + +#define DW_FORM_addr 0x01 +#define DW_FORM_block2 0x03 +#define DW_FORM_block4 0x04 +#define DW_FORM_data2 0x05 +#define DW_FORM_data4 0x06 +#define DW_FORM_data8 0x07 +#define DW_FORM_string 0x08 +#define DW_FORM_block 0x09 +#define DW_FORM_block1 0x0a +#define DW_FORM_data1 0x0b +#define DW_FORM_flag 0x0c +#define DW_FORM_sdata 0x0d +#define DW_FORM_strp 0x0e +#define DW_FORM_udata 0x0f +#define DW_FORM_ref_addr 0x10 +#define DW_FORM_ref1 0x11 +#define DW_FORM_ref2 0x12 +#define DW_FORM_ref4 0x13 +#define DW_FORM_ref8 0x14 +#define DW_FORM_ref_udata 0x15 +#define DW_FORM_indirect 0x16 +#define DW_FORM_sec_offset 0x17 /* DWARF4 */ +#define DW_FORM_exprloc 0x18 /* DWARF4 */ +#define DW_FORM_flag_present 0x19 /* DWARF4 */ +/* 0x1a thru 0x1f were left unused accidentally. Reserved for future use. */ +#define DW_FORM_ref_sig8 0x20 /* DWARF4 */ + +#define DW_AT_sibling 0x01 +#define DW_AT_location 0x02 +#define DW_AT_name 0x03 +#define DW_AT_ordering 0x09 +#define DW_AT_subscr_data 0x0a +#define DW_AT_byte_size 0x0b +#define DW_AT_bit_offset 0x0c +#define DW_AT_bit_size 0x0d +#define DW_AT_element_list 0x0f +#define DW_AT_stmt_list 0x10 +#define DW_AT_low_pc 0x11 +#define DW_AT_high_pc 0x12 +#define DW_AT_language 0x13 +#define DW_AT_member 0x14 +#define DW_AT_discr 0x15 +#define DW_AT_discr_value 0x16 +#define DW_AT_visibility 0x17 +#define DW_AT_import 0x18 +#define DW_AT_string_length 0x19 +#define DW_AT_common_reference 0x1a +#define DW_AT_comp_dir 0x1b +#define DW_AT_const_value 0x1c +#define DW_AT_containing_type 0x1d +#define DW_AT_default_value 0x1e +#define DW_AT_inline 0x20 +#define DW_AT_is_optional 0x21 +#define DW_AT_lower_bound 0x22 +#define DW_AT_producer 0x25 +#define DW_AT_prototyped 0x27 +#define DW_AT_return_addr 0x2a +#define DW_AT_start_scope 0x2c +#define DW_AT_bit_stride 0x2e /* DWARF3 name */ +#define DW_AT_stride_size 0x2e /* DWARF2 name */ +#define DW_AT_upper_bound 0x2f +#define DW_AT_abstract_origin 0x31 +#define DW_AT_accessibility 0x32 +#define DW_AT_address_class 0x33 +#define DW_AT_artificial 0x34 +#define DW_AT_base_types 0x35 +#define DW_AT_calling_convention 0x36 +#define DW_AT_count 0x37 +#define DW_AT_data_member_location 0x38 +#define DW_AT_decl_column 0x39 +#define DW_AT_decl_file 0x3a +#define DW_AT_decl_line 0x3b +#define DW_AT_declaration 0x3c +#define DW_AT_discr_list 0x3d +#define DW_AT_encoding 0x3e +#define DW_AT_external 0x3f +#define DW_AT_frame_base 0x40 +#define DW_AT_friend 0x41 +#define DW_AT_identifier_case 0x42 +#define DW_AT_macro_info 0x43 +#define DW_AT_namelist_item 0x44 +#define DW_AT_priority 0x45 +#define DW_AT_segment 0x46 +#define DW_AT_specification 0x47 +#define DW_AT_static_link 0x48 +#define DW_AT_type 0x49 +#define DW_AT_use_location 0x4a +#define DW_AT_variable_parameter 0x4b +#define DW_AT_virtuality 0x4c +#define DW_AT_vtable_elem_location 0x4d +#define DW_AT_allocated 0x4e /* DWARF3 */ +#define DW_AT_associated 0x4f /* DWARF3 */ +#define DW_AT_data_location 0x50 /* DWARF3 */ +#define DW_AT_byte_stride 0x51 /* DWARF3f */ +#define DW_AT_stride 0x51 /* DWARF3 (do not use) */ +#define DW_AT_entry_pc 0x52 /* DWARF3 */ +#define DW_AT_use_UTF8 0x53 /* DWARF3 */ +#define DW_AT_extension 0x54 /* DWARF3 */ +#define DW_AT_ranges 0x55 /* DWARF3 */ +#define DW_AT_trampoline 0x56 /* DWARF3 */ +#define DW_AT_call_column 0x57 /* DWARF3 */ +#define DW_AT_call_file 0x58 /* DWARF3 */ +#define DW_AT_call_line 0x59 /* DWARF3 */ +#define DW_AT_description 0x5a /* DWARF3 */ +#define DW_AT_binary_scale 0x5b /* DWARF3f */ +#define DW_AT_decimal_scale 0x5c /* DWARF3f */ +#define DW_AT_small 0x5d /* DWARF3f */ +#define DW_AT_decimal_sign 0x5e /* DWARF3f */ +#define DW_AT_digit_count 0x5f /* DWARF3f */ +#define DW_AT_picture_string 0x60 /* DWARF3f */ +#define DW_AT_mutable 0x61 /* DWARF3f */ +#define DW_AT_threads_scaled 0x62 /* DWARF3f */ +#define DW_AT_explicit 0x63 /* DWARF3f */ +#define DW_AT_object_pointer 0x64 /* DWARF3f */ +#define DW_AT_endianity 0x65 /* DWARF3f */ +#define DW_AT_elemental 0x66 /* DWARF3f */ +#define DW_AT_pure 0x67 /* DWARF3f */ +#define DW_AT_recursive 0x68 /* DWARF3f */ +#define DW_AT_signature 0x69 /* DWARF4 */ +#define DW_AT_main_subprogram 0x6a /* DWARF4 */ +#define DW_AT_data_bit_offset 0x6b /* DWARF4 */ +#define DW_AT_const_expr 0x6c /* DWARF4 */ +#define DW_AT_enum_class 0x6d /* DWARF4 */ +#define DW_AT_linkage_name 0x6e /* DWARF4 */ + +/* In extensions, we attempt to include the vendor extension + in the name even when the vendor leaves it out. */ + +/* HP extensions. */ +#define DW_AT_HP_block_index 0x2000 /* HP */ + +/* Follows extension so dwarfdump prints the most-likely-useful name. */ +#define DW_AT_lo_user 0x2000 + +#define DW_AT_MIPS_fde 0x2001 /* MIPS/SGI */ +#define DW_AT_MIPS_loop_begin 0x2002 /* MIPS/SGI */ +#define DW_AT_MIPS_tail_loop_begin 0x2003 /* MIPS/SGI */ +#define DW_AT_MIPS_epilog_begin 0x2004 /* MIPS/SGI */ +#define DW_AT_MIPS_loop_unroll_factor 0x2005 /* MIPS/SGI */ +#define DW_AT_MIPS_software_pipeline_depth 0x2006 /* MIPS/SGI */ +#define DW_AT_MIPS_linkage_name 0x2007 /* MIPS/SGI, GNU, and others.*/ +#define DW_AT_MIPS_stride 0x2008 /* MIPS/SGI */ +#define DW_AT_MIPS_abstract_name 0x2009 /* MIPS/SGI */ +#define DW_AT_MIPS_clone_origin 0x200a /* MIPS/SGI */ +#define DW_AT_MIPS_has_inlines 0x200b /* MIPS/SGI */ +#define DW_AT_MIPS_stride_byte 0x200c /* MIPS/SGI */ +#define DW_AT_MIPS_stride_elem 0x200d /* MIPS/SGI */ +#define DW_AT_MIPS_ptr_dopetype 0x200e /* MIPS/SGI */ +#define DW_AT_MIPS_allocatable_dopetype 0x200f /* MIPS/SGI */ +#define DW_AT_MIPS_assumed_shape_dopetype 0x2010 /* MIPS/SGI */ +#define DW_AT_MIPS_assumed_size 0x2011 /* MIPS/SGI */ + +/* HP extensions. */ +#define DW_AT_HP_unmodifiable 0x2001 /* conflict: MIPS */ +#define DW_AT_HP_actuals_stmt_list 0x2010 /* conflict: MIPS */ +#define DW_AT_HP_proc_per_section 0x2011 /* conflict: MIPS */ +#define DW_AT_HP_raw_data_ptr 0x2012 /* HP */ +#define DW_AT_HP_pass_by_reference 0x2013 /* HP */ +#define DW_AT_HP_opt_level 0x2014 /* HP */ +#define DW_AT_HP_prof_version_id 0x2015 /* HP */ +#define DW_AT_HP_opt_flags 0x2016 /* HP */ +#define DW_AT_HP_cold_region_low_pc 0x2017 /* HP */ +#define DW_AT_HP_cold_region_high_pc 0x2018 /* HP */ +#define DW_AT_HP_all_variables_modifiable 0x2019 /* HP */ +#define DW_AT_HP_linkage_name 0x201a /* HP */ +#define DW_AT_HP_prof_flags 0x201b /* HP */ + +#define DW_AT_CPQ_discontig_ranges 0x2001 /* COMPAQ/HP */ +#define DW_AT_CPQ_semantic_events 0x2002 /* COMPAQ/HP */ +#define DW_AT_CPQ_split_lifetimes_var 0x2003 /* COMPAQ/HP */ +#define DW_AT_CPQ_split_lifetimes_rtn 0x2004 /* COMPAQ/HP */ +#define DW_AT_CPQ_prologue_length 0x2005 /* COMPAQ/HP */ + +#define DW_AT_INTEL_other_endian 0x2026 /* Intel, 1 if byte swapped. */ + +/* GNU extensions. */ +#define DW_AT_sf_names 0x2101 /* GNU */ +#define DW_AT_src_info 0x2102 /* GNU */ +#define DW_AT_mac_info 0x2103 /* GNU */ +#define DW_AT_src_coords 0x2104 /* GNU */ +#define DW_AT_body_begin 0x2105 /* GNU */ +#define DW_AT_body_end 0x2106 /* GNU */ +#define DW_AT_GNU_vector 0x2107 /* GNU */ +#define DW_AT_GNU_template_name 0x2108 /* GNU */ + +/* ALTIUM extension: ALTIUM Compliant location lists (flag) */ +#define DW_AT_ALTIUM_loclist 0x2300 /* ALTIUM */ + +/* Sun extensions */ +#define DW_AT_SUN_template 0x2201 /* SUN */ +#define DW_AT_VMS_rtnbeg_pd_address 0x2201 /* VMS */ +#define DW_AT_SUN_alignment 0x2202 /* SUN */ +#define DW_AT_SUN_vtable 0x2203 /* SUN */ +#define DW_AT_SUN_count_guarantee 0x2204 /* SUN */ +#define DW_AT_SUN_command_line 0x2205 /* SUN */ +#define DW_AT_SUN_vbase 0x2206 /* SUN */ +#define DW_AT_SUN_compile_options 0x2207 /* SUN */ +#define DW_AT_SUN_language 0x2208 /* SUN */ +#define DW_AT_SUN_browser_file 0x2209 /* SUN */ +#define DW_AT_SUN_vtable_abi 0x2210 /* SUN */ +#define DW_AT_SUN_func_offsets 0x2211 /* SUN */ +#define DW_AT_SUN_cf_kind 0x2212 /* SUN */ +#define DW_AT_SUN_vtable_index 0x2213 /* SUN */ +#define DW_AT_SUN_omp_tpriv_addr 0x2214 /* SUN */ +#define DW_AT_SUN_omp_child_func 0x2215 /* SUN */ +#define DW_AT_SUN_func_offset 0x2216 /* SUN */ +#define DW_AT_SUN_memop_type_ref 0x2217 /* SUN */ +#define DW_AT_SUN_profile_id 0x2218 /* SUN */ +#define DW_AT_SUN_memop_signature 0x2219 /* SUN */ +#define DW_AT_SUN_obj_dir 0x2220 /* SUN */ +#define DW_AT_SUN_obj_file 0x2221 /* SUN */ +#define DW_AT_SUN_original_name 0x2222 /* SUN */ +#define DW_AT_SUN_hwcprof_signature 0x2223 /* SUN */ +#define DW_AT_SUN_amd64_parmdump 0x2224 /* SUN */ +#define DW_AT_SUN_part_link_name 0x2225 /* SUN */ +#define DW_AT_SUN_link_name 0x2226 /* SUN */ +#define DW_AT_SUN_pass_with_const 0x2227 /* SUN */ +#define DW_AT_SUN_return_with_const 0x2228 /* SUN */ +#define DW_AT_SUN_import_by_name 0x2229 /* SUN */ +#define DW_AT_SUN_f90_pointer 0x222a /* SUN */ +#define DW_AT_SUN_pass_by_ref 0x222b /* SUN */ +#define DW_AT_SUN_f90_allocatable 0x222c /* SUN */ +#define DW_AT_SUN_f90_assumed_shape_array 0x222d /* SUN */ +#define DW_AT_SUN_c_vla 0x222e /* SUN */ +#define DW_AT_SUN_return_value_ptr 0x2230 /* SUN */ +#define DW_AT_SUN_dtor_start 0x2231 /* SUN */ +#define DW_AT_SUN_dtor_length 0x2232 /* SUN */ +#define DW_AT_SUN_dtor_state_initial 0x2233 /* SUN */ +#define DW_AT_SUN_dtor_state_final 0x2234 /* SUN */ +#define DW_AT_SUN_dtor_state_deltas 0x2235 /* SUN */ +#define DW_AT_SUN_import_by_lname 0x2236 /* SUN */ +#define DW_AT_SUN_f90_use_only 0x2237 /* SUN */ +#define DW_AT_SUN_namelist_spec 0x2238 /* SUN */ +#define DW_AT_SUN_is_omp_child_func 0x2239 /* SUN */ +#define DW_AT_SUN_fortran_main_alias 0x223a /* SUN */ +#define DW_AT_SUN_fortran_based 0x223b /* SUN */ + +/* UPC extension */ +#define DW_AT_upc_threads_scaled 0x3210 /* UPC */ + +/* PGI (STMicroelectronics) extensions. */ +#define DW_AT_PGI_lbase 0x3a00 /* PGI. Block, constant, reference. This attribute is an ASTPLAB extension used to describe the array local base. */ +#define DW_AT_PGI_soffset 0x3a01 /* PGI. Block, constant, reference. ASTPLAB adds this attribute to describe the section offset, or the offset to the first element in the dimension. */ +#define DW_AT_PGI_lstride 0x3a02 /* PGI. Block, constant, reference. ASTPLAB adds this attribute to describe the linear stride or the distance between elements in the dimension. */ + +/* Apple Extensions for closures */ +#define DW_AT_APPLE_closure 0x3fe4 /* Apple */ +/* Apple Extensions for Objective-C runtime info */ +#define DW_AT_APPLE_major_runtime_vers 0x3fe5 /* Apple */ +#define DW_AT_APPLE_runtime_class 0x3fe6 /* Apple */ + + +#define DW_AT_hi_user 0x3fff + +#define DW_OP_addr 0x03 +#define DW_OP_deref 0x06 +#define DW_OP_const1u 0x08 +#define DW_OP_const1s 0x09 +#define DW_OP_const2u 0x0a +#define DW_OP_const2s 0x0b +#define DW_OP_const4u 0x0c +#define DW_OP_const4s 0x0d +#define DW_OP_const8u 0x0e +#define DW_OP_const8s 0x0f +#define DW_OP_constu 0x10 +#define DW_OP_consts 0x11 +#define DW_OP_dup 0x12 +#define DW_OP_drop 0x13 +#define DW_OP_over 0x14 +#define DW_OP_pick 0x15 +#define DW_OP_swap 0x16 +#define DW_OP_rot 0x17 +#define DW_OP_xderef 0x18 +#define DW_OP_abs 0x19 +#define DW_OP_and 0x1a +#define DW_OP_div 0x1b +#define DW_OP_minus 0x1c +#define DW_OP_mod 0x1d +#define DW_OP_mul 0x1e +#define DW_OP_neg 0x1f +#define DW_OP_not 0x20 +#define DW_OP_or 0x21 +#define DW_OP_plus 0x22 +#define DW_OP_plus_uconst 0x23 +#define DW_OP_shl 0x24 +#define DW_OP_shr 0x25 +#define DW_OP_shra 0x26 +#define DW_OP_xor 0x27 +#define DW_OP_bra 0x28 +#define DW_OP_eq 0x29 +#define DW_OP_ge 0x2a +#define DW_OP_gt 0x2b +#define DW_OP_le 0x2c +#define DW_OP_lt 0x2d +#define DW_OP_ne 0x2e +#define DW_OP_skip 0x2f +#define DW_OP_lit0 0x30 +#define DW_OP_lit1 0x31 +#define DW_OP_lit2 0x32 +#define DW_OP_lit3 0x33 +#define DW_OP_lit4 0x34 +#define DW_OP_lit5 0x35 +#define DW_OP_lit6 0x36 +#define DW_OP_lit7 0x37 +#define DW_OP_lit8 0x38 +#define DW_OP_lit9 0x39 +#define DW_OP_lit10 0x3a +#define DW_OP_lit11 0x3b +#define DW_OP_lit12 0x3c +#define DW_OP_lit13 0x3d +#define DW_OP_lit14 0x3e +#define DW_OP_lit15 0x3f +#define DW_OP_lit16 0x40 +#define DW_OP_lit17 0x41 +#define DW_OP_lit18 0x42 +#define DW_OP_lit19 0x43 +#define DW_OP_lit20 0x44 +#define DW_OP_lit21 0x45 +#define DW_OP_lit22 0x46 +#define DW_OP_lit23 0x47 +#define DW_OP_lit24 0x48 +#define DW_OP_lit25 0x49 +#define DW_OP_lit26 0x4a +#define DW_OP_lit27 0x4b +#define DW_OP_lit28 0x4c +#define DW_OP_lit29 0x4d +#define DW_OP_lit30 0x4e +#define DW_OP_lit31 0x4f +#define DW_OP_reg0 0x50 +#define DW_OP_reg1 0x51 +#define DW_OP_reg2 0x52 +#define DW_OP_reg3 0x53 +#define DW_OP_reg4 0x54 +#define DW_OP_reg5 0x55 +#define DW_OP_reg6 0x56 +#define DW_OP_reg7 0x57 +#define DW_OP_reg8 0x58 +#define DW_OP_reg9 0x59 +#define DW_OP_reg10 0x5a +#define DW_OP_reg11 0x5b +#define DW_OP_reg12 0x5c +#define DW_OP_reg13 0x5d +#define DW_OP_reg14 0x5e +#define DW_OP_reg15 0x5f +#define DW_OP_reg16 0x60 +#define DW_OP_reg17 0x61 +#define DW_OP_reg18 0x62 +#define DW_OP_reg19 0x63 +#define DW_OP_reg20 0x64 +#define DW_OP_reg21 0x65 +#define DW_OP_reg22 0x66 +#define DW_OP_reg23 0x67 +#define DW_OP_reg24 0x68 +#define DW_OP_reg25 0x69 +#define DW_OP_reg26 0x6a +#define DW_OP_reg27 0x6b +#define DW_OP_reg28 0x6c +#define DW_OP_reg29 0x6d +#define DW_OP_reg30 0x6e +#define DW_OP_reg31 0x6f +#define DW_OP_breg0 0x70 +#define DW_OP_breg1 0x71 +#define DW_OP_breg2 0x72 +#define DW_OP_breg3 0x73 +#define DW_OP_breg4 0x74 +#define DW_OP_breg5 0x75 +#define DW_OP_breg6 0x76 +#define DW_OP_breg7 0x77 +#define DW_OP_breg8 0x78 +#define DW_OP_breg9 0x79 +#define DW_OP_breg10 0x7a +#define DW_OP_breg11 0x7b +#define DW_OP_breg12 0x7c +#define DW_OP_breg13 0x7d +#define DW_OP_breg14 0x7e +#define DW_OP_breg15 0x7f +#define DW_OP_breg16 0x80 +#define DW_OP_breg17 0x81 +#define DW_OP_breg18 0x82 +#define DW_OP_breg19 0x83 +#define DW_OP_breg20 0x84 +#define DW_OP_breg21 0x85 +#define DW_OP_breg22 0x86 +#define DW_OP_breg23 0x87 +#define DW_OP_breg24 0x88 +#define DW_OP_breg25 0x89 +#define DW_OP_breg26 0x8a +#define DW_OP_breg27 0x8b +#define DW_OP_breg28 0x8c +#define DW_OP_breg29 0x8d +#define DW_OP_breg30 0x8e +#define DW_OP_breg31 0x8f +#define DW_OP_regx 0x90 +#define DW_OP_fbreg 0x91 +#define DW_OP_bregx 0x92 +#define DW_OP_piece 0x93 +#define DW_OP_deref_size 0x94 +#define DW_OP_xderef_size 0x95 +#define DW_OP_nop 0x96 +#define DW_OP_push_object_address 0x97 /* DWARF3 */ +#define DW_OP_call2 0x98 /* DWARF3 */ +#define DW_OP_call4 0x99 /* DWARF3 */ +#define DW_OP_call_ref 0x9a /* DWARF3 */ +#define DW_OP_form_tls_address 0x9b /* DWARF3f */ +#define DW_OP_call_frame_cfa 0x9c /* DWARF3f */ +#define DW_OP_bit_piece 0x9d /* DWARF3f */ +#define DW_OP_implicit_value 0x9e /* DWARF4 */ +#define DW_OP_stack_value 0x9f /* DWARF4 */ + + + /* GNU extensions. */ +#define DW_OP_GNU_push_tls_address 0xe0 /* GNU */ + +/* Follows extension so dwarfdump prints the most-likely-useful name. */ +#define DW_OP_lo_user 0xe0 + + /* HP extensions. */ +#define DW_OP_HP_unknown 0xe0 /* HP conflict: GNU */ +#define DW_OP_HP_is_value 0xe1 /* HP */ +#define DW_OP_HP_fltconst4 0xe2 /* HP */ +#define DW_OP_HP_fltconst8 0xe3 /* HP */ +#define DW_OP_HP_mod_range 0xe4 /* HP */ +#define DW_OP_HP_unmod_range 0xe5 /* HP */ +#define DW_OP_HP_tls 0xe6 /* HP */ + +#define DW_OP_INTEL_bit_piece 0xe8 /* Intel: made obsolete by DW_OP_bit_piece above. */ + + + /* Apple extension. */ +#define DW_OP_APPLE_uninit 0xf0 /* Apple */ + +#define DW_OP_hi_user 0xff + +#define DW_ATE_address 0x1 +#define DW_ATE_boolean 0x2 +#define DW_ATE_complex_float 0x3 +#define DW_ATE_float 0x4 +#define DW_ATE_signed 0x5 +#define DW_ATE_signed_char 0x6 +#define DW_ATE_unsigned 0x7 +#define DW_ATE_unsigned_char 0x8 +#define DW_ATE_imaginary_float 0x9 /* DWARF3 */ +#define DW_ATE_packed_decimal 0xa /* DWARF3f */ +#define DW_ATE_numeric_string 0xb /* DWARF3f */ +#define DW_ATE_edited 0xc /* DWARF3f */ +#define DW_ATE_signed_fixed 0xd /* DWARF3f */ +#define DW_ATE_unsigned_fixed 0xe /* DWARF3f */ +#define DW_ATE_decimal_float 0xf /* DWARF3f */ + + +/* ALTIUM extensions. x80, x81 */ +#define DW_ATE_ALTIUM_fract 0x80 /* ALTIUM __fract type */ + +/* Follows extension so dwarfdump prints the most-likely-useful name. */ +#define DW_ATE_lo_user 0x80 + +/* Shown here to help dwarfdump build script. */ +#define DW_ATE_ALTIUM_accum 0x81 /* ALTIUM __accum type */ + +/* HP Floating point extensions. */ +#define DW_ATE_HP_float80 0x80 /* (80 bit). HP */ + + +#define DW_ATE_HP_complex_float80 0x81 /* Complex (80 bit). HP */ +#define DW_ATE_HP_float128 0x82 /* (128 bit). HP */ +#define DW_ATE_HP_complex_float128 0x83 /* Complex (128 bit). HP */ +#define DW_ATE_HP_floathpintel 0x84 /* (82 bit IA64). HP */ +#define DW_ATE_HP_imaginary_float80 0x85 /* HP */ +#define DW_ATE_HP_imaginary_float128 0x86 /* HP */ + +/* Sun extensions */ +#define DW_ATE_SUN_interval_float 0x91 +#define DW_ATE_SUN_imaginary_float 0x92 /* Obsolete: See DW_ATE_imaginary_float */ + +#define DW_ATE_hi_user 0xff + + +/* Decimal Sign codes. */ +#define DW_DS_unsigned 0x01 /* DWARF3f */ +#define DW_DS_leading_overpunch 0x02 /* DWARF3f */ +#define DW_DS_trailing_overpunch 0x03 /* DWARF3f */ +#define DW_DS_leading_separate 0x04 /* DWARF3f */ + +#define DW_DS_trailing_separate 0x05 /* DWARF3f */ + +/* Endian code name. */ +#define DW_END_default 0x00 /* DWARF3f */ +#define DW_END_big 0x01 /* DWARF3f */ +#define DW_END_little 0x02 /* DWARF3f */ + +#define DW_END_lo_user 0x40 /* DWARF3f */ +#define DW_END_hi_user 0xff /* DWARF3f */ + +/* For use with DW_TAG_SUN_codeflags + * If DW_TAG_SUN_codeflags is accepted as a dwarf standard, then + * standard dwarf ATCF entries start at 0x01 + */ +#define DW_ATCF_lo_user 0x40 /* SUN */ +#define DW_ATCF_SUN_mop_bitfield 0x41 /* SUN */ +#define DW_ATCF_SUN_mop_spill 0x42 /* SUN */ +#define DW_ATCF_SUN_mop_scopy 0x43 /* SUN */ +#define DW_ATCF_SUN_func_start 0x44 /* SUN */ +#define DW_ATCF_SUN_end_ctors 0x45 /* SUN */ +#define DW_ATCF_SUN_branch_target 0x46 /* SUN */ +#define DW_ATCF_SUN_mop_stack_probe 0x47 /* SUN */ +#define DW_ATCF_SUN_func_epilog 0x48 /* SUN */ +#define DW_ATCF_hi_user 0xff /* SUN */ + +/* Accessibility code name. */ +#define DW_ACCESS_public 0x01 +#define DW_ACCESS_protected 0x02 +#define DW_ACCESS_private 0x03 + +/* Visibility code name. */ +#define DW_VIS_local 0x01 +#define DW_VIS_exported 0x02 +#define DW_VIS_qualified 0x03 + +/* Virtuality code name. */ +#define DW_VIRTUALITY_none 0x00 +#define DW_VIRTUALITY_virtual 0x01 +#define DW_VIRTUALITY_pure_virtual 0x02 + +#define DW_LANG_C89 0x0001 +#define DW_LANG_C 0x0002 +#define DW_LANG_Ada83 0x0003 +#define DW_LANG_C_plus_plus 0x0004 +#define DW_LANG_Cobol74 0x0005 +#define DW_LANG_Cobol85 0x0006 +#define DW_LANG_Fortran77 0x0007 +#define DW_LANG_Fortran90 0x0008 +#define DW_LANG_Pascal83 0x0009 +#define DW_LANG_Modula2 0x000a +#define DW_LANG_Java 0x000b /* DWARF3 */ +#define DW_LANG_C99 0x000c /* DWARF3 */ +#define DW_LANG_Ada95 0x000d /* DWARF3 */ +#define DW_LANG_Fortran95 0x000e /* DWARF3 */ +#define DW_LANG_PLI 0x000f /* DWARF3 */ +#define DW_LANG_ObjC 0x0010 /* DWARF3f */ +#define DW_LANG_ObjC_plus_plus 0x0011 /* DWARF3f */ +#define DW_LANG_UPC 0x0012 /* DWARF3f */ +#define DW_LANG_D 0x0013 /* DWARF3f */ +#define DW_LANG_Python 0x0014 /* DWARF4 */ +/* The following 2 are not yet formally approved October 2010, but + it seems extremely likely they will be approved as the committee + chair agrees these should be ok and no one on the committee + has objected. */ +#define DW_LANG_OpenCL 0x0015 /* Provisionally DWARF5 */ +#define DW_LANG_Go 0x0016 /* Provisionally DWARF5 */ +#define DW_LANG_lo_user 0x8000 +#define DW_LANG_Mips_Assembler 0x8001 /* MIPS */ +#define DW_LANG_Upc 0x8765 /* UPC, use + DW_LANG_UPC instead. */ +/* ALTIUM extension */ +#define DW_LANG_ALTIUM_Assembler 0x9101 /* ALTIUM */ + +/* Sun extensions */ +#define DW_LANG_SUN_Assembler 0x9001 /* SUN */ + +#define DW_LANG_hi_user 0xffff + +/* Identifier case name. */ +#define DW_ID_case_sensitive 0x00 +#define DW_ID_up_case 0x01 +#define DW_ID_down_case 0x02 +#define DW_ID_case_insensitive 0x03 + +/* Calling Convention Name. */ +#define DW_CC_normal 0x01 +#define DW_CC_program 0x02 +#define DW_CC_nocall 0x03 +#define DW_CC_lo_user 0x40 + +/* ALTIUM extensions. */ +/* Function is an interrupt handler, return address on system stack. */ +#define DW_CC_ALTIUM_interrupt 0x65 /* ALTIUM*/ + +/* Near function model, return address on system stack. */ +#define DW_CC_ALTIUM_near_system_stack 0x66 /*ALTIUM */ + +/* Near function model, return address on user stack. */ +#define DW_CC_ALTIUM_near_user_stack 0x67 /* ALTIUM */ + +/* Huge function model, return address on user stack. */ +#define DW_CC_ALTIUM_huge_user_stack 0x68 /* ALTIUM */ + + +#define DW_CC_hi_user 0xff + +/* Inline Code Name. */ +#define DW_INL_not_inlined 0x00 +#define DW_INL_inlined 0x01 +#define DW_INL_declared_not_inlined 0x02 +#define DW_INL_declared_inlined 0x03 + +/* Ordering Name. */ +#define DW_ORD_row_major 0x00 +#define DW_ORD_col_major 0x01 + +/* Discriminant Descriptor Name. */ +#define DW_DSC_label 0x00 +#define DW_DSC_range 0x01 + +/* Line number standard opcode name. */ +#define DW_LNS_copy 0x01 +#define DW_LNS_advance_pc 0x02 +#define DW_LNS_advance_line 0x03 +#define DW_LNS_set_file 0x04 +#define DW_LNS_set_column 0x05 +#define DW_LNS_negate_stmt 0x06 +#define DW_LNS_set_basic_block 0x07 +#define DW_LNS_const_add_pc 0x08 +#define DW_LNS_fixed_advance_pc 0x09 +#define DW_LNS_set_prologue_end 0x0a /* DWARF3 */ +#define DW_LNS_set_epilogue_begin 0x0b /* DWARF3 */ +#define DW_LNS_set_isa 0x0c /* DWARF3 */ + +/* Line number extended opcode name. */ +#define DW_LNE_end_sequence 0x01 +#define DW_LNE_set_address 0x02 +#define DW_LNE_define_file 0x03 +#define DW_LNE_set_discriminator 0x04 /* DWARF4 */ + +/* HP extensions. */ +#define DW_LNE_HP_negate_is_UV_update 0x11 /* 17 HP */ +#define DW_LNE_HP_push_context 0x12 /* 18 HP */ +#define DW_LNE_HP_pop_context 0x13 /* 19 HP */ +#define DW_LNE_HP_set_file_line_column 0x14 /* 20 HP */ +#define DW_LNE_HP_set_routine_name 0x15 /* 21 HP */ +#define DW_LNE_HP_set_sequence 0x16 /* 22 HP */ +#define DW_LNE_HP_negate_post_semantics 0x17 /* 23 HP */ +#define DW_LNE_HP_negate_function_exit 0x18 /* 24 HP */ +#define DW_LNE_HP_negate_front_end_logical 0x19 /* 25 HP */ +#define DW_LNE_HP_define_proc 0x20 /* 32 HP */ + +#define DW_LNE_lo_user 0x80 /* DWARF3 */ +#define DW_LNE_hi_user 0xff /* DWARF3 */ + +/* These are known values for DW_LNS_set_isa. */ +#define DW_ISA_UNKNOWN 0 +/* The following two are ARM specific. */ +#define DW_ISA_ARM_thumb 1 /* ARM ISA */ +#define DW_ISA_ARM_arm 2 /* ARM ISA */ + +/* Macro information. */ +#define DW_MACINFO_define 0x01 +#define DW_MACINFO_undef 0x02 +#define DW_MACINFO_start_file 0x03 +#define DW_MACINFO_end_file 0x04 +#define DW_MACINFO_vendor_ext 0xff + +/* CFA operator compaction (a space saving measure, see + the DWARF standard) means DW_CFA_extended and DW_CFA_nop + have the same value here. */ +#define DW_CFA_advance_loc 0x40 +#define DW_CFA_offset 0x80 +#define DW_CFA_restore 0xc0 +#define DW_CFA_extended 0 + +#define DW_CFA_nop 0x00 +#define DW_CFA_set_loc 0x01 +#define DW_CFA_advance_loc1 0x02 +#define DW_CFA_advance_loc2 0x03 +#define DW_CFA_advance_loc4 0x04 +#define DW_CFA_offset_extended 0x05 +#define DW_CFA_restore_extended 0x06 +#define DW_CFA_undefined 0x07 +#define DW_CFA_same_value 0x08 +#define DW_CFA_register 0x09 +#define DW_CFA_remember_state 0x0a +#define DW_CFA_restore_state 0x0b +#define DW_CFA_def_cfa 0x0c +#define DW_CFA_def_cfa_register 0x0d +#define DW_CFA_def_cfa_offset 0x0e +#define DW_CFA_def_cfa_expression 0x0f /* DWARF3 */ +#define DW_CFA_expression 0x10 /* DWARF3 */ +#define DW_CFA_offset_extended_sf 0x11 /* DWARF3 */ +#define DW_CFA_def_cfa_sf 0x12 /* DWARF3 */ +#define DW_CFA_def_cfa_offset_sf 0x13 /* DWARF3 */ +#define DW_CFA_val_offset 0x14 /* DWARF3f */ +#define DW_CFA_val_offset_sf 0x15 /* DWARF3f */ +#define DW_CFA_val_expression 0x16 /* DWARF3f */ + +#define DW_CFA_lo_user 0x1c +#define DW_CFA_low_user 0x1c /* Incorrect spelling, do not use. */ + +/* SGI/MIPS extension. */ +#define DW_CFA_MIPS_advance_loc8 0x1d /* MIPS */ + +/* GNU extensions. */ +#define DW_CFA_GNU_window_save 0x2d /* GNU */ +#define DW_CFA_GNU_args_size 0x2e /* GNU */ +#define DW_CFA_GNU_negative_offset_extended 0x2f /* GNU */ + +#define DW_CFA_high_user 0x3f + +/* GNU exception header encoding. See the Generic + Elf Specification of the Linux Standard Base (LSB). + http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html + The upper 4 bits indicate how the value is to be applied. + The lower 4 bits indicate the format of the data. +*/ +#define DW_EH_PE_absptr 0x00 /* GNU */ +#define DW_EH_PE_uleb128 0x01 /* GNU */ +#define DW_EH_PE_udata2 0x02 /* GNU */ +#define DW_EH_PE_udata4 0x03 /* GNU */ +#define DW_EH_PE_udata8 0x04 /* GNU */ +#define DW_EH_PE_sleb128 0x09 /* GNU */ +#define DW_EH_PE_sdata2 0x0A /* GNU */ +#define DW_EH_PE_sdata4 0x0B /* GNU */ +#define DW_EH_PE_sdata8 0x0C /* GNU */ + +#define DW_EH_PE_pcrel 0x10 /* GNU */ +#define DW_EH_PE_textrel 0x20 /* GNU */ +#define DW_EH_PE_datarel 0x30 /* GNU */ +#define DW_EH_PE_funcrel 0x40 /* GNU */ +#define DW_EH_PE_aligned 0x50 /* GNU */ + +#define DW_EH_PE_omit 0xff /* GNU. Means no value present. */ + + +/* Mapping from machine registers and pseudo-regs into the .debug_frame table. + DW_FRAME entries are machine specific. These describe + MIPS/SGI R3000, R4K, R4400 and all later MIPS/SGI IRIX machines. + They describe a mapping from hardware register number to + the number used in the table to identify that register. + + The CFA (Canonical Frame Address) described in DWARF is called + the Virtual Frame Pointer on MIPS/SGI machines. + + The DW_FRAME* names here are MIPS/SGI specfic. + Libdwarf interfaces defined in 2008 make the + frame definitions + here (and the fixed table sizes they imply) obsolete. + They are left here for compatibility. +*/ +/* Default column used for CFA in the libdwarf reader client. + Assumes reg 0 never appears as + a register in DWARF information. Usable for MIPS, + but never a good idea, really. */ +#define DW_FRAME_CFA_COL 0 + +#define DW_FRAME_REG1 1 /* integer reg 1 */ +#define DW_FRAME_REG2 2 /* integer reg 2 */ +#define DW_FRAME_REG3 3 /* integer reg 3 */ +#define DW_FRAME_REG4 4 /* integer reg 4 */ +#define DW_FRAME_REG5 5 /* integer reg 5 */ +#define DW_FRAME_REG6 6 /* integer reg 6 */ +#define DW_FRAME_REG7 7 /* integer reg 7 */ +#define DW_FRAME_REG8 8 /* integer reg 8 */ +#define DW_FRAME_REG9 9 /* integer reg 9 */ +#define DW_FRAME_REG10 10 /* integer reg 10 */ +#define DW_FRAME_REG11 11 /* integer reg 11 */ +#define DW_FRAME_REG12 12 /* integer reg 12 */ +#define DW_FRAME_REG13 13 /* integer reg 13 */ +#define DW_FRAME_REG14 14 /* integer reg 14 */ +#define DW_FRAME_REG15 15 /* integer reg 15 */ +#define DW_FRAME_REG16 16 /* integer reg 16 */ +#define DW_FRAME_REG17 17 /* integer reg 17 */ +#define DW_FRAME_REG18 18 /* integer reg 18 */ +#define DW_FRAME_REG19 19 /* integer reg 19 */ +#define DW_FRAME_REG20 20 /* integer reg 20 */ +#define DW_FRAME_REG21 21 /* integer reg 21 */ +#define DW_FRAME_REG22 22 /* integer reg 22 */ +#define DW_FRAME_REG23 23 /* integer reg 23 */ +#define DW_FRAME_REG24 24 /* integer reg 24 */ +#define DW_FRAME_REG25 25 /* integer reg 25 */ +#define DW_FRAME_REG26 26 /* integer reg 26 */ +#define DW_FRAME_REG27 27 /* integer reg 27 */ +#define DW_FRAME_REG28 28 /* integer reg 28 */ +#define DW_FRAME_REG29 29 /* integer reg 29 */ +#define DW_FRAME_REG30 30 /* integer reg 30 */ +#define DW_FRAME_REG31 31 /* integer reg 31, aka ra */ + + /* MIPS1, 2 have only some of these 64-bit registers. + ** MIPS1 save/restore takes 2 instructions per 64-bit reg, and + ** in that case, the register is considered stored after the second + ** swc1. + */ +#define DW_FRAME_FREG0 32 /* 64-bit floating point reg 0 */ +#define DW_FRAME_FREG1 33 /* 64-bit floating point reg 1 */ +#define DW_FRAME_FREG2 34 /* 64-bit floating point reg 2 */ +#define DW_FRAME_FREG3 35 /* 64-bit floating point reg 3 */ +#define DW_FRAME_FREG4 36 /* 64-bit floating point reg 4 */ +#define DW_FRAME_FREG5 37 /* 64-bit floating point reg 5 */ +#define DW_FRAME_FREG6 38 /* 64-bit floating point reg 6 */ +#define DW_FRAME_FREG7 39 /* 64-bit floating point reg 7 */ +#define DW_FRAME_FREG8 40 /* 64-bit floating point reg 8 */ +#define DW_FRAME_FREG9 41 /* 64-bit floating point reg 9 */ +#define DW_FRAME_FREG10 42 /* 64-bit floating point reg 10 */ +#define DW_FRAME_FREG11 43 /* 64-bit floating point reg 11 */ +#define DW_FRAME_FREG12 44 /* 64-bit floating point reg 12 */ +#define DW_FRAME_FREG13 45 /* 64-bit floating point reg 13 */ +#define DW_FRAME_FREG14 46 /* 64-bit floating point reg 14 */ +#define DW_FRAME_FREG15 47 /* 64-bit floating point reg 15 */ +#define DW_FRAME_FREG16 48 /* 64-bit floating point reg 16 */ +#define DW_FRAME_FREG17 49 /* 64-bit floating point reg 17 */ +#define DW_FRAME_FREG18 50 /* 64-bit floating point reg 18 */ +#define DW_FRAME_FREG19 51 /* 64-bit floating point reg 19 */ +#define DW_FRAME_FREG20 52 /* 64-bit floating point reg 20 */ +#define DW_FRAME_FREG21 53 /* 64-bit floating point reg 21 */ +#define DW_FRAME_FREG22 54 /* 64-bit floating point reg 22 */ +#define DW_FRAME_FREG23 55 /* 64-bit floating point reg 23 */ +#define DW_FRAME_FREG24 56 /* 64-bit floating point reg 24 */ +#define DW_FRAME_FREG25 57 /* 64-bit floating point reg 25 */ +#define DW_FRAME_FREG26 58 /* 64-bit floating point reg 26 */ +#define DW_FRAME_FREG27 59 /* 64-bit floating point reg 27 */ +#define DW_FRAME_FREG28 60 /* 64-bit floating point reg 28 */ +#define DW_FRAME_FREG29 61 /* 64-bit floating point reg 29 */ +#define DW_FRAME_FREG30 62 /* 64-bit floating point reg 30 */ +#define DW_FRAME_FREG31 63 /* 64-bit floating point reg 31 */ + +/* ***IMPORTANT NOTE, TARGET DEPENDENCY **** + The following 4 #defines are dependent on + the target cpu(s) that you apply libdwarf to. + Ensure that DW_FRAME_UNDEFINED_VAL and DW_FRAME_SAME_VAL + do not conflict with the range [0-DW_FRAME_STATIC_LINK]. + The value 63 works for MIPS cpus at least up to the R16000. + + For a cpu with more than 63 real registers + DW_FRAME_HIGHEST_NORMAL_REGISTER + must be increased for things to work properly! + Also ensure that DW_FRAME_UNDEFINED_VAL DW_FRAME_SAME_VAL + are not in the range [0-DW_FRAME_STATIC_LINK] + + Having DW_FRAME_HIGHEST_NORMAL_REGISTER be higher than + is strictly needed is safe. + +*/ + +#ifndef DW_FRAME_HIGHEST_NORMAL_REGISTER +#define DW_FRAME_HIGHEST_NORMAL_REGISTER 63 +#endif +/* This is the number of columns in the Frame Table. + This constant should + be kept in sync with DW_REG_TABLE_SIZE defined in libdwarf.h + It must also be large enough to be beyond the highest + compiler-defined-register (meaning DW_FRAME_RA_COL DW_FRAME_STATIC_LINK + in the MIPS/IRIX case */ +#ifndef DW_FRAME_LAST_REG_NUM +#define DW_FRAME_LAST_REG_NUM (DW_FRAME_HIGHEST_NORMAL_REGISTER + 3) +#endif + + +/* Column recording ra (return address from a function call). + This is common to many architectures, but as a 'simple register' + is not necessarily adequate for all architectures. + For MIPS/IRIX this register number is actually recorded on disk + in the .debug_frame section. + */ +#define DW_FRAME_RA_COL (DW_FRAME_HIGHEST_NORMAL_REGISTER + 1) + +/* Column recording static link applicable to up-level + addressing, as in IRIX mp code, pascal, etc. + This is common to many architectures but + is not necessarily adequate for all architectures. + For MIPS/IRIX this register number is actually recorded on disk + in the .debug_frame section. +*/ +#define DW_FRAME_STATIC_LINK (DW_FRAME_HIGHEST_NORMAL_REGISTER + 2) + + + +/* + DW_FRAME_UNDEFINED_VAL and DW_FRAME_SAME_VAL are + never on disk, just generated by libdwarf. See libdwarf.h + for their values. +*/ + + + +#define DW_CHILDREN_no 0x00 +#define DW_CHILDREN_yes 0x01 + +#define DW_ADDR_none 0 + +#ifdef __cplusplus +} +#endif +#endif /* __DWARF_H */ diff --git a/usr/src/lib/libdwarf/common/dwarf_abbrev.c b/usr/src/lib/libdwarf/common/dwarf_abbrev.c new file mode 100644 index 0000000000..c2ae361f33 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_abbrev.c @@ -0,0 +1,259 @@ +/* + + Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the above address. +*/ + + + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include "dwarf_abbrev.h" + +int +dwarf_get_abbrev(Dwarf_Debug dbg, + Dwarf_Unsigned offset, + Dwarf_Abbrev * returned_abbrev, + Dwarf_Unsigned * length, + Dwarf_Unsigned * abbr_count, Dwarf_Error * error) +{ + Dwarf_Small *abbrev_ptr = 0; + Dwarf_Small *abbrev_section_end = 0; + Dwarf_Half attr = 0; + Dwarf_Half attr_form = 0; + Dwarf_Abbrev ret_abbrev = 0; + Dwarf_Unsigned labbr_count = 0; + Dwarf_Unsigned utmp = 0; + + + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + if (dbg->de_debug_abbrev.dss_data == 0) { + /* Loads abbrev section (and .debug_info as we do those + together). */ + int res = _dwarf_load_debug_info(dbg, error); + + if (res != DW_DLV_OK) { + return res; + } + } + + if (offset >= dbg->de_debug_abbrev.dss_size) { + return (DW_DLV_NO_ENTRY); + } + + + ret_abbrev = (Dwarf_Abbrev) _dwarf_get_alloc(dbg, DW_DLA_ABBREV, 1); + if (ret_abbrev == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + ret_abbrev->ab_dbg = dbg; + if (returned_abbrev == 0 || abbr_count == 0) { + dwarf_dealloc(dbg, ret_abbrev, DW_DLA_ABBREV); + _dwarf_error(dbg, error, DW_DLE_DWARF_ABBREV_NULL); + return (DW_DLV_ERROR); + } + + + *abbr_count = 0; + if (length != NULL) + *length = 1; + + abbrev_ptr = dbg->de_debug_abbrev.dss_data + offset; + abbrev_section_end = + dbg->de_debug_abbrev.dss_data + dbg->de_debug_abbrev.dss_size; + + DECODE_LEB128_UWORD(abbrev_ptr, utmp); + ret_abbrev->ab_code = (Dwarf_Word) utmp; + if (ret_abbrev->ab_code == 0) { + *returned_abbrev = ret_abbrev; + *abbr_count = 0; + if (length) { + *length = 1; + } + return (DW_DLV_OK); + } + + DECODE_LEB128_UWORD(abbrev_ptr, utmp); + ret_abbrev->ab_tag = utmp; + ret_abbrev->ab_has_child = *(abbrev_ptr++); + ret_abbrev->ab_abbrev_ptr = abbrev_ptr; + + do { + Dwarf_Unsigned utmp2; + + DECODE_LEB128_UWORD(abbrev_ptr, utmp2); + attr = (Dwarf_Half) utmp2; + DECODE_LEB128_UWORD(abbrev_ptr, utmp2); + attr_form = (Dwarf_Half) utmp2; + + if (attr != 0) + (labbr_count)++; + + } while (abbrev_ptr < abbrev_section_end && + (attr != 0 || attr_form != 0)); + + if (abbrev_ptr > abbrev_section_end) { + dwarf_dealloc(dbg, ret_abbrev, DW_DLA_ABBREV); + _dwarf_error(dbg, error, DW_DLE_ABBREV_DECODE_ERROR); + return (DW_DLV_ERROR); + } + + if (length != NULL) + *length = abbrev_ptr - dbg->de_debug_abbrev.dss_data - offset; + + *returned_abbrev = ret_abbrev; + *abbr_count = labbr_count; + return (DW_DLV_OK); +} + +int +dwarf_get_abbrev_code(Dwarf_Abbrev abbrev, + Dwarf_Unsigned * returned_code, + Dwarf_Error * error) +{ + if (abbrev == NULL) { + _dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL); + return (DW_DLV_ERROR); + } + + *returned_code = abbrev->ab_code; + return (DW_DLV_OK); +} + +/* DWARF defines DW_TAG_hi_user as 0xffff so no tag should be + over 16 bits. */ +int +dwarf_get_abbrev_tag(Dwarf_Abbrev abbrev, + Dwarf_Half * returned_tag, Dwarf_Error * error) +{ + if (abbrev == NULL) { + _dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL); + return (DW_DLV_ERROR); + } + + *returned_tag = abbrev->ab_tag; + return (DW_DLV_OK); +} + + +int +dwarf_get_abbrev_children_flag(Dwarf_Abbrev abbrev, + Dwarf_Signed * returned_flag, + Dwarf_Error * error) +{ + if (abbrev == NULL) { + _dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL); + return (DW_DLV_ERROR); + } + + *returned_flag = abbrev->ab_has_child; + return (DW_DLV_OK); +} + + +int +dwarf_get_abbrev_entry(Dwarf_Abbrev abbrev, + Dwarf_Signed index, + Dwarf_Half * returned_attr_num, + Dwarf_Signed * form, + Dwarf_Off * offset, Dwarf_Error * error) +{ + Dwarf_Byte_Ptr abbrev_ptr = 0; + Dwarf_Byte_Ptr abbrev_end = 0; + Dwarf_Byte_Ptr mark_abbrev_ptr = 0; + Dwarf_Half attr = 0; + Dwarf_Half attr_form = 0; + + if (index < 0) + return (DW_DLV_NO_ENTRY); + + if (abbrev == NULL) { + _dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL); + return (DW_DLV_ERROR); + } + + if (abbrev->ab_code == 0) { + return (DW_DLV_NO_ENTRY); + } + + if (abbrev->ab_dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + + abbrev_ptr = abbrev->ab_abbrev_ptr; + abbrev_end = + abbrev->ab_dbg->de_debug_abbrev.dss_data + + abbrev->ab_dbg->de_debug_abbrev.dss_size; + + for (attr = 1, attr_form = 1; + index >= 0 && abbrev_ptr < abbrev_end && (attr != 0 || + attr_form != 0); + index--) { + Dwarf_Unsigned utmp4; + + mark_abbrev_ptr = abbrev_ptr; + DECODE_LEB128_UWORD(abbrev_ptr, utmp4); + attr = (Dwarf_Half) utmp4; + DECODE_LEB128_UWORD(abbrev_ptr, utmp4); + attr_form = (Dwarf_Half) utmp4; + } + + if (abbrev_ptr >= abbrev_end) { + _dwarf_error(abbrev->ab_dbg, error, DW_DLE_ABBREV_DECODE_ERROR); + return (DW_DLV_ERROR); + } + + if (index >= 0) { + return (DW_DLV_NO_ENTRY); + } + + if (form != NULL) + *form = attr_form; + if (offset != NULL) + *offset = mark_abbrev_ptr - abbrev->ab_dbg->de_debug_abbrev.dss_data; + + *returned_attr_num = (attr); + return DW_DLV_OK; +} diff --git a/usr/src/lib/libdwarf/common/dwarf_abbrev.h b/usr/src/lib/libdwarf/common/dwarf_abbrev.h new file mode 100644 index 0000000000..b525924c83 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_abbrev.h @@ -0,0 +1,55 @@ +/* + + Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2008-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + + +/* In a given CU, one of these is (eventually) set up + for every abbreviation we need to find (and for all. + those ealier in the abbreviations for that CU). + So we don't want elements needlessly big. +*/ +struct Dwarf_Abbrev_s { + /* No TAG should exceed DW_TAG_hi_user, 0xffff, but + we do allow a larger value here. */ + Dwarf_Word ab_tag; + /* Abbreviations are numbered (normally sequentially from + 1 and so 16 bits is not enough! */ + Dwarf_Word ab_code; + Dwarf_Small ab_has_child; + Dwarf_Byte_Ptr ab_abbrev_ptr; + Dwarf_Debug ab_dbg; +}; diff --git a/usr/src/lib/libdwarf/common/dwarf_addr_finder.c b/usr/src/lib/libdwarf/common/dwarf_addr_finder.c new file mode 100644 index 0000000000..2fadefc1ea --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_addr_finder.c @@ -0,0 +1,685 @@ +/* + + Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* This code used by SGI-IRIX rqs processing, not needed by + any other system or application. +*/ + +#include "config.h" +#include "libdwarfdefs.h" +#ifdef HAVE_ELF_H +#include +#endif +#include +#include +#include "dwarf_base_types.h" +#include "dwarf_alloc.h" +#include "dwarf_opaque.h" +#include "dwarf_arange.h" +#include "dwarf_line.h" +#include "dwarf_frame.h" +#include +#include "dwarf_error.h" + +typedef unsigned long long ull; + +static int do_this_die_and_dealloc(Dwarf_Debug dbg, Dwarf_Die die, + int *errval); +static int + handle_debug_info(Dwarf_Debug dbg, int *errval); +static int + handle_debug_frame(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func, int *errval); +static int + handle_debug_aranges(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func, int *errval); +static int + handle_debug_line(Dwarf_Debug dbg, Dwarf_Die cu_die, Dwarf_addr_callback_func cb_func, int *errval); +static int + handle_debug_loc(void); + + +static Dwarf_addr_callback_func send_addr_note; + +int +_dwarf_addr_finder(dwarf_elf_handle elf_file_ptr, + Dwarf_addr_callback_func cb_func, int *dwerr) +{ + + Dwarf_Error err = 0; + Dwarf_Debug dbg = 0; + int res = 0; + int errval = 0; + int sections_found = 0; + + res = dwarf_elf_init(elf_file_ptr, DW_DLC_READ, /* errhand */ 0, + /* errarg */ 0, &dbg, &err); + if (res == DW_DLV_ERROR) { + int errv = (int) dwarf_errno(err); + + return errv; + } + if (res == DW_DLV_NO_ENTRY) { + return res; + } + + send_addr_note = cb_func; + + res = handle_debug_info(dbg, &errval); + switch (res) { + case DW_DLV_OK: + ++sections_found; + break; + case DW_DLV_NO_ENTRY: + + break; + default: + case DW_DLV_ERROR: + dwarf_finish(dbg, &err); + *dwerr = errval; + return res; + } + + res = handle_debug_aranges(dbg, cb_func, &errval); + switch (res) { + case DW_DLV_OK: + ++sections_found; + break; + case DW_DLV_NO_ENTRY: + break; + default: + case DW_DLV_ERROR: + dwarf_finish(dbg, &err); + *dwerr = errval; + return res; + } + res = handle_debug_frame(dbg, cb_func, &errval); + switch (res) { + case DW_DLV_OK: + ++sections_found; + break; + case DW_DLV_NO_ENTRY: + break; + default: + case DW_DLV_ERROR: + dwarf_finish(dbg, &err); + *dwerr = errval; + return res; + } + + res = handle_debug_loc(); /* does nothing */ + switch (res) { + case DW_DLV_OK: + ++sections_found; + break; + case DW_DLV_NO_ENTRY: + break; + default: + case DW_DLV_ERROR: + /* IMPOSSIBLE : handle_debug_loc cannot return this */ + dwarf_finish(dbg, &err); + *dwerr = errval; + return res; + } + + + + *dwerr = 0; + res = dwarf_finish(dbg, &err); + if (res == DW_DLV_ERROR) { + *dwerr = (int) dwarf_errno(err); + return DW_DLV_ERROR; + } + if (sections_found == 0) { + return DW_DLV_NO_ENTRY; + } + return DW_DLV_OK; + +} + +/* + Return DW_DLV_OK, ERROR, or NO_ENTRY. +*/ +static int +handle_debug_info(Dwarf_Debug dbg, int *errval) +{ + Dwarf_Unsigned nxtoff = 1; + Dwarf_Unsigned hdr_length; + Dwarf_Half version_stamp; + Dwarf_Unsigned abbrev_offset; + Dwarf_Half addr_size; + Dwarf_Error err; + int terminate_now = 0; + int res = 0; + Dwarf_Die sibdie; + int sibres; + int nres = DW_DLV_OK; + + + for (nres = dwarf_next_cu_header(dbg, &hdr_length, &version_stamp, + &abbrev_offset, + &addr_size, &nxtoff, &err); + terminate_now == 0 && nres == DW_DLV_OK; + nres = dwarf_next_cu_header(dbg, &hdr_length, &version_stamp, + &abbrev_offset, + &addr_size, &nxtoff, &err) + ) { + + Dwarf_Die curdie = 0; + + /* try to get the compilation unit die */ + sibres = dwarf_siblingof(dbg, curdie, &sibdie, &err); + if (sibres == DW_DLV_OK) { + res = do_this_die_and_dealloc(dbg, sibdie, errval); + switch (res) { + case DW_DLV_OK: + break; + case DW_DLV_NO_ENTRY: + break; + default: + case DW_DLV_ERROR: + return DW_DLV_ERROR; + } + } else if (sibres == DW_DLV_ERROR) { + *errval = (int) dwarf_errno(err); + return DW_DLV_ERROR; + } else { + /* NO ENTRY! */ + /* impossible? */ + } + + } + if (nres == DW_DLV_ERROR) { + int localerr = (int) dwarf_errno(err); + + *errval = localerr; + return DW_DLV_ERROR; + } + return DW_DLV_OK; +} + +static int + might_have_addr[] = { + DW_AT_high_pc, + DW_AT_low_pc, +}; +static int + might_have_locdesc[] = { + DW_AT_segment, + DW_AT_return_addr, + DW_AT_frame_base, + DW_AT_static_link, + DW_AT_data_member_location, + DW_AT_string_length, + DW_AT_location, + DW_AT_use_location, + DW_AT_vtable_elem_location, +}; + +/* + Return DW_DLV_OK if handling this went ok. +*/ +static int +handle_attr_addr(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attrnum, + Dwarf_Error * perr) +{ + int res = DW_DLV_OK; + Dwarf_Off offset; + Dwarf_Addr addr; + Dwarf_Half form; + int ares; + + Dwarf_Attribute attr; + + ares = dwarf_attr(die, attrnum, &attr, perr); + if (ares == DW_DLV_OK) { + int formres = dwarf_whatform(attr, &form, perr); + + switch (formres) { + case DW_DLV_OK: + break; + case DW_DLV_ERROR: + case DW_DLV_NO_ENTRY: /* impossible. */ + return formres; + + } + + switch (form) { + case DW_FORM_ref_addr: + case DW_FORM_addr: + res = dwarf_attr_offset(die, attr, &offset, perr); + if (res == DW_DLV_OK) { + ares = dwarf_formaddr(attr, &addr, perr); + if (ares == DW_DLV_OK) { + send_addr_note(DW_SECTION_INFO, offset, addr); + } else if (ares == DW_DLV_ERROR) { + return ares; + } /* no entry: ok. */ + } else { + res = DW_DLV_ERROR; /* NO_ENTRY is impossible. */ + } + break; + + default: + /* surprising! An error? */ + + ; /* do nothing */ + } + dwarf_dealloc(dbg, attr, DW_DLA_ATTR); + + } else { + res = ares; + } + return res; +} + +/* + Return DW_DLV_OK if handling this went ok. +*/ +static int +handle_attr_locdesc(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attrnum, + Dwarf_Error * perr) +{ + int retval = DW_DLV_OK; + Dwarf_Attribute attr; + Dwarf_Locdesc *llbuf; + Dwarf_Signed i; + Dwarf_Off offset; + Dwarf_Loc *locp; + unsigned int entindx; + int res; + int ares; + + + ares = dwarf_attr(die, attrnum, &attr, perr); + if (ares == DW_DLV_OK) { + Dwarf_Half form; + int fres = dwarf_whatform(attr, &form, perr); + + if (fres == DW_DLV_OK) { + switch (form) { + case DW_FORM_block1: + case DW_FORM_block2: + case DW_FORM_block4: + /* must be location description */ + res = dwarf_attr_offset(die, attr, &offset, perr); + llbuf = 0; + if (res == DW_DLV_OK) { + Dwarf_Signed count; + int lres = dwarf_loclist(attr, &llbuf, &count, perr); + if (lres != DW_DLV_OK) { + return lres; + } + if (count != 1) { + /* this cannot happen! */ + /* perr? */ + _dwarf_error(dbg, perr, + DW_DLE_LOCDESC_COUNT_WRONG); + retval = DW_DLV_ERROR; + return retval; + } + for (i = 0; i < count; ++i) { + unsigned int ents = llbuf[i].ld_cents; + + locp = llbuf[i].ld_s; + for (entindx = 0; entindx < ents; entindx++) { + Dwarf_Loc *llocp; + + llocp = locp + entindx; + if (llocp->lr_atom == DW_OP_addr) { + send_addr_note(DW_SECTION_INFO, offset + + llocp->lr_offset + 1 + /* The offset is the + offset of the atom, + ** and we know the + addr is 1 past it. */ + , llocp->lr_number); + } + } + } + + + if (count > 0) { + for (i = 0; i < count; ++i) { + dwarf_dealloc(dbg, llbuf[i].ld_s, + DW_DLA_LOC_BLOCK); + } + dwarf_dealloc(dbg, llbuf, DW_DLA_LOCDESC); + } + } else { + retval = res; + } + break; + + default: + /* must be a const offset in debug_loc */ + ; /* do nothing */ + } + dwarf_dealloc(dbg, attr, DW_DLA_ATTR); + } /* else error or no entry */ + retval = fres; + } else { + retval = ares; + } + return retval; +} + +/* + Return DW_DLV_OK, or DW_DLV_ERROR + + Handle the addrs in a single die. +*/ +static int +process_this_die_attrs(Dwarf_Debug dbg, Dwarf_Die newdie, int *errval) +{ + Dwarf_Error err; + Dwarf_Half i; + Dwarf_Half newattrnum; + int res; + int tres; + Dwarf_Half ltag; + + Dwarf_Off doff; + int doffres = dwarf_dieoffset(newdie, &doff, &err); + + if (doffres != DW_DLV_OK) { + if (doffres == DW_DLV_ERROR) { + *errval = (int) dwarf_errno(err); + } + return doffres; + } + tres = dwarf_tag(newdie, <ag, &err); + if (tres != DW_DLV_OK) { + return tres; + } + if (DW_TAG_compile_unit == ltag) { + /* because of the way the dwarf_line code works, we do lines + only per compile unit. This may turn out to be wrong if + we have lines left unconnected to a CU. of course such + lines will not, at present, be used by gnome. This is + not ideal as coded due to the dwarf_line.c issue. */ + int lres = handle_debug_line(dbg, newdie, send_addr_note, errval); + if (lres == DW_DLV_ERROR) { + return lres; + } + } + + for (i = 0; i < sizeof(might_have_addr) / sizeof(int); i++) { + int resattr; + Dwarf_Bool hasattr; + + newattrnum = might_have_addr[i]; + err = 0; + resattr = dwarf_hasattr(newdie, newattrnum, &hasattr, &err); + if (DW_DLV_OK == resattr) { + if (hasattr) { + res = handle_attr_addr(dbg, newdie, newattrnum, &err); + if (res != DW_DLV_OK) { + *errval = (int) dwarf_errno(err); + return DW_DLV_ERROR; + } + } + } else { + if (resattr == DW_DLV_ERROR) { + *errval = (int) dwarf_errno(err); + return resattr; + } + } + } + for (i = 0; i < sizeof(might_have_locdesc) / sizeof(int); i++) { + int resattr; + Dwarf_Bool hasattr; + + newattrnum = might_have_locdesc[i]; + err = 0; + resattr = dwarf_hasattr(newdie, newattrnum, &hasattr, &err); + if (DW_DLV_OK == resattr) { + if (hasattr) { + res = + handle_attr_locdesc(dbg, newdie, newattrnum, &err); + if (res != DW_DLV_OK) { + *errval = (int) dwarf_errno(err); + return DW_DLV_ERROR; + } + } + } else { + if (resattr == DW_DLV_ERROR) { + *errval = (int) dwarf_errno(err); + return resattr; + } + } + } + + return DW_DLV_OK; +} + +/* + Handle siblings as a list, + Do children by recursing. + Effectively this is walking the tree preorder. + + This dealloc's any die passed to it, so the + caller should not do that dealloc. + It seems more logical to have the one causing + the alloc to do the dealloc, but that way this + routine became a mess. + +*/ +static int +do_this_die_and_dealloc(Dwarf_Debug dbg, Dwarf_Die die, int *errval) +{ + + Dwarf_Die prevdie = 0; + Dwarf_Die newdie = die; + Dwarf_Error err = 0; + int res = 0; + int sibres = DW_DLV_OK; + int tres = DW_DLV_OK; + Dwarf_Die sibdie; + + while (sibres == DW_DLV_OK) { + Dwarf_Die ch_die; + + + res = process_this_die_attrs(dbg, newdie, errval); + switch (res) { + case DW_DLV_OK: + break; + case DW_DLV_NO_ENTRY: + break; + default: + case DW_DLV_ERROR: + if (prevdie) { + dwarf_dealloc(dbg, prevdie, DW_DLA_DIE); + prevdie = 0; + } + return DW_DLV_ERROR; + } + + tres = dwarf_child(newdie, &ch_die, &err); + + if (tres == DW_DLV_OK) { + res = do_this_die_and_dealloc(dbg, ch_die, errval); + switch (res) { + case DW_DLV_OK: + break; + case DW_DLV_NO_ENTRY: + break; + default: + case DW_DLV_ERROR: + if (prevdie) { + dwarf_dealloc(dbg, prevdie, DW_DLA_DIE); + prevdie = 0; + } + return DW_DLV_ERROR; + } + } else if (tres == DW_DLV_ERROR) { + /* An error! */ + *errval = (int) dwarf_errno(err); + if (prevdie) { + dwarf_dealloc(dbg, prevdie, DW_DLA_DIE); + prevdie = 0; + } + dwarf_dealloc(dbg, err, DW_DLA_ERROR); + return DW_DLV_ERROR; + } /* else was NO ENTRY */ + prevdie = newdie; + sibdie = 0; + sibres = dwarf_siblingof(dbg, newdie, &sibdie, &err); + if (prevdie) { + dwarf_dealloc(dbg, prevdie, DW_DLA_DIE); + prevdie = 0; + } + newdie = sibdie; + + } + if (sibres == DW_DLV_NO_ENTRY) { + return DW_DLV_OK; + } + /* error. */ + *errval = (int) dwarf_errno(err); + if (prevdie) { + dwarf_dealloc(dbg, prevdie, DW_DLA_DIE); + prevdie = 0; + } + dwarf_dealloc(dbg, err, DW_DLA_ERROR); + return DW_DLV_ERROR; + +} + + +static int +handle_debug_frame(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func, + int *errval) +{ + int retval = DW_DLV_OK; + int res; + Dwarf_Error err; + Dwarf_Addr *addrlist; + Dwarf_Off *offsetlist; + Dwarf_Signed count; + int i; + + res = + _dwarf_frame_address_offsets(dbg, &addrlist, &offsetlist, + &count, &err); + if (res == DW_DLV_OK) { + for (i = 0; i < count; i++) { + cb_func(DW_SECTION_FRAME, offsetlist[i], addrlist[i]); + } + dwarf_dealloc(dbg, offsetlist, DW_DLA_ADDR); + dwarf_dealloc(dbg, addrlist, DW_DLA_ADDR); + } else if (res == DW_DLV_NO_ENTRY) { + retval = res; + } else { + *errval = (int) dwarf_errno(err); + retval = DW_DLV_ERROR; + } + return retval; + +} +static int +handle_debug_aranges(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func, + int *errval) +{ + int retval = DW_DLV_OK; + Dwarf_Error err; + Dwarf_Addr *aranges; + Dwarf_Signed count; + int indx; + Dwarf_Off *offsets; + + retval = + _dwarf_get_aranges_addr_offsets(dbg, &aranges, &offsets, &count, + &err); + if (retval == DW_DLV_OK) { + if (count == 0) { + retval = DW_DLV_NO_ENTRY; + } else { + for (indx = 0; indx < count; indx++) { + cb_func(DW_SECTION_ARANGES, offsets[indx], + aranges[indx]); + } + } + dwarf_dealloc(dbg, aranges, DW_DLA_ADDR); + dwarf_dealloc(dbg, offsets, DW_DLA_ADDR); + } else if (retval == DW_DLV_NO_ENTRY) { + ; /* do nothing */ + } else { + *errval = (int) dwarf_errno(err); + retval = DW_DLV_ERROR; + } + return retval; +} +static int +handle_debug_line(Dwarf_Debug dbg, Dwarf_Die cu_die, + Dwarf_addr_callback_func cb_func, int *errval) +{ + int retval = DW_DLV_OK; + int res; + Dwarf_Error err; + Dwarf_Addr *addrlist; + Dwarf_Off *offsetlist; + Dwarf_Unsigned count; + Dwarf_Unsigned i; + + res = + _dwarf_line_address_offsets(dbg, cu_die, &addrlist, &offsetlist, + &count, &err); + if (res == DW_DLV_OK) { + for (i = 0; i < count; i++) { + cb_func(DW_SECTION_LINE, offsetlist[i], addrlist[i]); + + } + dwarf_dealloc(dbg, offsetlist, DW_DLA_ADDR); + dwarf_dealloc(dbg, addrlist, DW_DLA_ADDR); + } else if (res == DW_DLV_NO_ENTRY) { + retval = res; + } else { + *errval = (int) dwarf_errno(err); + retval = DW_DLV_ERROR; + } + return retval; +} + +/* + We need to add support for this. Currently we do not + generate this section. + FIX! +*/ +static int +handle_debug_loc(void) +{ + int retval = DW_DLV_NO_ENTRY; + + return retval; +} diff --git a/usr/src/lib/libdwarf/common/dwarf_alloc.c b/usr/src/lib/libdwarf/common/dwarf_alloc.c new file mode 100644 index 0000000000..ddb423e841 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_alloc.c @@ -0,0 +1,1258 @@ +/* + + Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + +#undef DEBUG + +#include "config.h" +#include "dwarf_incl.h" +#include + +#include +#include +#include "malloc_check.h" + +/* + These files are included to get the sizes + of structs to set the ah_bytes_one_struct field + of the Dwarf_Alloc_Hdr_s structs for each + allocation type. +*/ +#include "dwarf_line.h" +#include "dwarf_global.h" +#include "dwarf_arange.h" +#include "dwarf_abbrev.h" +#include "dwarf_die_deliv.h" +#include "dwarf_frame.h" +#include "dwarf_loc.h" +#include "dwarf_funcs.h" +#include "dwarf_types.h" +#include "dwarf_vars.h" +#include "dwarf_weaks.h" + + +static void _dwarf_free_special_error(Dwarf_Ptr space); + +#ifdef DWARF_SIMPLE_MALLOC +static void _dwarf_simple_malloc_add_to_list(Dwarf_Debug dbg, + Dwarf_Ptr addr, + unsigned long size, + short alloc_type); +static void _dwarf_simple_malloc_delete_from_list(Dwarf_Debug dbg, + Dwarf_Ptr space, + short alloc_type); +void _dwarf_simple_malloc_botch(int err); + +#endif /* DWARF_SIMPLE_MALLOC */ + + + + +/* + This macro adds the size of a pointer to the size of a + struct that is given to it. It rounds up the size to + be a multiple of the size of a pointer. This is done + so that every struct returned by _dwarf_get_alloc() + can be preceded by a pointer to the chunk it came from. + Before allocating, it checks if the size of struct is less than + the size of a pointer. If yes, it returns the size + of 2 pointers. The returned size should be at least + the size of 2 pointers, since the first points to the + chunk the struct was allocated from, and the second + is used to link the free list. + + We want DW_RESERVE to be at least the size of + a long long and at least the size of a pointer because + our struct has a long long and we want that aligned right. + Now Standard C defines long long as 8 bytes, so lets + make that standard. It will become unworkable when + long long or pointer grows beyound 8 bytes. + Unclear what to do with wierd requirements, like + 36 bit pointers. + + +*/ +#define DW_RESERVE 8 + +/* Round size up to the next multiple of DW_RESERVE bytes +*/ +#define ROUND_SIZE(inputsize) \ + (((inputsize) % (DW_RESERVE)) == 0 ? \ + (inputsize): \ + ((inputsize) + \ + (DW_RESERVE) - ((inputsize) % (DW_RESERVE)) )) + +#define ROUND_SIZE_WITH_POINTER(i_size) (ROUND_SIZE(i_size) + DW_RESERVE) + +/* SMALL_ALLOC is for trivia where allocation is a waste. + Things that should be removed, really. */ +#define SMALL_ALLOC 2 + +/* BASE_ALLOC is where a basic allocation makes sense, but 'not too large'. + No thorough evaluation of this value has been done, though + it was found wasteful of memory to have BASE_ALLOC be as large as + BIG_ALLOC. */ +#define BASE_ALLOC 64 + +/* BIG_ALLOC is where a larger-than-BASE_ALLOC + allocation makes sense, but still 'not too large'. + No thorough evaluation of this value has been done. */ +#define BIG_ALLOC 128 + +/* This translates into de_alloc_hdr index +** the 0,1,1 entries are special: they don't use the +** table values at all. +** Rearranging the DW_DLA values would break binary compatibility +** so that is not an option. +*/ +struct ial_s { + int ia_al_num; /* Index into de_alloc_hdr table. */ + + /* In bytes, one struct instance. This does not account for extra + space needed per block, but that (DW_RESERVE) will be added in + later where it is needed (DW_RESERVE space never added in here). + */ + int ia_struct_size; + + + /* Number of instances per alloc block. MUST be > 0. */ + int ia_base_count; + + int (*specialconstructor) (Dwarf_Debug, void *); + void (*specialdestructor) (void *); +}; + +static const +struct ial_s index_into_allocated[ALLOC_AREA_INDEX_TABLE_MAX] = { + {0, 1, 1, 0, 0}, /* none */ + {0, 1, 1, 0, 0}, /* 1 DW_DLA_STRING */ + {1, sizeof(Dwarf_Loc), BASE_ALLOC, 0, 0} + , /* 2 DW_DLA_LOC */ + {2, sizeof(Dwarf_Locdesc), BASE_ALLOC, 0, 0} + , /* 3 DW_DLA_LOCDESC */ + {0, 1, 1, 0, 0} + , /* not used *//* 4 DW_DLA_ELLIST */ + {0, 1, 1, 0, 0} + , /* not used *//* 5 DW_DLA_BOUNDS */ + {3, sizeof(Dwarf_Block), BASE_ALLOC, 0, 0} + , /* 6 DW_DLA_BLOCK */ + {0, 1, 1, 0, 0} + , /* the actual dwarf_debug structure *//* 7 DW_DLA_DEBUG */ + {4, sizeof(struct Dwarf_Die_s), BIG_ALLOC, 0, 0}, /* 8 DW_DLA_DIE + */ + {5, sizeof(struct Dwarf_Line_s), BIG_ALLOC, 0, 0}, /* 9 + DW_DLA_LINE */ + {6, sizeof(struct Dwarf_Attribute_s), BIG_ALLOC * 2, 0, 0}, + /* 10 DW_DLA_ATTR */ + {0, 1, 1, 0, 0}, /* not used *//* 11 DW_DLA_TYPE */ + {0, 1, 1, 0, 0}, /* not used *//* 12 DW_DLA_SUBSCR */ + {7, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0}, /* 13 + DW_DLA_GLOBAL + */ + {8, sizeof(struct Dwarf_Error_s), BASE_ALLOC, 0, 0}, /* 14 + DW_DLA_ERROR + */ + {0, 1, 1, 0, 0}, /* 15 DW_DLA_LIST */ + {0, 1, 1, 0, 0}, /* not used *//* 16 DW_DLA_LINEBUF */ + {9, sizeof(struct Dwarf_Arange_s), BASE_ALLOC, 0, 0}, /* 17 + DW_DLA_ARANGE + */ + {10, sizeof(struct Dwarf_Abbrev_s), BIG_ALLOC, 0, 0}, /* 18 + DW_DLA_ABBREV + */ + {11, sizeof(Dwarf_Frame_Op), BIG_ALLOC, 0, 0} + , /* 19 DW_DLA_FRAME_OP */ + {12, sizeof(struct Dwarf_Cie_s), BASE_ALLOC, 0, 0}, /* 20 + DW_DLA_CIE */ + {13, sizeof(struct Dwarf_Fde_s), BASE_ALLOC, 0, 0}, /* 21 DW_DLA_FDE */ + {0, 1, 1, 0, 0}, /* 22 DW_DLA_LOC_BLOCK */ + {0, 1, 1, 0, 0}, /* 23 DW_DLA_FRAME_BLOCK */ + {14, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0}, /* 24 DW_DLA_FUNC + UNUSED */ + {15, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0}, /* 25 + DW_DLA_TYPENAME + UNUSED */ + {16, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0}, /* 26 DW_DLA_VAR + UNUSED */ + {17, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0}, /* 27 DW_DLA_WEAK + UNUSED */ + {0, 1, 1, 0, 0}, /* 28 DW_DLA_ADDR */ + {0, 1,1,0,0 }, /* 29 DW_DLA_RANGES */ + + /* The following DW_DLA data types + are known only inside libdwarf. */ + + {18, sizeof(struct Dwarf_Abbrev_List_s), BIG_ALLOC, 0, 0}, + /* 30 DW_DLA_ABBREV_LIST */ + + {19, sizeof(struct Dwarf_Chain_s), BIG_ALLOC, 0, 0}, /* 31 DW_DLA_CHAIN */ + {20, sizeof(struct Dwarf_CU_Context_s), BASE_ALLOC, 0, 0}, + /* 32 DW_DLA_CU_CONTEXT */ + {21, sizeof(struct Dwarf_Frame_s), BASE_ALLOC, + _dwarf_frame_constructor, + _dwarf_frame_destructor}, /* 33 DW_DLA_FRAME */ + {22, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0}, + /* 34 DW_DLA_GLOBAL_CONTEXT */ + {23, sizeof(struct Dwarf_File_Entry_s), BASE_ALLOC, 0, 0}, /* 34 */ + /* 35 DW_DLA_FILE_ENTRY */ + {24, sizeof(struct Dwarf_Line_Context_s), BASE_ALLOC, 0, 0}, + /* 36 DW_DLA_LINE_CONTEXT */ + {25, sizeof(struct Dwarf_Loc_Chain_s), BASE_ALLOC, 0, 0}, /* 36 */ + /* 37 DW_DLA_LOC_CHAIN */ + + {26, sizeof(struct Dwarf_Hash_Table_s),BASE_ALLOC, 0, 0}, /* 37 */ + /* 38 DW_DLA_HASH_TABLE */ + +/* The following really use Global struct: used to be unique struct + per type, but now merged (11/99). The opaque types + are visible in the interface. The types for + DW_DLA_FUNC, + DW_DLA_TYPENAME, DW_DLA_VAR, DW_DLA_WEAK also use + the global types. + +*/ + {27, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0}, + /* 39 DW_DLA_FUNC_CONTEXT */ + {28, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0}, + /* 40 DW_DLA_TYPENAME_CONTEXT */ + {29, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0}, + /* 41 DW_DLA_VAR_CONTEXT */ + {30, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0}, + /* 42 DW_DLA_WEAK_CONTEXT */ + {31, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0}, + /* 43 DW_DLA_PUBTYPES_CONTEXT DWARF3 */ + + {0,1,1,0,0 }, + /* 44 DW_DLA_HASH_TABLE_ENTRY */ + + +}; + +#ifndef DWARF_SIMPLE_MALLOC + +/* + This function is given a pointer to the header + structure that is used to allocate 1 struct of + the type given by alloc_type. It first checks + if a struct is available in its free list. If + not, it checks if 1 is available in its blob, + which is a chunk of memory that is reserved for + its use. If not, it malloc's a chunk. The + initial part of it is used to store the end + address of the chunk, and also to keep track + of the number of free structs in that chunk. + This information is used for freeing the chunk + when all the structs in it are free. + + Assume all input arguments have been validated. + + This function can be used only to allocate 1 + struct of the given type. + + It returns a pointer to the struct that the + user can use. It returns NULL only when it + is out of free structs, and cannot malloc + any more. The struct returned is zero-ed. + + A pointer to the chunk that the struct belongs + to is stored in the bytes preceding the + returned address. Since this pointer it + never overwritten, when a struct is allocated + from the free_list this pointer does not + have to be written. In the 2 other cases, + where the struct is allocated from a new + chunk, or the blob, a pointer to the chunk + is written. +*/ +static Dwarf_Ptr +_dwarf_find_memory(Dwarf_Alloc_Hdr alloc_hdr) +{ + /* Pointer to the struct allocated. */ + Dwarf_Small *ret_mem = 0; + + /* Pointer to info about chunks allocated. */ + Dwarf_Alloc_Area alloc_area; + + /* Size of chunk malloc'ed when no free structs left. */ + Dwarf_Signed mem_block_size; + + /* Pointer to block malloc'ed. */ + Dwarf_Small *mem_block; + + /* + Check the alloc_area from which the last allocation was made + (most recent new block). If that is not successful, then search + the list of alloc_area's from alloc_header. */ + alloc_area = alloc_hdr->ah_last_alloc_area; + if (alloc_area == NULL || alloc_area->aa_free_structs_in_chunk == 0) + for (alloc_area = alloc_hdr->ah_alloc_area_head; + alloc_area != NULL; alloc_area = alloc_area->aa_next) { + + if (alloc_area->aa_free_structs_in_chunk > 0) { + break; /* found a free entry! */ + } + + } + + if (alloc_area != NULL) { + alloc_area->aa_free_structs_in_chunk--; + + if (alloc_area->aa_free_list != NULL) { + ret_mem = alloc_area->aa_free_list; + + /* + Update the free list. The initial part of the struct is + used to hold a pointer to the next struct on the free + list. In this way, the free list chain is maintained at + 0 memory cost. */ + alloc_area->aa_free_list = + ((Dwarf_Free_List) ret_mem)->fl_next; + } else if (alloc_area->aa_blob_start < alloc_area->aa_blob_end) { + ret_mem = alloc_area->aa_blob_start; + + /* + Store pointer to chunk this struct belongs to in the + first few bytes. Return pointer to bytes after this + pointer storage. */ + *(Dwarf_Alloc_Area *) ret_mem = alloc_area; + ret_mem += DW_RESERVE; + + alloc_area->aa_blob_start += alloc_hdr->ah_bytes_one_struct; + } else { + /* else fall thru , though it should be impossible to fall + thru. And represents a disastrous programming error if + we get here. */ +#ifdef DEBUG + fprintf(stderr, "libdwarf Internal error start %x end %x\n", + (int) alloc_area->aa_blob_start, + (int) alloc_area->aa_blob_end); +#endif + } + } + + /* New memory has to malloc'ed since there are no free structs. */ + if (ret_mem == 0) { + Dwarf_Word rounded_area_hdr_size; + + alloc_hdr->ah_chunks_allocated++; + + { /* this nonsense avoids a warning */ + /* CONSTCOND would be better */ + unsigned long v = sizeof(struct Dwarf_Alloc_Area_s); + + rounded_area_hdr_size = ROUND_SIZE(v); + } + + /* + Allocate memory to contain the required number of structs + and the Dwarf_Alloc_Area_s to control it. */ + mem_block_size = alloc_hdr->ah_bytes_malloc_per_chunk + + rounded_area_hdr_size; + + mem_block = malloc(mem_block_size); + if (mem_block == NULL) { + return (NULL); + } + + + /* + Attach the Dwarf_Alloc_Area_s struct to the list of chunks + malloc'ed for this struct type. Also initialize the fields + of the Dwarf_Alloc_Area_s. */ + alloc_area = (Dwarf_Alloc_Area) mem_block; + alloc_area->aa_prev = 0; + if (alloc_hdr->ah_alloc_area_head != NULL) { + alloc_hdr->ah_alloc_area_head->aa_prev = alloc_area; + } + alloc_area->aa_free_list = 0; + alloc_area->aa_next = alloc_hdr->ah_alloc_area_head; + alloc_hdr->ah_alloc_area_head = alloc_area; + + alloc_area->aa_alloc_hdr = alloc_hdr; + alloc_area->aa_free_structs_in_chunk = + (Dwarf_Sword) alloc_hdr->ah_structs_per_chunk - 1; + if (alloc_area->aa_free_structs_in_chunk < 1) { + /* If we get here, there is a disastrous programming error + somewhere. */ +#ifdef DEBUG + fprintf(stderr, + "libdwarf Internal error: free structs in chunk %d\n", + (int) alloc_area->aa_free_structs_in_chunk); +#endif + return NULL; + } + + /* + The struct returned begins immediately after the + Dwarf_Alloc_Area_s struct. */ + ret_mem = mem_block + rounded_area_hdr_size; + alloc_area->aa_blob_start = + ret_mem + alloc_hdr->ah_bytes_one_struct; + alloc_area->aa_blob_end = mem_block + mem_block_size; + + /* + Store pointer to chunk this struct belongs to in the first + few bytes. Return pointer to bytes after this pointer + storage. */ + *(Dwarf_Alloc_Area *) ret_mem = alloc_area; + ret_mem += DW_RESERVE; + } + + alloc_hdr->ah_last_alloc_area = alloc_area; + alloc_hdr->ah_struct_user_holds++; + memset(ret_mem, 0, alloc_hdr->ah_bytes_one_struct - DW_RESERVE); + return (ret_mem); +} + +#endif /* ndef DWARF_SIMPLE_MALLOC */ + +/* + This function returns a pointer to a region + of memory. For alloc_types that are not + strings or lists of pointers, only 1 struct + can be requested at a time. This is indicated + by an input count of 1. For strings, count + equals the length of the string it will + contain, i.e it the length of the string + plus 1 for the terminating null. For lists + of pointers, count is equal to the number of + pointers. For DW_DLA_FRAME_BLOCK, DW_DLA_RANGES, and + DW_DLA_LOC_BLOCK allocation types also, count + is the count of the number of structs needed. + + This function cannot be used to allocate a + Dwarf_Debug_s struct. + +*/ +Dwarf_Ptr +_dwarf_get_alloc(Dwarf_Debug dbg, + Dwarf_Small alloc_type, Dwarf_Unsigned count) +{ + Dwarf_Alloc_Hdr alloc_hdr; + + Dwarf_Ptr ret_mem; + + Dwarf_Signed size = 0; + unsigned int index; + unsigned int type = alloc_type; + + if (dbg == NULL) { + return (NULL); + } + + if (type >= ALLOC_AREA_INDEX_TABLE_MAX) { + /* internal error */ + return NULL; + } + index = index_into_allocated[type].ia_al_num; + /* zero also illegal but not tested for */ + + /* If the Dwarf_Debug is not fully set up, we will get index 0 for + any type and must do something. 'Not fully set up' can only + happen for DW_DLA_ERROR, I (davea) believe, and for that we call + special code here.. */ + + if (index == 0) { + if (alloc_type == DW_DLA_STRING) { + size = count; + } else if (alloc_type == DW_DLA_LIST) { + size = count * sizeof(Dwarf_Ptr); + } else if (alloc_type == DW_DLA_FRAME_BLOCK) { + size = count * sizeof(Dwarf_Frame_Op); + } else if (alloc_type == DW_DLA_LOC_BLOCK) { + size = count * sizeof(Dwarf_Loc); + } else if (alloc_type == DW_DLA_HASH_TABLE_ENTRY) { + size = count * sizeof(struct Dwarf_Hash_Table_Entry_s); + } else if (alloc_type == DW_DLA_ADDR) { + size = count * + (sizeof(Dwarf_Addr) > sizeof(Dwarf_Off) ? + sizeof(Dwarf_Addr) : sizeof(Dwarf_Off)); + } else if (alloc_type == DW_DLA_RANGES) { + size = count * sizeof(Dwarf_Ranges); + } else if (alloc_type == DW_DLA_ERROR) { + void *m = _dwarf_special_no_dbg_error_malloc(); + + dwarf_malloc_check_alloc_data(m, DW_DLA_ERROR); + return m; + + } else { + /* If we get here, there is a disastrous programming error + somewhere. */ +#ifdef DEBUG + fprintf(stderr, + "libdwarf Internal error: type %d unexpected\n", + (int) type); +#endif + } + } else { + alloc_hdr = &dbg->de_alloc_hdr[index]; + if (alloc_hdr->ah_bytes_one_struct > 0) { +#ifdef DWARF_SIMPLE_MALLOC + size = alloc_hdr->ah_bytes_one_struct; +#else + { + void *m = _dwarf_find_memory(alloc_hdr); + + dwarf_malloc_check_alloc_data(m, type); + if (index_into_allocated[type].specialconstructor) { + int res = + index_into_allocated[type]. + specialconstructor(dbg, m); + if (res != DW_DLV_OK) { + /* We leak what we allocated in + _dwarf_find_memory when constructor fails. */ + return NULL; + } + } + return m; + } +#endif + + } else { + /* Special case: should not really happen at all. */ + if (type == DW_DLA_ERROR) { + /* dwarf_init failure. Because dbg is incomplete we + won't use it to record the malloc. */ + void *m = _dwarf_special_no_dbg_error_malloc(); + + dwarf_malloc_check_alloc_data(m, DW_DLA_ERROR); + return m; + } else { + /* If we get here, there is a disastrous programming + error somewhere. */ +#ifdef DWARF_SIMPLE_MALLOC + _dwarf_simple_malloc_botch(3); +#endif +#ifdef DEBUG + fprintf(stderr, + "libdwarf Internal error: Type %d unexpected\n", + (int) type); +#endif + } + } + } + + ret_mem = malloc(size); +#ifdef DWARF_SIMPLE_MALLOC + _dwarf_simple_malloc_add_to_list(dbg, ret_mem, (unsigned long) size, + type); +#endif + if (ret_mem != NULL) + memset(ret_mem, 0, size); + + dwarf_malloc_check_alloc_data(ret_mem, type); + if (index_into_allocated[type].specialconstructor) { + int res = + index_into_allocated[type].specialconstructor(dbg, ret_mem); + if (res != DW_DLV_OK) { + /* We leak what we allocated in _dwarf_find_memory when + constructor fails. */ + return NULL; + } + } + + return (ret_mem); +} + + + +/* + This function is used to deallocate a region of memory + that was obtained by a call to _dwarf_get_alloc. Note + that though dwarf_dealloc() is a public function, + _dwarf_get_alloc() isn't. + + For lists, typically arrays of pointers, it is assumed + that the space was allocated by a direct call to malloc, + and so a straight free() is done. This is also the case + for variable length blocks such as DW_DLA_FRAME_BLOCK + and DW_DLA_LOC_BLOCK and DW_DLA_RANGES. + + For strings, the pointer might point to a string in + .debug_info or .debug_string. After this is checked, + and if found not to be the case, a free() is done, + again on the assumption that a malloc was used to + obtain the space. + + For other types of structs, a pointer to the chunk that + the struct was allocated out of, is present in the bytes + preceding the pointer passed in. For this chunk it is + checked whether all the structs in that chunk are now free. + If so, the entire chunk is free_ed. Otherwise, the space + is added to the free list for that chunk, and the free count + incremented. + + This function does not return anything. +*/ +void +dwarf_dealloc(Dwarf_Debug dbg, + Dwarf_Ptr space, Dwarf_Unsigned alloc_type) +{ + Dwarf_Alloc_Hdr alloc_hdr; + Dwarf_Alloc_Area alloc_area; + unsigned int type = alloc_type; + unsigned int index; + + if (space == NULL) { + return; + } + if (type == DW_DLA_ERROR) { + /* Get pointer to Dwarf_Alloc_Area this struct came from. See + dwarf_alloc.h ROUND_SIZE_WITH_POINTER stuff */ + alloc_area = + *(Dwarf_Alloc_Area *) ((char *) space - DW_RESERVE); + if (alloc_area == 0) { + /* This is the special case of a failed dwarf_init(). Also + (and more signficantly) there are a variety of other + situations where libdwarf does not *know* what dbg is + involved (because of a libdwarf-caller-error) so + libdwarf uses NULL as the dbg. Those too wind up here. */ + _dwarf_free_special_error(space); + dwarf_malloc_check_dealloc_data(space, type); + return; + } + + } + if (dbg == NULL) { + /* App error, or an app that failed to succeed in a + dwarf_init() call. */ + return; + } + if (type >= ALLOC_AREA_INDEX_TABLE_MAX) { + /* internal or user app error */ + return; + } + + index = index_into_allocated[type].ia_al_num; + /* + A string pointer may point into .debug_info or .debug_string. + Otherwise, they are directly malloc'ed. */ + dwarf_malloc_check_dealloc_data(space, type); + if (index == 0) { + if (type == DW_DLA_STRING) { + if ((Dwarf_Small *) space >= dbg->de_debug_info.dss_data && + (Dwarf_Small *) space < + dbg->de_debug_info.dss_data + dbg->de_debug_info.dss_size) + return; + + if (dbg->de_debug_line.dss_data != NULL && + (Dwarf_Small *) space >= dbg->de_debug_line.dss_data && + (Dwarf_Small *) space < + dbg->de_debug_line.dss_data + dbg->de_debug_line.dss_size) + return; + + if (dbg->de_debug_pubnames.dss_data != NULL && + (Dwarf_Small *) space >= dbg->de_debug_pubnames.dss_data && + (Dwarf_Small *) space < + dbg->de_debug_pubnames.dss_data + + dbg->de_debug_pubnames.dss_size) + return; + + if (dbg->de_debug_frame.dss_data != NULL && + (Dwarf_Small *) space >= dbg->de_debug_frame.dss_data && + (Dwarf_Small *) space < + dbg->de_debug_frame.dss_data + dbg->de_debug_frame.dss_size) + return; + + if (dbg->de_debug_str.dss_data != NULL && + (Dwarf_Small *) space >= dbg->de_debug_str.dss_data && + (Dwarf_Small *) space < + dbg->de_debug_str.dss_data + dbg->de_debug_str.dss_size) + return; + + if (dbg->de_debug_funcnames.dss_data != NULL && + (Dwarf_Small *) space >= dbg->de_debug_funcnames.dss_data && + (Dwarf_Small *) space < + dbg->de_debug_funcnames.dss_data + + dbg->de_debug_funcnames.dss_size) + return; + + if (dbg->de_debug_typenames.dss_data != NULL && + (Dwarf_Small *) space >= dbg->de_debug_typenames.dss_data && + (Dwarf_Small *) space < + dbg->de_debug_typenames.dss_data + + dbg->de_debug_typenames.dss_size) + return; + if (dbg->de_debug_pubtypes.dss_data != NULL && + (Dwarf_Small *) space >= dbg->de_debug_pubtypes.dss_data && + (Dwarf_Small *) space < + dbg->de_debug_pubtypes.dss_data + + dbg->de_debug_pubtypes.dss_size) + return; + + if (dbg->de_debug_varnames.dss_data != NULL && + (Dwarf_Small *) space >= dbg->de_debug_varnames.dss_data && + (Dwarf_Small *) space < + dbg->de_debug_varnames.dss_data + + dbg->de_debug_varnames.dss_size) + return; + + if (dbg->de_debug_weaknames.dss_data != NULL && + (Dwarf_Small *) space >= dbg->de_debug_weaknames.dss_data && + (Dwarf_Small *) space < + dbg->de_debug_weaknames.dss_data + + dbg->de_debug_weaknames.dss_size) + return; + +#ifdef DWARF_SIMPLE_MALLOC + _dwarf_simple_malloc_delete_from_list(dbg, space, type); +#endif + free(space); + return; + } + + if (type == DW_DLA_LIST || + type == DW_DLA_FRAME_BLOCK || + type == DW_DLA_LOC_BLOCK || type == DW_DLA_ADDR || + type == DW_DLA_RANGES || + type == DW_DLA_HASH_TABLE_ENTRY) { + +#ifdef DWARF_SIMPLE_MALLOC + _dwarf_simple_malloc_delete_from_list(dbg, space, type); +#endif + free(space); + return; + } + /* else is an alloc type that is not used */ + /* app or internal error */ +#ifdef DWARF_SIMPLE_MALLOC + _dwarf_simple_malloc_botch(4); +#endif + return; + + } + if (index_into_allocated[type].specialdestructor) { + index_into_allocated[type].specialdestructor(space); + } +#ifdef DWARF_SIMPLE_MALLOC + _dwarf_simple_malloc_delete_from_list(dbg, space, type); + free(space); +#else /* !DWARF_SIMPLE_MALLOC */ + alloc_hdr = &dbg->de_alloc_hdr[index]; + + /* Get pointer to Dwarf_Alloc_Area this struct came from. See + dwarf_alloc.h ROUND_SIZE_WITH_POINTER stuff */ + alloc_area = *(Dwarf_Alloc_Area *) ((char *) space - DW_RESERVE); + + /* ASSERT: alloc_area != NULL If NULL we could abort, let it + coredump below, or return, pretending all is well. We go on, + letting program crash. Is caller error. */ + + /* + Check that the alloc_hdr field of the alloc_area we have is + pointing to the right alloc_hdr. This is used to catch use of + incorrect deallocation code by the user. */ + if (alloc_area->aa_alloc_hdr != alloc_hdr) { + /* If we get here, the user has called dwarf_dealloc wrongly or + there is some other disastrous error. By leaking mem here we + try to be safe... */ +#ifdef DEBUG + fprintf(stderr, + "libdwarf Internal error: type %d hdr mismatch %lx %lx " + "area ptr %lx\n", + (int) type, + (long) alloc_area->aa_alloc_hdr, + (long) alloc_hdr, (long) alloc_area); +#endif + return; + } + + alloc_hdr->ah_struct_user_holds--; + alloc_area->aa_free_structs_in_chunk++; + + /* + Give chunk back to malloc only when every struct is freed */ + if (alloc_area->aa_free_structs_in_chunk == + alloc_hdr->ah_structs_per_chunk) { + if (alloc_area->aa_prev != NULL) { + alloc_area->aa_prev->aa_next = alloc_area->aa_next; + } else { + alloc_hdr->ah_alloc_area_head = alloc_area->aa_next; + } + + if (alloc_area->aa_next != NULL) { + alloc_area->aa_next->aa_prev = alloc_area->aa_prev; + } + + alloc_hdr->ah_chunks_allocated--; + + if (alloc_area == alloc_hdr->ah_last_alloc_area) { + alloc_hdr->ah_last_alloc_area = NULL; + } + memset(alloc_area, 0, sizeof(*alloc_area)); + free(alloc_area); + } + + else { + ((Dwarf_Free_List) space)->fl_next = alloc_area->aa_free_list; + alloc_area->aa_free_list = space; + } +#endif /* !DWARF_SIMPLE_MALLOC */ +} + + +/* + Allocates space for a Dwarf_Debug_s struct, + since one does not exist. +*/ +Dwarf_Debug +_dwarf_get_debug(void + ) +{ + Dwarf_Debug dbg; + + dbg = (Dwarf_Debug) malloc(sizeof(struct Dwarf_Debug_s)); + if (dbg == NULL) + return (NULL); + else + memset(dbg, 0, sizeof(struct Dwarf_Debug_s)); + return (dbg); +} + + +/* + Sets up the Dwarf_Debug_s struct for all the + allocation types currently defined. + Allocation types DW_DLA_STRING, DW_DLA_LIST, + DW_DLA_FRAME_BLOCK, DW_DLA_LOC_BLOCK, DW_DLA_RANGES are + malloc'ed directly. + + This routine should be called after _dwarf_setup(), + so that information about the sizes of the Dwarf + sections can be used to decide the number of + structs of each type malloc'ed. + + Also DW_DLA_ELLIST, DW_DLA_BOUNDS, DW_DLA_TYPE, + DW_DLA_SUBSCR, DW_DLA_LINEBUF allocation types + are currently not used. + The ah_bytes_one_struct and ah_structs_per_chunk fields for + these types have been set to 1 for efficiency + in dwarf_get_alloc(). + + Ah_alloc_num should be greater than 1 for all + types that are currently being used. + + Therefore, for these allocation types the + ah_bytes_one_struct, and ah_structs_per_chunk fields do not + need to be initialized. + + Being an internal routine, assume proper dbg. +*/ + +Dwarf_Debug +_dwarf_setup_debug(Dwarf_Debug dbg) +{ + int i; + + for (i = 1; i <= MAX_DW_DLA; i++) { + const struct ial_s *ialp = &index_into_allocated[i]; + unsigned int hdr_index = ialp->ia_al_num; + Dwarf_Word str_size = ialp->ia_struct_size; + Dwarf_Word str_count = ialp->ia_base_count; + Dwarf_Word rnded_size = ROUND_SIZE_WITH_POINTER(str_size); + + Dwarf_Alloc_Hdr alloc_hdr = &dbg->de_alloc_hdr[hdr_index]; + + alloc_hdr->ah_bytes_one_struct = (Dwarf_Half) rnded_size; + + /* ah_structs_per_chunk must be >0 else we are in trouble */ + alloc_hdr->ah_structs_per_chunk = str_count; + alloc_hdr->ah_bytes_malloc_per_chunk = rnded_size * str_count; + } + return (dbg); +} + +/* + This function prints out the statistics + collected on allocation of memory chunks. +*/ +void +dwarf_print_memory_stats(Dwarf_Debug dbg) +{ + Dwarf_Alloc_Hdr alloc_hdr; + Dwarf_Shalf i; + + /* + Alloc types start at 1, not 0. Hence, the first NULL string, and + also a size of MAX_DW_DLA + 1. */ + char *alloc_type_name[MAX_DW_DLA + 1] = { + "", + "DW_DLA_STRING", + "DW_DLA_LOC", + "DW_DLA_LOCDESC", + "DW_DLA_ELLIST", + "DW_DLA_BOUNDS", + "DW_DLA_BLOCK", + "DW_DLA_DEBUG", + "DW_DLA_DIE", + "DW_DLA_LINE", + "DW_DLA_ATTR", + "DW_DLA_TYPE", + "DW_DLA_SUBSCR", + "DW_DLA_GLOBAL", + "DW_DLA_ERROR", + "DW_DLA_LIST", + "DW_DLA_LINEBUF", + "DW_DLA_ARANGE", + "DW_DLA_ABBREV", + "DW_DLA_FRAME_OP", + "DW_DLA_CIE", + "DW_DLA_FDE", + "DW_DLA_LOC_BLOCK", + "DW_DLA_FRAME_BLOCK", + "DW_DLA_FUNC", + "DW_DLA_TYPENAME", + "DW_DLA_VAR", + "DW_DLA_WEAK", + "DW_DLA_ADDR", + "DW_DLA_RANGES", + "DW_DLA_ABBREV_LIST", + "DW_DLA_CHAIN", + "DW_DLA_CU_CONTEXT", + "DW_DLA_FRAME", + "DW_DLA_GLOBAL_CONTEXT", + "DW_DLA_FILE_ENTRY", + "DW_DLA_LINE_CONTEXT", + "DW_DLA_LOC_CHAIN", + "DW_DLA_HASH_TABLE", + "DW_DLA_FUNC_CONTEXT", + "DW_DLA_TYPENAME_CONTEXT", + "DW_DLA_VAR_CONTEXT", + "DW_DLA_WEAK_CONTEXT", + "DW_DLA_PUBTYPES_CONTEXT", + "DW_DLA_HASH_TABLE_ENTRY", + }; + + if (dbg == NULL) + return; + + printf("Size of Dwarf_Debug %4ld bytes\n", + (long) sizeof(*dbg)); + printf("Size of Dwarf_Alloc_Hdr_s %4ld bytes\n", + (long) sizeof(struct Dwarf_Alloc_Hdr_s)); + printf("size of Dwarf_Alloc_Area_s %4ld bytes\n", + (long) sizeof(struct Dwarf_Alloc_Area_s)); + + printf(" Alloc Type Curr Structs byt str\n"); + printf(" ---------- ---- ------- per per\n"); + for (i = 1; i <= MAX_DW_DLA; i++) { + int indx = index_into_allocated[i].ia_al_num; + + alloc_hdr = &dbg->de_alloc_hdr[indx]; + if (alloc_hdr->ah_bytes_one_struct != 1) { + printf("%2d %-25s %6d %8d %6d %6d\n", + (int) i, + alloc_type_name[i], + (int) alloc_hdr->ah_chunks_allocated, + (int) alloc_hdr->ah_struct_user_holds, + (int) alloc_hdr->ah_bytes_malloc_per_chunk, + (int) alloc_hdr->ah_structs_per_chunk); + } + } +} + + +#ifndef DWARF_SIMPLE_MALLOC +/* + This recursively frees + the chunks still allocated, and + forward chained through the aa_next + pointer. +*/ +static void +_dwarf_recursive_free(Dwarf_Alloc_Area alloc_area) +{ + if (alloc_area->aa_next != NULL) { + _dwarf_recursive_free(alloc_area->aa_next); + } + + alloc_area->aa_next = 0; + alloc_area->aa_prev = 0; + free(alloc_area); +} +#endif + +/* In the 'rela' relocation case we might have malloc'd + space to ensure it is read-write. In that case, free the space. */ +static void +rela_free(struct Dwarf_Section_s * sec) +{ + if (sec->dss_data_was_malloc) { + free(sec->dss_data); + } + sec->dss_data = 0; + sec->dss_data_was_malloc = 0; +} + +/* + Used to free all space allocated for this Dwarf_Debug. + The caller should assume that the Dwarf_Debug pointer + itself is no longer valid upon return from this function. + + In case of difficulty, this function simply returns quietly. +*/ +int +_dwarf_free_all_of_one_debug(Dwarf_Debug dbg) +{ + Dwarf_Alloc_Hdr alloc_hdr; + Dwarf_Shalf i; + Dwarf_CU_Context context = 0; + Dwarf_CU_Context nextcontext = 0; + + if (dbg == NULL) + return (DW_DLV_ERROR); + + /* To do complete validation that we have no surprising missing or + erroneous deallocs it is advisable to do the dwarf_deallocs here + that are not things the user can otherwise request. + Housecleaning. */ + + for (context = dbg->de_cu_context_list; + context; context = nextcontext) { + Dwarf_Hash_Table hash_table = context->cc_abbrev_hash_table; + _dwarf_free_abbrev_hash_table_contents(dbg,hash_table); + nextcontext = context->cc_next; + dwarf_dealloc(dbg, hash_table, DW_DLA_HASH_TABLE); + dwarf_dealloc(dbg, context, DW_DLA_CU_CONTEXT); + } + + /* Housecleaning done. Now really free all the space. */ +#ifdef DWARF_SIMPLE_MALLOC + if (dbg->de_simple_malloc_base) { + struct simple_malloc_record_s *smp = dbg->de_simple_malloc_base; + + while (smp) { + int i; + struct simple_malloc_record_s *prev_smp = 0; + + for (i = 0; i < smp->sr_used; ++i) { + struct simple_malloc_entry_s *cur; + + cur = &smp->sr_entry[i]; + if (cur->se_addr != 0) { + free(cur->se_addr); + cur->se_addr = 0; + } + } + prev_smp = smp; + smp = smp->sr_next; + free(prev_smp); + } + dbg->de_simple_malloc_base = 0; + } +#else + for (i = 1; i < ALLOC_AREA_REAL_TABLE_MAX; i++) { + int indx = i; + + alloc_hdr = &dbg->de_alloc_hdr[indx]; + if (alloc_hdr->ah_alloc_area_head != NULL) { + _dwarf_recursive_free(alloc_hdr->ah_alloc_area_head); + } + } + +#endif + rela_free(&dbg->de_debug_info); + rela_free(&dbg->de_debug_abbrev); + rela_free(&dbg->de_debug_line); + rela_free(&dbg->de_debug_loc); + rela_free(&dbg->de_debug_aranges); + rela_free(&dbg->de_debug_macinfo); + rela_free(&dbg->de_debug_pubnames); + rela_free(&dbg->de_debug_str); + rela_free(&dbg->de_debug_frame); + rela_free(&dbg->de_debug_frame_eh_gnu); + rela_free(&dbg->de_debug_pubtypes); + rela_free(&dbg->de_debug_funcnames); + rela_free(&dbg->de_debug_typenames); + rela_free(&dbg->de_debug_varnames); + rela_free(&dbg->de_debug_weaknames); + rela_free(&dbg->de_debug_ranges); + dwarf_harmless_cleanout(&dbg->de_harmless_errors); + + memset(dbg, 0, sizeof(*dbg)); /* Prevent accidental use later. */ + free(dbg); + return (DW_DLV_OK); +} + +/* A special case: we have no dbg, no alloc header etc. + So create something out of thin air that we can recognize + in dwarf_dealloc. + Something with the prefix (prefix space hidden from caller). + + Only applies to DW_DLA_ERROR, making up an error record. +*/ + +struct Dwarf_Error_s * +_dwarf_special_no_dbg_error_malloc(void) +{ + /* the union unused things are to guarantee proper alignment */ + union u { + Dwarf_Alloc_Area ptr_not_used; + struct Dwarf_Error_s base_not_used; + char data_space[sizeof(struct Dwarf_Error_s) + + (DW_RESERVE * 2)]; + }; + char *mem; + + mem = malloc(sizeof(union u)); + + if (mem == 0) { + return 0; + + } + memset(mem, 0, sizeof(union u)); + mem += DW_RESERVE; + return (struct Dwarf_Error_s *) mem; +} + +/* The free side of _dwarf_special_no_dbg_error_malloc() +*/ +static void +_dwarf_free_special_error(Dwarf_Ptr space) +{ + char *mem = (char *) space; + + mem -= DW_RESERVE; + free(mem); +} + + +#ifdef DWARF_SIMPLE_MALLOC +/* here solely for planting a breakpoint. */ +/* ARGSUSED */ +void +_dwarf_simple_malloc_botch(int err) +{ + fprintf(stderr,"simple malloc botch %d\n",err); +} +static void +_dwarf_simple_malloc_add_to_list(Dwarf_Debug dbg, + Dwarf_Ptr addr, + unsigned long size, short alloc_type) +{ + struct simple_malloc_record_s *cur; + struct simple_malloc_entry_s *newentry; + + if (!dbg->de_simple_malloc_base) { + /* First entry to this routine. */ + dbg->de_simple_malloc_base = + malloc(sizeof(struct simple_malloc_record_s)); + if (!dbg->de_simple_malloc_base) { + _dwarf_simple_malloc_botch(7); + return; /* no memory, give up */ + } + memset(dbg->de_simple_malloc_base, + 0, sizeof(struct simple_malloc_record_s)); + } + cur = dbg->de_simple_malloc_base; + + if (cur->sr_used >= DSM_BLOCK_COUNT) { + /* Better not be > than as that means chaos */ + + /* Create a new block to link at the head. */ + + struct simple_malloc_record_s *newblock = + malloc(sizeof(struct simple_malloc_record_s)); + if (!newblock) { + _dwarf_simple_malloc_botch(8); + return; /* Can do nothing, out of memory */ + } + memset(newblock, 0, sizeof(struct simple_malloc_record_s)); + /* Link the new block at the head of the chain, and make it + 'current' */ + dbg->de_simple_malloc_base = newblock; + newblock->sr_next = cur; + cur = newblock; + } + newentry = &cur->sr_entry[cur->sr_used]; + newentry->se_addr = addr; + newentry->se_size = size; + newentry->se_type = alloc_type; + ++cur->sr_used; +} + +/* + DWARF_SIMPLE_MALLOC: testing the hypothesis that the existing + malloc scheme here (see _dwarf_get_alloc()) is pointless complexity. + + DWARF_SIMPLE_MALLOC also makes it easy for a malloc-tracing + tool to verify libdwarf malloc has no botches (though of course + such does not test the complicated standard-libdwarf-alloc code). + + To properly answer the question, the simple-malloc allocate + and delete should be something other than a simple list. + Perhaps a heap, or perhaps a red-black tree. + +*/ +static void +_dwarf_simple_malloc_delete_from_list(Dwarf_Debug dbg, + Dwarf_Ptr space, short alloc_type) +{ + if (space == 0) { + _dwarf_simple_malloc_botch(6); + } + if (dbg->de_simple_malloc_base) { + struct simple_malloc_record_s *smp = dbg->de_simple_malloc_base; + + while (smp) { + int i; + + for (i = 0; i < smp->sr_used; ++i) { + struct simple_malloc_entry_s *cur; + + cur = &smp->sr_entry[i]; + if (cur->se_addr == space) { + if (cur->se_type != alloc_type) { + _dwarf_simple_malloc_botch(0); + } + cur->se_addr = 0; + return; + } + } + smp = smp->sr_next; + } + } + /* Never found the space. */ + _dwarf_simple_malloc_botch(1); + return; + +} +#endif diff --git a/usr/src/lib/libdwarf/common/dwarf_alloc.h b/usr/src/lib/libdwarf/common/dwarf_alloc.h new file mode 100644 index 0000000000..3a61c692c6 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_alloc.h @@ -0,0 +1,177 @@ +/* + + Copyright (C) 2000,2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2008-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + +/* #define DWARF_SIMPLE_MALLOC 1 */ + +Dwarf_Ptr _dwarf_get_alloc(Dwarf_Debug, Dwarf_Small, Dwarf_Unsigned); +Dwarf_Debug _dwarf_get_debug(void); +Dwarf_Debug _dwarf_setup_debug(Dwarf_Debug); +int _dwarf_free_all_of_one_debug(Dwarf_Debug); + +typedef struct Dwarf_Alloc_Area_s *Dwarf_Alloc_Area; +typedef struct Dwarf_Free_List_s *Dwarf_Free_List; + +/* ALLOC_AREA_INDEX_TABLE_MAX is the size of the + struct ial_s index_into_allocated array in dwarf_alloc.c +*/ +#define ALLOC_AREA_INDEX_TABLE_MAX 45 +/* ALLOC_AREA_REAL_TABLE_MAX is the size of the array needed + to hold pointers to dwarf alloc chunk areas. + It's smaller as some of the index_into_allocated + entries (they look like {0,1,1,0,0} ) + are treated specially and don't use 'chunks'. +*/ +#define ALLOC_AREA_REAL_TABLE_MAX 32 + +/* + This struct is used to chain all the deallocated + structs on the free list of each chain. The structs + are chained internally, by using the memory they + contain. +*/ +struct Dwarf_Free_List_s { + Dwarf_Free_List fl_next; +}; + + +/* + This struct is used to manage all the chunks malloc'ed + for a particular alloc_type. Many of the fields are + initialized by dwarf_init(). +*/ +struct Dwarf_Alloc_Hdr_s { + + /* Count of actual number of structs user app holds pointers to + currently. */ + Dwarf_Sword ah_struct_user_holds; + + /* + Size of each struct that will be allocated for this alloc_type. + Initialized by dwarf_init(). */ + Dwarf_Half ah_bytes_one_struct; + + /* + Number of structs of this alloc_type that will be contained in + each chunk that is malloc'ed. Initialized by dwarf_init(). */ + Dwarf_Word ah_structs_per_chunk; + + /* + Number of bytes malloc'ed per chunk which is basically + (ah_bytes_one_struct+_DWARF_RESERVE) * ah_alloc_num. */ + Dwarf_Word ah_bytes_malloc_per_chunk; + + /* Count of chunks currently allocated for type. */ + Dwarf_Sword ah_chunks_allocated; + + /* + Points to a chain of Dwarf_Alloc_Area_s structs that represent + all the chunks currently allocated for the alloc_type. */ + Dwarf_Alloc_Area ah_alloc_area_head; + + /* Last Alloc Area that was allocated by malloc. The + free-space-search area looks here first and only if it is full + goes thru the list pointed to by ah_alloc_area_head. */ + Dwarf_Alloc_Area ah_last_alloc_area; +}; + + +/* + This struct is used to manage each chunk that is + malloc'ed for a particular alloc_type. For each + allocation type, the allocation header points to + a list of all the chunks malloc'ed for that type. +*/ +struct Dwarf_Alloc_Area_s { + + /* Points to the free list of structs in the chunk. */ + Dwarf_Ptr aa_free_list; + + /* + Count of the number of free structs in the chunk. This includes + both those on the free list, and in the blob. */ + Dwarf_Sword aa_free_structs_in_chunk; + + /* + Points to the first byte of the blob from which struct will be + allocated. A struct is put on the free_list only when it + dwarf_deallocated. Initial allocations are from the blob. */ + Dwarf_Small *aa_blob_start; + + /* Points just past the last byte of the blob. */ + Dwarf_Small *aa_blob_end; + + /* Points to alloc_hdr this alloc_area is linked to: The owner, in + other words. */ + Dwarf_Alloc_Hdr aa_alloc_hdr; + + /* + Used for chaining Dwarf_Alloc_Area_s atructs. Alloc areas are + doubly linked to enable deletion from the list in constant time. */ + Dwarf_Alloc_Area aa_next; + Dwarf_Alloc_Area aa_prev; +}; + +struct Dwarf_Error_s *_dwarf_special_no_dbg_error_malloc(void); + +#ifdef DWARF_SIMPLE_MALLOC +/* + DWARF_SIMPLE_MALLOC is for testing the hypothesis that the existing + complex malloc scheme in libdwarf is pointless complexity. + + DWARF_SIMPLE_MALLOC also makes it easy for a malloc-tracing + tool to verify libdwarf malloc has no botches (though of course + such does not test the complicated standard-libdwarf-alloc code). + +*/ + +struct simple_malloc_entry_s { + Dwarf_Small *se_addr; + unsigned long se_size; + short se_type; +}; +#define DSM_BLOCK_COUNT (1000) +#define DSM_BLOCK_SIZE (sizeof(struct simple_malloc_entry_s)*DSM_BLOCK_COUNT) + +/* we do this so dwarf_dealloc can really free everything */ +struct simple_malloc_record_s { + struct simple_malloc_record_s *sr_next; + int sr_used; + struct simple_malloc_entry_s sr_entry[DSM_BLOCK_COUNT]; +}; + + + +#endif /* DWARF_SIMPLE_MALLOC */ diff --git a/usr/src/lib/libdwarf/common/dwarf_arange.c b/usr/src/lib/libdwarf/common/dwarf_arange.c new file mode 100644 index 0000000000..e7ad8acc5e --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_arange.c @@ -0,0 +1,593 @@ +/* + + Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + + + + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include "dwarf_arange.h" +#include "dwarf_global.h" /* for _dwarf_fixup_* */ + + +/* Common code for two user-visible routines to share. + Errors here result in memory leaks, but errors here + are serious (making aranges unusable) so we assume + callers will not repeat the error often or mind the leaks. +*/ +static int +dwarf_get_aranges_list(Dwarf_Debug dbg, + Dwarf_Chain * chain_out, + Dwarf_Signed * chain_count_out, + Dwarf_Error * error) +{ + /* Sweeps through the arange. */ + Dwarf_Small *arange_ptr = 0; + Dwarf_Small *arange_ptr_start = 0; + + /* Start of arange header. Used for rounding offset of arange_ptr + to twice the tuple size. Libdwarf requirement. */ + Dwarf_Small *header_ptr = 0; + + /* Version of .debug_aranges header. */ + Dwarf_Half version = 0; + + /* Offset of current set of aranges into .debug_info. */ + Dwarf_Off info_offset = 0; + + /* Size in bytes of addresses in target. */ + Dwarf_Small address_size = 0; + + /* Size in bytes of segment offsets in target. */ + Dwarf_Small segment_size = 0; + + /* Count of total number of aranges. */ + Dwarf_Unsigned arange_count = 0; + + Dwarf_Arange arange = 0; + + /* Used to chain Dwarf_Aranges structs. */ + Dwarf_Chain curr_chain = NULL; + Dwarf_Chain prev_chain = NULL; + Dwarf_Chain head_chain = NULL; + + arange_ptr = dbg->de_debug_aranges.dss_data; + arange_ptr_start = arange_ptr; + do { + /* Length of current set of aranges. */ + Dwarf_Unsigned length = 0; + Dwarf_Small remainder = 0; + Dwarf_Small *arange_ptr_past_end = 0; + Dwarf_Unsigned range_entry_size = 0; + + int local_length_size; + + /*REFERENCED*/ /* Not used in this instance of the macro */ + int local_extension_size = 0; + + header_ptr = arange_ptr; + + /* READ_AREA_LENGTH updates arange_ptr for consumed bytes */ + READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned, + arange_ptr, local_length_size, + local_extension_size); + arange_ptr_past_end = arange_ptr + length; + + + READ_UNALIGNED(dbg, version, Dwarf_Half, + arange_ptr, sizeof(Dwarf_Half)); + arange_ptr += sizeof(Dwarf_Half); + length = length - sizeof(Dwarf_Half); + if (version != CURRENT_VERSION_STAMP) { + _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR); + return (DW_DLV_ERROR); + } + + READ_UNALIGNED(dbg, info_offset, Dwarf_Off, + arange_ptr, local_length_size); + arange_ptr += local_length_size; + length = length - local_length_size; + if (info_offset >= dbg->de_debug_info.dss_size) { + FIX_UP_OFFSET_IRIX_BUG(dbg, info_offset, + "arange info offset.a"); + if (info_offset >= dbg->de_debug_info.dss_size) { + _dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD); + return (DW_DLV_ERROR); + } + } + + address_size = *(Dwarf_Small *) arange_ptr; + /* It is not an error if the sizes differ. + Unusual, but not an error. */ + arange_ptr = arange_ptr + sizeof(Dwarf_Small); + length = length - sizeof(Dwarf_Small); + + segment_size = *(Dwarf_Small *) arange_ptr; + arange_ptr = arange_ptr + sizeof(Dwarf_Small); + length = length - sizeof(Dwarf_Small); + if (segment_size != 0) { + _dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD); + return (DW_DLV_ERROR); + } + + range_entry_size = 2*address_size + segment_size; + /* Round arange_ptr offset to next multiple of address_size. */ + remainder = (Dwarf_Unsigned) (arange_ptr - header_ptr) % + (range_entry_size); + if (remainder != 0) { + arange_ptr = arange_ptr + (2 * address_size) - remainder; + length = length - ((2 * address_size) - remainder); + } + do { + Dwarf_Addr range_address = 0; + Dwarf_Unsigned segment_selector = 0; + Dwarf_Unsigned range_length = 0; + /* For segmented address spaces, the first field to + read is a segment selector (new in DWARF4) */ + if(version == 4 && segment_size != 0) { + READ_UNALIGNED(dbg, segment_selector, Dwarf_Unsigned, + arange_ptr, segment_size); + arange_ptr += address_size; + length = length - address_size; + } + + READ_UNALIGNED(dbg, range_address, Dwarf_Addr, + arange_ptr, address_size); + arange_ptr += address_size; + length = length - address_size; + + READ_UNALIGNED(dbg, range_length, Dwarf_Unsigned, + arange_ptr, address_size); + arange_ptr += address_size; + length = length - address_size; + + { /* We used to suppress all-zero entries, but + now we return all aranges entries so we show + the entire content. March 31, 2010. */ + + arange = (Dwarf_Arange) + _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1); + if (arange == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + arange->ar_segment_selector = segment_selector; + arange->ar_segment_selector_size = segment_size; + arange->ar_address = range_address; + arange->ar_length = range_length; + arange->ar_info_offset = info_offset; + arange->ar_dbg = dbg; + arange_count++; + + curr_chain = (Dwarf_Chain) + _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); + if (curr_chain == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + curr_chain->ch_item = arange; + if (head_chain == NULL) + head_chain = prev_chain = curr_chain; + else { + prev_chain->ch_next = curr_chain; + prev_chain = curr_chain; + } + } + /* The current set of ranges is terminated by + range_address 0 and range_length 0, but that + does not necessarily terminate the ranges for this CU! + There can be multiple sets in that DWARF + does not explicitly forbid multiple sets. + DWARF2,3,4 section 7.20 + We stop short to avoid overrun of the end of the CU. + */ + + } while (arange_ptr_past_end >= (arange_ptr + range_entry_size)); + + /* A compiler could emit some padding bytes here. dwarf2/3 + (dwarf4 sec 7.20) does not clearly make extra padding + bytes illegal. */ + if (arange_ptr_past_end < arange_ptr) { + char buf[200]; + Dwarf_Unsigned pad_count = arange_ptr - arange_ptr_past_end; + Dwarf_Unsigned offset = arange_ptr - arange_ptr_start; + snprintf(buf,sizeof(buf),"DW_DLE_ARANGE_LENGTH_BAD." + " 0x%" DW_PR_DUx + " pad bytes at offset 0x%" DW_PR_DUx + " in .debug_aranges", + pad_count, offset); + dwarf_insert_harmless_error(dbg,buf); + } + /* For most compilers, arange_ptr == arange_ptr_past_end at + this point. But not if there were padding bytes */ + arange_ptr = arange_ptr_past_end; + } while (arange_ptr < + dbg->de_debug_aranges.dss_data + dbg->de_debug_aranges.dss_size); + + if (arange_ptr != + dbg->de_debug_aranges.dss_data + dbg->de_debug_aranges.dss_size) { + _dwarf_error(dbg, error, DW_DLE_ARANGE_DECODE_ERROR); + return (DW_DLV_ERROR); + } + *chain_out = head_chain; + *chain_count_out = arange_count; + return DW_DLV_OK; +} + +/* + This function returns the count of the number of + aranges in the .debug_aranges section. It sets + aranges to point to a block of Dwarf_Arange's + describing the arange's. It returns DW_DLV_ERROR + on error. + + Must be identical in most aspects to + dwarf_get_aranges_addr_offsets! + +*/ +int +dwarf_get_aranges(Dwarf_Debug dbg, + Dwarf_Arange ** aranges, + Dwarf_Signed * returned_count, Dwarf_Error * error) +{ + /* Count of total number of aranges. */ + Dwarf_Signed arange_count = 0; + + Dwarf_Arange *arange_block = 0; + + /* Used to chain Dwarf_Aranges structs. */ + Dwarf_Chain curr_chain = NULL; + Dwarf_Chain prev_chain = NULL; + Dwarf_Chain head_chain = NULL; + Dwarf_Unsigned i = 0; + int res = DW_DLV_ERROR; + + /* ***** BEGIN CODE ***** */ + + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + + res = _dwarf_load_section(dbg, &dbg->de_debug_aranges, error); + if (res != DW_DLV_OK) { + return res; + } + + res = dwarf_get_aranges_list(dbg,&head_chain,&arange_count,error); + if(res != DW_DLV_OK) { + return res; + } + + arange_block = (Dwarf_Arange *) + _dwarf_get_alloc(dbg, DW_DLA_LIST, arange_count); + if (arange_block == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + curr_chain = head_chain; + for (i = 0; i < arange_count; i++) { + *(arange_block + i) = curr_chain->ch_item; + prev_chain = curr_chain; + curr_chain = curr_chain->ch_next; + dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN); + } + + *aranges = arange_block; + *returned_count = (arange_count); + return DW_DLV_OK; +} + +/* + This function returns DW_DLV_OK if it succeeds + and DW_DLV_ERR or DW_DLV_OK otherwise. + count is set to the number of addresses in the + .debug_aranges section. + For each address, the corresponding element in + an array is set to the address itself(aranges) and + the section offset (offsets). + Must be identical in most aspects to + dwarf_get_aranges! +*/ +int +_dwarf_get_aranges_addr_offsets(Dwarf_Debug dbg, + Dwarf_Addr ** addrs, + Dwarf_Off ** offsets, + Dwarf_Signed * count, + Dwarf_Error * error) +{ + Dwarf_Unsigned i = 0; + + /* Used to chain Dwarf_Aranges structs. */ + Dwarf_Chain curr_chain = NULL; + Dwarf_Chain prev_chain = NULL; + Dwarf_Chain head_chain = NULL; + + Dwarf_Signed arange_count = 0; + Dwarf_Addr *arange_addrs = 0; + Dwarf_Off *arange_offsets = 0; + + int res = DW_DLV_ERROR; + + /* ***** BEGIN CODE ***** */ + + if (error != NULL) + *error = NULL; + + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + + res = _dwarf_load_section(dbg, &dbg->de_debug_aranges,error); + if (res != DW_DLV_OK) { + return res; + } + + res = dwarf_get_aranges_list(dbg,&head_chain,&arange_count,error); + if(res != DW_DLV_OK) { + return res; + } + + arange_addrs = (Dwarf_Addr *) + _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count); + if (arange_addrs == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + arange_offsets = (Dwarf_Off *) + _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count); + if (arange_offsets == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + curr_chain = head_chain; + for (i = 0; i < arange_count; i++) { + Dwarf_Arange ar = curr_chain->ch_item; + + arange_addrs[i] = ar->ar_address; + arange_offsets[i] = ar->ar_info_offset; + prev_chain = curr_chain; + curr_chain = curr_chain->ch_next; + dwarf_dealloc(dbg, ar, DW_DLA_ARANGE); + dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN); + } + *count = arange_count; + *offsets = arange_offsets; + *addrs = arange_addrs; + return (DW_DLV_OK); +} + + +/* + This function takes a pointer to a block + of Dwarf_Arange's, and a count of the + length of the block. It checks if the + given address is within the range of an + address range in the block. If yes, it + returns the appropriate Dwarf_Arange. + Otherwise, it returns DW_DLV_ERROR. +*/ +int +dwarf_get_arange(Dwarf_Arange * aranges, + Dwarf_Unsigned arange_count, + Dwarf_Addr address, + Dwarf_Arange * returned_arange, Dwarf_Error * error) +{ + Dwarf_Arange curr_arange = 0; + Dwarf_Unsigned i = 0; + + if (aranges == NULL) { + _dwarf_error(NULL, error, DW_DLE_ARANGES_NULL); + return (DW_DLV_ERROR); + } + for (i = 0; i < arange_count; i++) { + curr_arange = *(aranges + i); + if (address >= curr_arange->ar_address && + address < + curr_arange->ar_address + curr_arange->ar_length) { + *returned_arange = curr_arange; + return (DW_DLV_OK); + } + } + + return (DW_DLV_NO_ENTRY); +} + + +/* + This function takes an Dwarf_Arange, + and returns the offset of the first + die in the compilation-unit that the + arange belongs to. Returns DW_DLV_ERROR + on error. +*/ +int +dwarf_get_cu_die_offset(Dwarf_Arange arange, + Dwarf_Off * returned_offset, + Dwarf_Error * error) +{ + Dwarf_Debug dbg = 0; + Dwarf_Off offset = 0; + + if (arange == NULL) { + _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL); + return (DW_DLV_ERROR); + } + dbg = arange->ar_dbg; + offset = arange->ar_info_offset; + if (!dbg->de_debug_info.dss_data) { + int res = _dwarf_load_debug_info(dbg, error); + + if (res != DW_DLV_OK) { + return res; + } + } + *returned_offset = offset + _dwarf_length_of_cu_header(dbg, offset); + return DW_DLV_OK; +} + +/* + This function takes an Dwarf_Arange, + and returns the offset of the CU header + in the compilation-unit that the + arange belongs to. Returns DW_DLV_ERROR + on error. + Ensures .debug_info loaded so + the cu_offset is meaningful. +*/ +int +dwarf_get_arange_cu_header_offset(Dwarf_Arange arange, + Dwarf_Off * cu_header_offset_returned, + Dwarf_Error * error) +{ + Dwarf_Debug dbg = 0; + if (arange == NULL) { + _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL); + return (DW_DLV_ERROR); + } + dbg = arange->ar_dbg; + /* Like dwarf_get_arange_info this ensures debug_info loaded: + the cu_header is in debug_info and will be used else + we would not call dwarf_get_arange_cu_header_offset. */ + if (!dbg->de_debug_info.dss_data) { + int res = _dwarf_load_debug_info(dbg, error); + if (res != DW_DLV_OK) { + return res; + } + } + *cu_header_offset_returned = arange->ar_info_offset; + return DW_DLV_OK; +} + + + + +/* + This function takes a Dwarf_Arange, and returns + true if it is not NULL. It also stores the start + address of the range in *start, the length of the + range in *length, and the offset of the first die + in the compilation-unit in *cu_die_offset. It + returns false on error. + If cu_die_offset returned ensures .debug_info loaded so + the cu_die_offset is meaningful. +*/ +int +dwarf_get_arange_info(Dwarf_Arange arange, + Dwarf_Addr * start, + Dwarf_Unsigned * length, + Dwarf_Off * cu_die_offset, Dwarf_Error * error) +{ + if (arange == NULL) { + _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL); + return (DW_DLV_ERROR); + } + + if (start != NULL) + *start = arange->ar_address; + if (length != NULL) + *length = arange->ar_length; + if (cu_die_offset != NULL) { + Dwarf_Debug dbg = arange->ar_dbg; + Dwarf_Off offset = arange->ar_info_offset; + + if (!dbg->de_debug_info.dss_data) { + int res = _dwarf_load_debug_info(dbg, error); + if (res != DW_DLV_OK) { + return res; + } + } + *cu_die_offset = + offset + _dwarf_length_of_cu_header(dbg, offset); + } + return (DW_DLV_OK); +} + + +/* New for DWARF4, entries may have segment information. + *segment is only meaningful if *segment_entry_size is non-zero. */ +int +dwarf_get_arange_info_b(Dwarf_Arange arange, + Dwarf_Unsigned* segment, + Dwarf_Unsigned* segment_entry_size, + Dwarf_Addr * start, + Dwarf_Unsigned* length, + Dwarf_Off * cu_die_offset, + Dwarf_Error * error) +{ + if (arange == NULL) { + _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL); + return (DW_DLV_ERROR); + } + + if(segment != NULL) { + *segment = arange->ar_segment_selector; + } + if(segment_entry_size != NULL) { + *segment_entry_size = arange->ar_segment_selector_size; + } + if (start != NULL) + *start = arange->ar_address; + if (length != NULL) + *length = arange->ar_length; + if (cu_die_offset != NULL) { + Dwarf_Debug dbg = arange->ar_dbg; + Dwarf_Off offset = arange->ar_info_offset; + + if (!dbg->de_debug_info.dss_data) { + int res = _dwarf_load_debug_info(dbg, error); + if (res != DW_DLV_OK) { + return res; + } + } + *cu_die_offset = + offset + _dwarf_length_of_cu_header(dbg, offset); + } + return (DW_DLV_OK); +} diff --git a/usr/src/lib/libdwarf/common/dwarf_arange.h b/usr/src/lib/libdwarf/common/dwarf_arange.h new file mode 100644 index 0000000000..d6c537c452 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_arange.h @@ -0,0 +1,71 @@ +/* + + Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +/* This structure is used to read an arange into. */ +struct Dwarf_Arange_s { + + /* The segment selector. Only non-zero if Dwarf4, only + meaningful if ar_segment_selector_size non-zero */ + Dwarf_Unsigned ar_segment_selector; + + /* Starting address of the arange, ie low-pc. */ + Dwarf_Addr ar_address; + + /* Length of the arange. */ + Dwarf_Unsigned ar_length; + + + /* + Offset into .debug_info of the start of the compilation-unit + containing this set of aranges. */ + Dwarf_Off ar_info_offset; + + /* Corresponding Dwarf_Debug. */ + Dwarf_Debug ar_dbg; + + Dwarf_Half ar_segment_selector_size; +}; + + + +int + _dwarf_get_aranges_addr_offsets(Dwarf_Debug dbg, + Dwarf_Addr ** addrs, + Dwarf_Off ** offsets, + Dwarf_Signed * count, + Dwarf_Error * error); diff --git a/usr/src/lib/libdwarf/common/dwarf_base_types.h b/usr/src/lib/libdwarf/common/dwarf_base_types.h new file mode 100644 index 0000000000..00e2700a81 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_base_types.h @@ -0,0 +1,123 @@ +/* + + Copyright (C) 2000,2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2008-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "libdwarfdefs.h" + +#define true 1 +#define false 0 + +/* to identify a cie */ +#define DW_CIE_ID ~(0x0) +#define DW_CIE_VERSION 1 /* DWARF2 */ +#define DW_CIE_VERSION3 3 /* DWARF3 */ +#define DW_CIE_VERSION4 4 /* DWARF4 */ + +#define DW_CU_VERSION2 2 +#define DW_CU_VERSION3 3 +#define DW_CU_VERSION4 4 + +/* DWARF2,3 and 4 */ +#define DW_ARANGES_VERSION2 2 + +#define DW_LINE_VERSION2 2 +#define DW_LINE_VERSION3 3 +#define DW_LINE_VERSION4 4 + + +/* + These are allocation type codes for structs that + are internal to the Libdwarf Consumer library. +*/ +#define DW_DLA_ABBREV_LIST DW_DLA_RANGES + 1 +#define DW_DLA_CHAIN DW_DLA_RANGES + 2 +#define DW_DLA_CU_CONTEXT DW_DLA_RANGES + 3 +#define DW_DLA_FRAME DW_DLA_RANGES + 4 +#define DW_DLA_GLOBAL_CONTEXT DW_DLA_RANGES + 5 +#define DW_DLA_FILE_ENTRY DW_DLA_RANGES + 6 +#define DW_DLA_LINE_CONTEXT DW_DLA_RANGES + 7 +#define DW_DLA_LOC_CHAIN DW_DLA_RANGES + 8 +#define DW_DLA_HASH_TABLE DW_DLA_RANGES + 9 +#define DW_DLA_FUNC_CONTEXT DW_DLA_RANGES + 10 +#define DW_DLA_TYPENAME_CONTEXT DW_DLA_RANGES + 11 +#define DW_DLA_VAR_CONTEXT DW_DLA_RANGES + 12 +#define DW_DLA_WEAK_CONTEXT DW_DLA_RANGES + 13 +#define DW_DLA_PUBTYPES_CONTEXT DW_DLA_RANGES + 14 /* DWARF3 */ +#define DW_DLA_HASH_TABLE_ENTRY DW_DLA_RANGES + 15 + +/* Maximum number of allocation types for allocation routines. */ +#define MAX_DW_DLA DW_DLA_HASH_TABLE_ENTRY + +/*Dwarf_Word is unsigned word usable for index, count in memory */ +/*Dwarf_Sword is signed word usable for index, count in memory */ +/* The are 32 or 64 bits depending if 64 bit longs or not, which +** fits the ILP32 and LP64 models +** These work equally well with ILP64. +*/ + +typedef unsigned long Dwarf_Word; +typedef signed long Dwarf_Sword; + +typedef signed char Dwarf_Sbyte; +typedef unsigned char Dwarf_Ubyte; +typedef signed short Dwarf_Shalf; +typedef Dwarf_Small *Dwarf_Byte_Ptr; + +/* these 2 are fixed sizes which must not vary with the +** ILP32/LP64 model. Between these two, stay at 32 bit. +*/ +typedef __uint32_t Dwarf_ufixed; +typedef __int32_t Dwarf_sfixed; + +/* + In various places the code mistakenly associates + forms 8 bytes long with Dwarf_Signed or Dwarf_Unsigned + This is not a very portable assumption. + The following should be used instead for 64 bit integers. +*/ +typedef __uint64_t Dwarf_ufixed64; +typedef __int64_t Dwarf_sfixed64; + + +typedef struct Dwarf_Abbrev_List_s *Dwarf_Abbrev_List; +typedef struct Dwarf_File_Entry_s *Dwarf_File_Entry; +typedef struct Dwarf_CU_Context_s *Dwarf_CU_Context; +typedef struct Dwarf_Hash_Table_s *Dwarf_Hash_Table; +typedef struct Dwarf_Hash_Table_Entry_s *Dwarf_Hash_Table_Entry; + + +typedef struct Dwarf_Alloc_Hdr_s *Dwarf_Alloc_Hdr; diff --git a/usr/src/lib/libdwarf/common/dwarf_die_deliv.c b/usr/src/lib/libdwarf/common/dwarf_die_deliv.c new file mode 100644 index 0000000000..4ba9f2aded --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_die_deliv.c @@ -0,0 +1,855 @@ +/* + + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + + + +#include "config.h" +#include "dwarf_incl.h" +#ifdef HAVE_ELF_H +#include +#endif +#include +#include "dwarf_die_deliv.h" + + +/* + For a given Dwarf_Debug dbg, this function checks + if a CU that includes the given offset has been read + or not. If yes, it returns the Dwarf_CU_Context + for the CU. Otherwise it returns NULL. Being an + internal routine, it is assumed that a valid dbg + is passed. + + **This is a sequential search. May be too slow. + + If debug_info and debug_abbrev not loaded, this will + wind up returning NULL. So no need to load before calling + this. +*/ +static Dwarf_CU_Context +_dwarf_find_CU_Context(Dwarf_Debug dbg, Dwarf_Off offset) +{ + Dwarf_CU_Context cu_context = 0; + + if (offset >= dbg->de_info_last_offset) + return (NULL); + + if (dbg->de_cu_context != NULL && + dbg->de_cu_context->cc_next != NULL && + dbg->de_cu_context->cc_next->cc_debug_info_offset == offset) { + + return (dbg->de_cu_context->cc_next); + } + + if (dbg->de_cu_context != NULL && + dbg->de_cu_context->cc_debug_info_offset <= offset) { + + for (cu_context = dbg->de_cu_context; + cu_context != NULL; cu_context = cu_context->cc_next) { + + if (offset >= cu_context->cc_debug_info_offset && + offset < cu_context->cc_debug_info_offset + + cu_context->cc_length + cu_context->cc_length_size + + cu_context->cc_extension_size) { + + return (cu_context); + } + } + } + + for (cu_context = dbg->de_cu_context_list; + cu_context != NULL; cu_context = cu_context->cc_next) { + + if (offset >= cu_context->cc_debug_info_offset && + offset < cu_context->cc_debug_info_offset + + cu_context->cc_length + cu_context->cc_length_size + + cu_context->cc_extension_size) { + + return (cu_context); + } + } + + return (NULL); +} + + +/* + This routine checks the dwarf_offdie() list of + CU contexts for the right CU context. +*/ +static Dwarf_CU_Context +_dwarf_find_offdie_CU_Context(Dwarf_Debug dbg, Dwarf_Off offset) +{ + Dwarf_CU_Context cu_context = 0; + + for (cu_context = dbg->de_offdie_cu_context; + cu_context != NULL; cu_context = cu_context->cc_next) + + if (offset >= cu_context->cc_debug_info_offset && + offset < cu_context->cc_debug_info_offset + + cu_context->cc_length + cu_context->cc_length_size + + cu_context->cc_extension_size) + + return (cu_context); + + return (NULL); +} + + +/* + This function is used to create a CU Context for + a compilation-unit that begins at offset in + .debug_info. The CU Context is attached to the + list of CU Contexts for this dbg. It is assumed + that the CU at offset has not been read before, + and so do not call this routine before making + sure of this with _dwarf_find_CU_Context(). + Returns NULL on error. As always, being an + internal routine, assumes a good dbg. + + This function must always set a dwarf error code + before returning NULL. Always. +*/ +static Dwarf_CU_Context +_dwarf_make_CU_Context(Dwarf_Debug dbg, + Dwarf_Off offset, Dwarf_Error * error) +{ + Dwarf_CU_Context cu_context = 0; + Dwarf_Unsigned length = 0; + Dwarf_Signed abbrev_offset = 0; + Dwarf_Byte_Ptr cu_ptr = 0; + int local_extension_size = 0; + int local_length_size = 0; + + cu_context = + (Dwarf_CU_Context) _dwarf_get_alloc(dbg, DW_DLA_CU_CONTEXT, 1); + if (cu_context == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (NULL); + } + cu_context->cc_dbg = dbg; + + cu_ptr = (Dwarf_Byte_Ptr) (dbg->de_debug_info.dss_data + offset); + + /* READ_AREA_LENGTH updates cu_ptr for consumed bytes */ + READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned, + cu_ptr, local_length_size, local_extension_size); + cu_context->cc_length_size = local_length_size; + cu_context->cc_extension_size = local_extension_size; + + + cu_context->cc_length = (Dwarf_Word) length; + + READ_UNALIGNED(dbg, cu_context->cc_version_stamp, Dwarf_Half, + cu_ptr, sizeof(Dwarf_Half)); + cu_ptr += sizeof(Dwarf_Half); + + READ_UNALIGNED(dbg, abbrev_offset, Dwarf_Signed, + cu_ptr, local_length_size); + cu_ptr += local_length_size; + cu_context->cc_abbrev_offset = (Dwarf_Sword) abbrev_offset; + + cu_context->cc_address_size = *(Dwarf_Small *) cu_ptr; + + if ((length < CU_VERSION_STAMP_SIZE + local_length_size + + CU_ADDRESS_SIZE_SIZE) || + (offset + length + local_length_size + + local_extension_size > dbg->de_debug_info.dss_size)) { + + dwarf_dealloc(dbg, cu_context, DW_DLA_CU_CONTEXT); + _dwarf_error(dbg, error, DW_DLE_CU_LENGTH_ERROR); + return (NULL); + } + + if (cu_context->cc_version_stamp != CURRENT_VERSION_STAMP + && cu_context->cc_version_stamp != CURRENT_VERSION_STAMP3 + && cu_context->cc_version_stamp != CURRENT_VERSION_STAMP4) { + dwarf_dealloc(dbg, cu_context, DW_DLA_CU_CONTEXT); + _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR); + return (NULL); + } + + if (abbrev_offset >= dbg->de_debug_abbrev.dss_size) { + dwarf_dealloc(dbg, cu_context, DW_DLA_CU_CONTEXT); + _dwarf_error(dbg, error, DW_DLE_ABBREV_OFFSET_ERROR); + return (NULL); + } + + cu_context->cc_abbrev_hash_table = + (Dwarf_Hash_Table) _dwarf_get_alloc(dbg, DW_DLA_HASH_TABLE, 1); + if (cu_context->cc_abbrev_hash_table == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (NULL); + } + + cu_context->cc_debug_info_offset = (Dwarf_Word) offset; + dbg->de_info_last_offset = + (Dwarf_Word) (offset + length + + local_extension_size + local_length_size); + + if (dbg->de_cu_context_list == NULL) { + dbg->de_cu_context_list = cu_context; + dbg->de_cu_context_list_end = cu_context; + } else { + dbg->de_cu_context_list_end->cc_next = cu_context; + dbg->de_cu_context_list_end = cu_context; + } + + return (cu_context); +} + + +/* + Returns offset of next compilation-unit thru next_cu_offset + pointer. + It basically sequentially moves from one + cu to the next. The current cu is recorded + internally by libdwarf. + + The _b form is new for DWARF4 adding new returned fields. +*/ +int +dwarf_next_cu_header(Dwarf_Debug dbg, + Dwarf_Unsigned * cu_header_length, + Dwarf_Half * version_stamp, + Dwarf_Unsigned * abbrev_offset, + Dwarf_Half * address_size, + Dwarf_Unsigned * next_cu_offset, + Dwarf_Error * error) +{ + return dwarf_next_cu_header_b(dbg, + cu_header_length, + version_stamp, + abbrev_offset, + address_size, + 0,0, + next_cu_offset, + error); +} +int +dwarf_next_cu_header_b(Dwarf_Debug dbg, + Dwarf_Unsigned * cu_header_length, + Dwarf_Half * version_stamp, + Dwarf_Unsigned * abbrev_offset, + Dwarf_Half * address_size, + Dwarf_Half * offset_size, + Dwarf_Half * extension_size, + Dwarf_Unsigned * next_cu_offset, + Dwarf_Error * error) +{ + /* Offset for current and new CU. */ + Dwarf_Unsigned new_offset = 0; + + /* CU Context for current CU. */ + Dwarf_CU_Context cu_context = 0; + + /* ***** BEGIN CODE ***** */ + + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + /* + Get offset into .debug_info of next CU. If dbg has no context, + this has to be the first one. */ + if (dbg->de_cu_context == NULL) { + new_offset = 0; + if (!dbg->de_debug_info.dss_data) { + int res = _dwarf_load_debug_info(dbg, error); + + if (res != DW_DLV_OK) { + return res; + } + } + + } else { + new_offset = dbg->de_cu_context->cc_debug_info_offset + + dbg->de_cu_context->cc_length + + dbg->de_cu_context->cc_length_size + + dbg->de_cu_context->cc_extension_size; + } + + /* + Check that there is room in .debug_info beyond the new offset + for at least a new cu header. If not, return 0 to indicate end + of debug_info section, and reset de_cu_debug_info_offset to + enable looping back through the cu's. */ + if ((new_offset + _dwarf_length_of_cu_header_simple(dbg)) >= + dbg->de_debug_info.dss_size) { + dbg->de_cu_context = NULL; + return (DW_DLV_NO_ENTRY); + } + + /* Check if this CU has been read before. */ + cu_context = _dwarf_find_CU_Context(dbg, new_offset); + + /* If not, make CU Context for it. */ + if (cu_context == NULL) { + cu_context = _dwarf_make_CU_Context(dbg, new_offset, error); + if (cu_context == NULL) { + /* Error if CU Context could not be made. Since + _dwarf_make_CU_Context has already registered an error + we do not do that here: we let the lower error pass + thru. */ + return (DW_DLV_ERROR); + } + } + + dbg->de_cu_context = cu_context; + + if (cu_header_length != NULL) + *cu_header_length = cu_context->cc_length; + + if (version_stamp != NULL) + *version_stamp = cu_context->cc_version_stamp; + + if (abbrev_offset != NULL) + *abbrev_offset = cu_context->cc_abbrev_offset; + + if (address_size != NULL) + *address_size = cu_context->cc_address_size; + if (offset_size != NULL) + *offset_size = cu_context->cc_length_size; + if (extension_size != NULL) + *extension_size = cu_context->cc_extension_size; + + new_offset = new_offset + cu_context->cc_length + + cu_context->cc_length_size + cu_context->cc_extension_size; + *next_cu_offset = new_offset; + return (DW_DLV_OK); +} + + +/* + This function does two slightly different things + depending on the input flag want_AT_sibling. If + this flag is true, it checks if the input die has + a DW_AT_sibling attribute. If it does it returns + a pointer to the start of the sibling die in the + .debug_info section. Otherwise it behaves the + same as the want_AT_sibling false case. + + If the want_AT_sibling flag is false, it returns + a pointer to the immediately adjacent die in the + .debug_info section. + + Die_info_end points to the end of the .debug_info + portion for the cu the die belongs to. It is used + to check that the search for the next die does not + cross the end of the current cu. Cu_info_start points + to the start of the .debug_info portion for the + current cu, and is used to add to the offset for + DW_AT_sibling attributes. Finally, has_die_child + is a pointer to a Dwarf_Bool that is set true if + the present die has children, false otherwise. + However, in case want_AT_child is true and the die + has a DW_AT_sibling attribute *has_die_child is set + false to indicate that the children are being skipped. + + die_info_end points to the last byte+1 of the cu. + +*/ +static Dwarf_Byte_Ptr +_dwarf_next_die_info_ptr(Dwarf_Byte_Ptr die_info_ptr, + Dwarf_CU_Context cu_context, + Dwarf_Byte_Ptr die_info_end, + Dwarf_Byte_Ptr cu_info_start, + Dwarf_Bool want_AT_sibling, + Dwarf_Bool * has_die_child) +{ + Dwarf_Byte_Ptr info_ptr = 0; + Dwarf_Byte_Ptr abbrev_ptr = 0; + Dwarf_Word abbrev_code = 0; + Dwarf_Abbrev_List abbrev_list; + Dwarf_Half attr = 0; + Dwarf_Half attr_form = 0; + Dwarf_Unsigned offset = 0; + Dwarf_Word leb128_length = 0; + Dwarf_Unsigned utmp = 0; + Dwarf_Debug dbg = 0; + + info_ptr = die_info_ptr; + DECODE_LEB128_UWORD(info_ptr, utmp); + abbrev_code = (Dwarf_Word) utmp; + if (abbrev_code == 0) { + return NULL; + } + + + abbrev_list = _dwarf_get_abbrev_for_code(cu_context, abbrev_code); + if (abbrev_list == NULL) { + return (NULL); + } + dbg = cu_context->cc_dbg; + + *has_die_child = abbrev_list->ab_has_child; + + abbrev_ptr = abbrev_list->ab_abbrev_ptr; + do { + Dwarf_Unsigned utmp2; + + DECODE_LEB128_UWORD(abbrev_ptr, utmp2); + attr = (Dwarf_Half) utmp2; + DECODE_LEB128_UWORD(abbrev_ptr, utmp2); + attr_form = (Dwarf_Half) utmp2; + if (attr_form == DW_FORM_indirect) { + Dwarf_Unsigned utmp6; + + /* DECODE_LEB128_UWORD updates info_ptr */ + DECODE_LEB128_UWORD(info_ptr, utmp6); + attr_form = (Dwarf_Half) utmp6; + + } + + if (want_AT_sibling && attr == DW_AT_sibling) { + switch (attr_form) { + case DW_FORM_ref1: + offset = *(Dwarf_Small *) info_ptr; + break; + case DW_FORM_ref2: + /* READ_UNALIGNED does not update info_ptr */ + READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, + info_ptr, sizeof(Dwarf_Half)); + break; + case DW_FORM_ref4: + READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, + info_ptr, sizeof(Dwarf_ufixed)); + break; + case DW_FORM_ref8: + READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, + info_ptr, sizeof(Dwarf_Unsigned)); + break; + case DW_FORM_ref_udata: + offset = + _dwarf_decode_u_leb128(info_ptr, &leb128_length); + break; + case DW_FORM_ref_addr: + /* Very unusual. The FORM is intended to refer to + a different CU, but a different CU cannot + be a sibling, can it? + We could ignore this and treat as if no DW_AT_sibling + present. Or derive the offset from it and if + it is in the same CU use it directly. + The offset here is *supposed* to be a global offset, + so adding cu_info_start is wrong to any offset + we find here unless cu_info_start + is zero! Lets pretend there is no DW_AT_sibling + attribute. */ + goto no_sibling_attr; + default: + return (NULL); + } + + /* Reset *has_die_child to indicate children skipped. */ + *has_die_child = false; + + /* A value beyond die_info_end indicates an error. Exactly + at die_info_end means 1-past-cu-end and simply means we + are at the end, do not return NULL. Higher level code + will detect that we are at the end. */ + if (cu_info_start + offset > die_info_end) { + /* Error case, bad DWARF. */ + return (NULL); + } + /* At or before end-of-cu */ + return (cu_info_start + offset); + } + + no_sibling_attr: + if (attr_form != 0) { + info_ptr += _dwarf_get_size_of_val(cu_context->cc_dbg, + attr_form, + cu_context->cc_address_size, + info_ptr, + cu_context->cc_length_size); + /* It is ok for info_ptr == die_info_end, as we will test + later before using a too-large info_ptr */ + if (info_ptr > die_info_end) { + /* More than one-past-end indicates a bug somewhere, + likely bad dwarf generation. */ + return (NULL); + } + } + } while (attr != 0 || attr_form != 0); + + return (info_ptr); +} + + +/* + Given a Dwarf_Debug dbg, and a Dwarf_Die die, it returns + a Dwarf_Die for the sibling of die. In case die is NULL, + it returns (thru ptr) a Dwarf_Die for the first die in the current + cu in dbg. Returns DW_DLV_ERROR on error. + + It is assumed that every sibling chain including those with + only one element is terminated with a NULL die, except a + chain with only a NULL die. + + The algorithm moves from one die to the adjacent one. It + returns when the depth of children it sees equals the number + of sibling chain terminations. A single count, child_depth + is used to track the depth of children and sibling terminations + encountered. Child_depth is incremented when a die has the + Has-Child flag set unless the child happens to be a NULL die. + Child_depth is decremented when a die has Has-Child false, + and the adjacent die is NULL. Algorithm returns when + child_depth is 0. + + **NOTE: Do not modify input die, since it is used at the end. +*/ +int +dwarf_siblingof(Dwarf_Debug dbg, + Dwarf_Die die, + Dwarf_Die * caller_ret_die, Dwarf_Error * error) +{ + Dwarf_Die ret_die = 0; + Dwarf_Byte_Ptr die_info_ptr = 0; + Dwarf_Byte_Ptr cu_info_start = 0; + + /* die_info_end points 1-past end of die (once set) */ + Dwarf_Byte_Ptr die_info_end = 0; + Dwarf_Word abbrev_code = 0; + Dwarf_Unsigned utmp = 0; + + + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + + if (die == NULL) { + /* Find root die of cu */ + /* die_info_end is untouched here, need not be set in this + branch. */ + Dwarf_Off off2; + + /* If we've not loaded debug_info, de_cu_context will be NULL, + so no need to laod */ + + if (dbg->de_cu_context == NULL) { + _dwarf_error(dbg, error, DW_DLE_DBG_NO_CU_CONTEXT); + return (DW_DLV_ERROR); + } + + off2 = dbg->de_cu_context->cc_debug_info_offset; + die_info_ptr = dbg->de_debug_info.dss_data + + off2 + _dwarf_length_of_cu_header(dbg, off2); + } else { + /* Find sibling die. */ + Dwarf_Bool has_child = false; + Dwarf_Sword child_depth = 0; + + /* We cannot have a legal die unless debug_info was loaded, so + no need to load debug_info here. */ + CHECK_DIE(die, DW_DLV_ERROR); + + die_info_ptr = die->di_debug_info_ptr; + if (*die_info_ptr == 0) { + return (DW_DLV_NO_ENTRY); + } + cu_info_start = dbg->de_debug_info.dss_data + + die->di_cu_context->cc_debug_info_offset; + die_info_end = cu_info_start + die->di_cu_context->cc_length + + die->di_cu_context->cc_length_size + + die->di_cu_context->cc_extension_size; + + if ((*die_info_ptr) == 0) { + return (DW_DLV_NO_ENTRY); + } + child_depth = 0; + do { + die_info_ptr = _dwarf_next_die_info_ptr(die_info_ptr, + die->di_cu_context, + die_info_end, + cu_info_start, true, + &has_child); + if (die_info_ptr == NULL) { + _dwarf_error(dbg, error, DW_DLE_NEXT_DIE_PTR_NULL); + return (DW_DLV_ERROR); + } + + /* die_info_end is one past end. Do not read it! + A test for ``!= die_info_end'' would work as well, + but perhaps < reads more like the meaning. */ + if(die_info_ptr < die_info_end) { + if ((*die_info_ptr) == 0 && has_child) { + die_info_ptr++; + has_child = false; + } + } + + /* die_info_ptr can be one-past-end. */ + if ((die_info_ptr == die_info_end) || + ((*die_info_ptr) == 0)) { + for (; child_depth > 0 && *die_info_ptr == 0; + child_depth--, die_info_ptr++); + } else { + child_depth = has_child ? child_depth + 1 : child_depth; + } + + } while (child_depth != 0); + } + + /* die_info_ptr > die_info_end is really a bug (possibly in dwarf + generation)(but we are past end, no more DIEs here), whereas + die_info_ptr == die_info_end means 'one past end, no more DIEs + here'. */ + if (die != NULL && die_info_ptr >= die_info_end) { + return (DW_DLV_NO_ENTRY); + } + + if ((*die_info_ptr) == 0) { + return (DW_DLV_NO_ENTRY); + } + + ret_die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1); + if (ret_die == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + ret_die->di_debug_info_ptr = die_info_ptr; + ret_die->di_cu_context = + die == NULL ? dbg->de_cu_context : die->di_cu_context; + + DECODE_LEB128_UWORD(die_info_ptr, utmp); + abbrev_code = (Dwarf_Word) utmp; + if (abbrev_code == 0) { + /* Zero means a null DIE */ + dwarf_dealloc(dbg, ret_die, DW_DLA_DIE); + return (DW_DLV_NO_ENTRY); + } + ret_die->di_abbrev_code = abbrev_code; + ret_die->di_abbrev_list = + _dwarf_get_abbrev_for_code(ret_die->di_cu_context, abbrev_code); + if (ret_die->di_abbrev_list == NULL || (die == NULL && + ret_die->di_abbrev_list-> + ab_tag != + DW_TAG_compile_unit)) { + dwarf_dealloc(dbg, ret_die, DW_DLA_DIE); + _dwarf_error(dbg, error, DW_DLE_FIRST_DIE_NOT_CU); + return (DW_DLV_ERROR); + } + + *caller_ret_die = ret_die; + return (DW_DLV_OK); +} + + +int +dwarf_child(Dwarf_Die die, + Dwarf_Die * caller_ret_die, Dwarf_Error * error) +{ + Dwarf_Byte_Ptr die_info_ptr = 0; + + /* die_info_end points one-past-end of die area. */ + Dwarf_Byte_Ptr die_info_end = 0; + Dwarf_Die ret_die = 0; + Dwarf_Bool has_die_child = 0; + Dwarf_Debug dbg; + Dwarf_Word abbrev_code = 0; + Dwarf_Unsigned utmp = 0; + + + CHECK_DIE(die, DW_DLV_ERROR); + dbg = die->di_cu_context->cc_dbg; + die_info_ptr = die->di_debug_info_ptr; + + /* NULL die has no child. */ + if ((*die_info_ptr) == 0) + return (DW_DLV_NO_ENTRY); + + die_info_end = dbg->de_debug_info.dss_data + + die->di_cu_context->cc_debug_info_offset + + die->di_cu_context->cc_length + + die->di_cu_context->cc_length_size + + die->di_cu_context->cc_extension_size; + + die_info_ptr = + _dwarf_next_die_info_ptr(die_info_ptr, die->di_cu_context, + die_info_end, NULL, false, + &has_die_child); + if (die_info_ptr == NULL) { + _dwarf_error(dbg, error, DW_DLE_NEXT_DIE_PTR_NULL); + return (DW_DLV_ERROR); + } + + if (!has_die_child) + return (DW_DLV_NO_ENTRY); + + ret_die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1); + if (ret_die == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + ret_die->di_debug_info_ptr = die_info_ptr; + ret_die->di_cu_context = die->di_cu_context; + + DECODE_LEB128_UWORD(die_info_ptr, utmp); + abbrev_code = (Dwarf_Word) utmp; + if (abbrev_code == 0) { + /* We have arrived at a null DIE, at the end of a CU or the end + of a list of siblings. */ + *caller_ret_die = 0; + dwarf_dealloc(dbg, ret_die, DW_DLA_DIE); + return DW_DLV_NO_ENTRY; + } + ret_die->di_abbrev_code = abbrev_code; + ret_die->di_abbrev_list = + _dwarf_get_abbrev_for_code(die->di_cu_context, abbrev_code); + if (ret_die->di_abbrev_list == NULL) { + dwarf_dealloc(dbg, ret_die, DW_DLA_DIE); + _dwarf_error(dbg, error, DW_DLE_DIE_BAD); + return (DW_DLV_ERROR); + } + + *caller_ret_die = ret_die; + return (DW_DLV_OK); +} + +/* + Given a (global, not cu_relative) die offset, this returns + a pointer to a DIE thru *new_die. + It is up to the caller to do a + dwarf_dealloc(dbg,*new_die,DW_DLE_DIE); +*/ +int +dwarf_offdie(Dwarf_Debug dbg, + Dwarf_Off offset, Dwarf_Die * new_die, Dwarf_Error * error) +{ + Dwarf_CU_Context cu_context = 0; + Dwarf_Off new_cu_offset = 0; + Dwarf_Die die = 0; + Dwarf_Byte_Ptr info_ptr = 0; + Dwarf_Unsigned abbrev_code = 0; + Dwarf_Unsigned utmp = 0; + + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + + cu_context = _dwarf_find_CU_Context(dbg, offset); + if (cu_context == NULL) + cu_context = _dwarf_find_offdie_CU_Context(dbg, offset); + + if (cu_context == NULL) { + int res = _dwarf_load_debug_info(dbg, error); + + if (res != DW_DLV_OK) { + return res; + } + + if (dbg->de_offdie_cu_context_end != NULL) { + Dwarf_CU_Context lcu_context = + dbg->de_offdie_cu_context_end; + new_cu_offset = + lcu_context->cc_debug_info_offset + + lcu_context->cc_length + + lcu_context->cc_length_size + + lcu_context->cc_extension_size; + } + + + do { + if ((new_cu_offset + + _dwarf_length_of_cu_header_simple(dbg)) >= + dbg->de_debug_info.dss_size) { + _dwarf_error(dbg, error, DW_DLE_OFFSET_BAD); + return (DW_DLV_ERROR); + } + + cu_context = + _dwarf_make_CU_Context(dbg, new_cu_offset, error); + if (cu_context == NULL) { + /* Error if CU Context could not be made. Since + _dwarf_make_CU_Context has already registered an + error we do not do that here: we let the lower error + pass thru. */ + + return (DW_DLV_ERROR); + } + + if (dbg->de_offdie_cu_context == NULL) { + dbg->de_offdie_cu_context = cu_context; + dbg->de_offdie_cu_context_end = cu_context; + } else { + dbg->de_offdie_cu_context_end->cc_next = cu_context; + dbg->de_offdie_cu_context_end = cu_context; + } + + new_cu_offset = new_cu_offset + cu_context->cc_length + + cu_context->cc_length_size; + + } while (offset >= new_cu_offset); + } + + die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1); + if (die == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + die->di_cu_context = cu_context; + + info_ptr = dbg->de_debug_info.dss_data + offset; + die->di_debug_info_ptr = info_ptr; + DECODE_LEB128_UWORD(info_ptr, utmp); + abbrev_code = utmp; + if (abbrev_code == 0) { + /* we are at a null DIE (or there is a bug). */ + *new_die = 0; + dwarf_dealloc(dbg, die, DW_DLA_DIE); + return DW_DLV_NO_ENTRY; + } + die->di_abbrev_code = abbrev_code; + die->di_abbrev_list = + _dwarf_get_abbrev_for_code(cu_context, abbrev_code); + if (die->di_abbrev_list == NULL) { + dwarf_dealloc(dbg, die, DW_DLA_DIE); + _dwarf_error(dbg, error, DW_DLE_DIE_ABBREV_LIST_NULL); + return (DW_DLV_ERROR); + } + + *new_die = die; + return (DW_DLV_OK); +} diff --git a/usr/src/lib/libdwarf/common/dwarf_die_deliv.h b/usr/src/lib/libdwarf/common/dwarf_die_deliv.h new file mode 100644 index 0000000000..f1ecb153ba --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_die_deliv.h @@ -0,0 +1,57 @@ +/* + + Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2008-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + + +/* + This struct holds information about a abbreviation. + It is put in the hash table for abbreviations for + a compile-unit. +*/ +struct Dwarf_Abbrev_List_s { + + Dwarf_Unsigned ab_code; + Dwarf_Half ab_tag; + Dwarf_Half ab_has_child; + + /* + Points to start of attribute and form pairs in the .debug_abbrev + section for the abbrev. */ + Dwarf_Byte_Ptr ab_abbrev_ptr; + + struct Dwarf_Abbrev_List_s *ab_next; +}; diff --git a/usr/src/lib/libdwarf/common/dwarf_elf_access.c b/usr/src/lib/libdwarf/common/dwarf_elf_access.c new file mode 100644 index 0000000000..6caa64a758 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_elf_access.c @@ -0,0 +1,976 @@ +/* + Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2008-2010 Arxan Technologies, Inc. All Rights Reserved. + Portions Copyright 2009-2010 David Anderson. All rights reserved. + Portions Copyright 2009-2010 Novell Inc. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + +#include "config.h" +#include "dwarf_incl.h" +#include "dwarf_elf_access.h" + +#ifdef HAVE_ELF_H +#include +#endif +#ifdef HAVE_LIBELF_H +#include +#else +#ifdef HAVE_LIBELF_LIBELF_H +#include +#endif +#endif + +#include +#include +#include +#include +#include + +#define FALSE 0 +#define TRUE 1 + +#ifndef EM_MIPS +/* This is the standard elf value EM_MIPS. */ +#define EM_MIPS 8 +#endif + + +#ifdef HAVE_ELF64_GETEHDR +extern Elf64_Ehdr *elf64_getehdr(Elf *); +#endif +#ifdef HAVE_ELF64_GETSHDR +extern Elf64_Shdr *elf64_getshdr(Elf_Scn *); +#endif +#ifdef WORDS_BIGENDIAN +#define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \ + { \ + dbg->de_copy_word(dest, \ + ((char *)source) +srclength-len_out, \ + len_out) ; \ + } + + +#else /* LITTLE ENDIAN */ + +#define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \ + { \ + dbg->de_copy_word( (dest) , \ + ((char *)source) , \ + len_out) ; \ + } +#endif + + + +typedef struct { + dwarf_elf_handle elf; + int is_64bit; + Dwarf_Small length_size; + Dwarf_Small pointer_size; + Dwarf_Unsigned section_count; + Dwarf_Endianness endianness; + Dwarf_Small machine; + int libdwarf_owns_elf; + Elf32_Ehdr *ehdr32; + +#ifdef HAVE_ELF64_GETEHDR + Elf64_Ehdr *ehdr64; +#endif + /* Elf symtab and its strtab. Initialized at first + call to do relocations, the actual data is in the Dwarf_Debug + struct, not allocated locally here. */ + struct Dwarf_Section_s *symtab; + struct Dwarf_Section_s *strtab; + +} dwarf_elf_object_access_internals_t; + +struct Dwarf_Elf_Rela { + Dwarf_ufixed64 r_offset; + /*Dwarf_ufixed64 r_info; */ + Dwarf_ufixed64 r_type; + Dwarf_ufixed64 r_symidx; + Dwarf_ufixed64 r_addend; +}; + + +static int dwarf_elf_object_access_load_section(void* obj_in, + Dwarf_Half section_index, + Dwarf_Small** section_data, + int* error); + +/* + dwarf_elf_object_access_internals_init() + */ +static int +dwarf_elf_object_access_internals_init(void* obj_in, + dwarf_elf_handle elf, + int* error) +{ + dwarf_elf_object_access_internals_t*obj = + (dwarf_elf_object_access_internals_t*)obj_in; + char *ehdr_ident = 0; + Dwarf_Half machine = 0; + obj->elf = elf; + + if ((ehdr_ident = elf_getident(elf, NULL)) == NULL) { + *error = DW_DLE_ELF_GETIDENT_ERROR; + return DW_DLV_ERROR; + } + + obj->is_64bit = (ehdr_ident[EI_CLASS] == ELFCLASS64); + + + if(ehdr_ident[EI_DATA] == ELFDATA2LSB){ + obj->endianness = DW_OBJECT_LSB; + } + else if(ehdr_ident[EI_DATA] == ELFDATA2MSB){ + obj->endianness = DW_OBJECT_MSB; + } + + if (obj->is_64bit) { +#ifdef HAVE_ELF64_GETEHDR + obj->ehdr64 = elf64_getehdr(elf); + if (obj->ehdr64 == NULL) { + *error = DW_DLE_ELF_GETEHDR_ERROR; + return DW_DLV_ERROR; + } + obj->section_count = obj->ehdr64->e_shnum; + machine = obj->ehdr64->e_machine; + obj->machine = machine; +#else + *error = DW_DLE_NO_ELF64_SUPPORT; + return DW_DLV_ERROR; +#endif + } + else { + obj->ehdr32 = elf32_getehdr(elf); + if (obj->ehdr32 == NULL) { + *error = DW_DLE_ELF_GETEHDR_ERROR; + return DW_DLV_ERROR; + } + obj->section_count = obj->ehdr32->e_shnum; + machine = obj->ehdr32->e_machine; + obj->machine = machine; + } + + /* The following length_size is Not Too Significant. Only used + one calculation, and an approximate one at that. */ + obj->length_size = obj->is_64bit ? 8 : 4; + obj->pointer_size = obj->is_64bit ? 8 : 4; + + if (obj->is_64bit && machine != EM_MIPS) { + /* MIPS/IRIX makes pointer size and length size 8 for -64. + Other platforms make length 4 always. */ + /* 4 here supports 32bit-offset dwarf2, as emitted by cygnus + tools, and the dwarfv2.1 64bit extension setting. + This is not the same as the size-of-an-offset, which + is 4 in 32bit dwarf and 8 in 64bit dwarf. */ + obj->length_size = 4; + } + return DW_DLV_OK; +} + +/* + dwarf_elf_object_access_get_byte_order + */ +static +Dwarf_Endianness +dwarf_elf_object_access_get_byte_order(void* obj_in) +{ + dwarf_elf_object_access_internals_t*obj = + (dwarf_elf_object_access_internals_t*)obj_in; + return obj->endianness; +} + +/* + dwarf_elf_object_access_get_section_count() + */ +static +Dwarf_Unsigned +dwarf_elf_object_access_get_section_count(void * obj_in) +{ + dwarf_elf_object_access_internals_t*obj = + (dwarf_elf_object_access_internals_t*)obj_in; + return obj->section_count; +} + + +/* + dwarf_elf_object_access_get_section() + */ +static +int +dwarf_elf_object_access_get_section_info( + void* obj_in, + Dwarf_Half section_index, + Dwarf_Obj_Access_Section* ret_scn, + int* error) +{ + dwarf_elf_object_access_internals_t*obj = + (dwarf_elf_object_access_internals_t*)obj_in; + + Elf32_Shdr *shdr32 = 0; + +#ifdef HAVE_ELF64_GETSHDR + Elf64_Shdr *shdr64 = 0; +#endif + Elf_Scn *scn = 0; + + + scn = elf_getscn(obj->elf, section_index); + if (scn == NULL) { + *error = DW_DLE_MDE; + return DW_DLV_ERROR; + } + if (obj->is_64bit) { +#ifdef HAVE_ELF64_GETSHDR + shdr64 = elf64_getshdr(scn); + if (shdr64 == NULL) { + *error = DW_DLE_ELF_GETSHDR_ERROR; + return DW_DLV_ERROR; + } + + ret_scn->size = shdr64->sh_size; + ret_scn->addr = shdr64->sh_addr; + ret_scn->link = shdr64->sh_link; + + ret_scn->name = elf_strptr(obj->elf, obj->ehdr64->e_shstrndx, + shdr64->sh_name); + if(ret_scn->name == NULL) { + *error = DW_DLE_ELF_STRPTR_ERROR; + return DW_DLV_ERROR; + } + return DW_DLV_OK; +#else + *error = DW_DLE_MISSING_ELF64_SUPPORT; + return DW_DLV_ERROR; +#endif /* HAVE_ELF64_GETSHDR */ + } + if ((shdr32 = elf32_getshdr(scn)) == NULL) { + *error = DW_DLE_ELF_GETSHDR_ERROR; + return DW_DLV_ERROR; + } + + ret_scn->size = shdr32->sh_size; + ret_scn->addr = shdr32->sh_addr; + ret_scn->link = shdr32->sh_link; + + ret_scn->name = elf_strptr(obj->elf, obj->ehdr32->e_shstrndx, + shdr32->sh_name); + if (ret_scn->name == NULL) { + *error = DW_DLE_ELF_STRPTR_ERROR; + return DW_DLV_ERROR; + } + return DW_DLV_OK; +} + +/* + dwarf_elf_object_access_get_length_size + */ +static +Dwarf_Small +dwarf_elf_object_access_get_length_size(void* obj_in) +{ + dwarf_elf_object_access_internals_t*obj = + (dwarf_elf_object_access_internals_t*)obj_in; + return obj->length_size; +} + +/* + dwarf_elf_object_access_get_pointer_size + */ +static +Dwarf_Small +dwarf_elf_object_access_get_pointer_size(void* obj_in) +{ + dwarf_elf_object_access_internals_t*obj = + (dwarf_elf_object_access_internals_t*)obj_in; + return obj->pointer_size; +} + +#define MATCH_REL_SEC(i_,s_,r_) \ +if(i_ == s_.dss_index) { \ + *r_ = &s_; \ + return DW_DLV_OK; \ +} + +static int +find_section_to_relocate(Dwarf_Debug dbg,Dwarf_Half section_index, + struct Dwarf_Section_s **relocatablesec, int *error) +{ + MATCH_REL_SEC(section_index,dbg->de_debug_info,relocatablesec); + MATCH_REL_SEC(section_index,dbg->de_debug_abbrev,relocatablesec); + MATCH_REL_SEC(section_index,dbg->de_debug_line,relocatablesec); + MATCH_REL_SEC(section_index,dbg->de_debug_loc,relocatablesec); + MATCH_REL_SEC(section_index,dbg->de_debug_aranges,relocatablesec); + MATCH_REL_SEC(section_index,dbg->de_debug_macinfo,relocatablesec); + MATCH_REL_SEC(section_index,dbg->de_debug_pubnames,relocatablesec); + MATCH_REL_SEC(section_index,dbg->de_debug_ranges,relocatablesec); + MATCH_REL_SEC(section_index,dbg->de_debug_frame,relocatablesec); + MATCH_REL_SEC(section_index,dbg->de_debug_frame_eh_gnu,relocatablesec); + MATCH_REL_SEC(section_index,dbg->de_debug_pubtypes,relocatablesec); + MATCH_REL_SEC(section_index,dbg->de_debug_funcnames,relocatablesec); + MATCH_REL_SEC(section_index,dbg->de_debug_typenames,relocatablesec); + MATCH_REL_SEC(section_index,dbg->de_debug_varnames,relocatablesec); + MATCH_REL_SEC(section_index,dbg->de_debug_weaknames,relocatablesec); + /* dbg-> de_debug_str,syms); */ + /* de_elf_symtab,syms); */ + /* de_elf_strtab,syms); */ + *error = DW_DLE_RELOC_SECTION_MISMATCH; + return DW_DLV_ERROR; + +} +#undef MATCH_REL_SEC + +static void +get_rela_elf32(Dwarf_Small *data, unsigned int i, + int endianness, + int machine, struct Dwarf_Elf_Rela *relap) +{ + Elf32_Rela *relp = (Elf32_Rela*)(data + (i * sizeof(Elf32_Rela))); + relap->r_offset = relp->r_offset; + /* + relap->r_info = relp->r_info; + */ + relap->r_type = ELF32_R_TYPE(relp->r_info); + relap->r_symidx = ELF32_R_SYM(relp->r_info); + relap->r_addend = relp->r_addend; +} + +static void +get_rela_elf64(Dwarf_Small *data, unsigned int i, + int endianness, + int machine,struct Dwarf_Elf_Rela *relap) +{ +#ifdef HAVE_ELF64_RELA + Elf64_Rela * relp = (Elf64_Rela*)(data + (i * sizeof(Elf64_Rela))); + relap->r_offset = relp->r_offset; + /* + relap->r_info = relp->r_info; + */ + if(machine == EM_MIPS && endianness == DW_OBJECT_LSB ) { + /* This is really wierd. Treat this very specially. + The Elf64 LE MIPS object used for + testing (that has rela) wants the + values as sym ssym type3 type2 type, treating + each value as independent value. But libelf xlate + treats it as something else so we fudge here. + It is unclear + how to precisely characterize where these relocations + were used. + SGI MIPS on IRIX never used .rela relocations. + The BE 64bit elf MIPS test object with rela uses traditional + elf relocation layouts, not this special case. */ +#define ELF64MIPS_REL_SYM(i) ((i) & 0xffffffff) +#define ELF64MIPS_REL_TYPE(i) ((i >> 56) &0xff) + /* We ignore the special TYPE2 and TYPE3, they should be + value R_MIPS_NONE in rela. */ + relap->r_type = ELF64MIPS_REL_TYPE(relp->r_info); + relap->r_symidx = ELF64MIPS_REL_SYM(relp->r_info); +#undef MIPS64SYM +#undef MIPS64TYPE + } else + { + relap->r_type = ELF64_R_TYPE(relp->r_info); + relap->r_symidx = ELF64_R_SYM(relp->r_info); + } + relap->r_addend = relp->r_addend; +#endif +} + +static void +get_relocations_array(Dwarf_Bool is_64bit, + int endianness, + int machine, + Dwarf_Small *data, + unsigned int num_relocations, + struct Dwarf_Elf_Rela *relap) +{ + unsigned int i = 0; + void (*get_relocations)(Dwarf_Small *data, unsigned int i, + int endianness, + int machine, + struct Dwarf_Elf_Rela *relap); + + /* Handle 32/64 bit issue + */ + if (is_64bit) { + get_relocations = get_rela_elf64; + } else { + get_relocations = get_rela_elf32; + } + + for (i=0; i < num_relocations; i++) { + get_relocations(data, i,endianness,machine, &(relap[i])); + } + +} + +static int +get_relocation_entries(Dwarf_Bool is_64bit, + int endianness, + int machine, + Dwarf_Small *relocation_section, + Dwarf_Unsigned relocation_section_size, + struct Dwarf_Elf_Rela **relas, + unsigned int *nrelas, + int *error) +{ + unsigned int relocation_size = 0; + + if (is_64bit) { +#ifdef HAVE_ELF64_RELA + relocation_size = sizeof(Elf64_Rela); +#else + *error = DW_DLE_MISSING_ELF64_SUPPORT; + return DW_DLV_ERROR; +#endif + } else { + relocation_size = sizeof(Elf32_Rela); + } + + if (relocation_section == NULL) { + *error = DW_DLE_RELOC_SECTION_PTR_NULL; + return(DW_DLV_ERROR); + } + + if ((relocation_section_size != 0)) { + size_t bytescount = 0; + if(relocation_section_size%relocation_size) { + *error = DW_DLE_RELOC_SECTION_LENGTH_ODD; + return DW_DLV_ERROR; + } + *nrelas = relocation_section_size/relocation_size; + bytescount = (*nrelas) * sizeof(struct Dwarf_Elf_Rela); + *relas = malloc(bytescount); + if (!*relas) { + *error = DW_DLE_MAF; + return(DW_DLV_ERROR); + } + memset(*relas,0,bytescount); + get_relocations_array(is_64bit,endianness,machine, relocation_section, + *nrelas, *relas); + } + return(DW_DLV_OK); +} + +static Dwarf_Bool +is_32bit_abs_reloc(unsigned int type, Dwarf_Half machine) +{ + Dwarf_Bool r = 0; + switch (machine) { +#if defined(EM_MIPS) && defined (R_MIPS_32) + case EM_MIPS: + r = (type == R_MIPS_32); + break; +#endif +#if defined(EM_SPARC32PLUS) && defined (R_SPARC_UA32) + case EM_SPARC32PLUS: + r = (type == R_SPARC_UA32); + break; +#endif +#if defined(EM_SPARCV9) && defined (R_SPARC_UA32) + case EM_SPARCV9: + r = (type == R_SPARC_UA32); + break; +#endif +#if defined(EM_SPARC) && defined (R_SPARC_UA32) + case EM_SPARC: + r = (type == R_SPARC_UA32); + break; +#endif +#if defined(EM_386) && defined (R_386_32) + case EM_386: + r = (type == R_386_32); + break; +#endif +#if defined(EM_IA_64) && defined (R_IA64_SECREL32LSB) + case EM_IA_64: + r = (type == R_IA64_SECREL32LSB); + break; +#endif +#if defined(EM_PPC64) && defined (R_PPC64_ADDR32) + case EM_PPC64: + r = (type == R_PPC64_ADDR32); + break; +#endif +#if defined(EM_PPC) && defined (R_PPC_ADDR32) + case EM_PPC: + r = (type == R_PPC_ADDR32); + break; +#endif +#if defined(EM_S390) && defined (R_390_32) + case EM_S390: + r = (type == R_390_32); + break; +#endif +#if defined(EM_X86_64) && defined (R_X86_64_32) + case EM_X86_64: + r = (type == R_X86_64_32); + break; +#endif + } + return r; +} + +static Dwarf_Bool +is_64bit_abs_reloc(unsigned int type, Dwarf_Half machine) +{ + Dwarf_Bool r = 0; + switch (machine) { +#if defined(EM_MIPS) && defined (R_MIPS_64) + case EM_MIPS: + r = (type == R_MIPS_64); + break; +#endif +#if defined(EM_SPARC32PLUS) && defined (R_SPARC_UA64) + case EM_SPARC32PLUS: + r = (type == R_SPARC_UA64); + break; +#endif +#if defined(EM_SPARCV9) && defined (R_SPARC_UA64) + case EM_SPARCV9: + r = (type == R_SPARC_UA64); + break; +#endif +#if defined(EM_SPARC) && defined (R_SPARC_UA64) + case EM_SPARC: + r = (type == R_SPARC_UA64); + break; +#endif +#if defined(EM_IA_64) && defined (R_IA64_SECREL32LSB) + case EM_IA_64: + r = (type == R_IA64_DIR64LSB); + break; +#endif +#if defined(EM_PPC64) && defined (R_PPC64_ADDR64) + case EM_PPC64: + r = (type == R_PPC64_ADDR64); + break; +#endif +#if defined(EM_S390) && defined (R_390_64) + case EM_S390: + r = (type == R_390_64); + break; +#endif +#if defined(EM_X86_64) && defined (R_X86_64_64) + case EM_X86_64: + r = (type == R_X86_64_64); + break; +#endif + } + return r; +} + + +static void +update_entry(Dwarf_Debug dbg, + Dwarf_Bool is_64bit, Dwarf_Endianness endianess, + Dwarf_Half machine, struct Dwarf_Elf_Rela *rela, + Dwarf_Small *target_section, Dwarf_Small *section_data) +{ + unsigned int type = 0; + unsigned int sym_idx = 0; +#ifdef HAVE_ELF64_SYM + Elf64_Sym sym_buf; + Elf64_Sym *sym = 0; +#else + Elf32_Sym sym_buf; + Elf32_Sym *sym = 0; +#endif + Elf32_Sym *sym32 = 0; + Dwarf_ufixed64 offset = 0; + Dwarf_sfixed64 addend = 0; + Dwarf_Unsigned reloc_size = 0; + + + /* Dwarf_Elf_Rela dereferencing */ + offset = rela->r_offset; + addend = rela->r_addend; + type = rela->r_type; + sym_idx = rela->r_symidx; + + if (is_64bit) { +#ifdef HAVE_ELF64_SYM + sym = &((Elf64_Sym*)section_data)[sym_idx]; +#endif + } else { + sym32 = &((Elf32_Sym*)section_data)[sym_idx]; + + /* Convert Elf32_Sym struct to Elf64_Sym struct. We point at + * an Elf64_Sym local variable (sym_buf) to allow us to use the + * same pointer (sym) for both 32-bit and 64-bit instances. + */ + sym = &sym_buf; + sym->st_name = sym32->st_name; + sym->st_info = sym32->st_info; + sym->st_other = sym32->st_other; + sym->st_shndx = sym32->st_shndx; + sym->st_value = sym32->st_value; + sym->st_size = sym32->st_size; + } + + /* Determine relocation size */ + if (is_32bit_abs_reloc(type, machine)) { + reloc_size = 4; + } else if (is_64bit_abs_reloc(type, machine)) { + reloc_size = 8; + } else { + return; + } + + + { + /* Assuming we do not need to do a READ_UNALIGNED here + at target_section + offset and add its value to + outval. Some ABIs say no read (for example MIPS), + but if some do then which ones? */ + Dwarf_Unsigned outval = sym->st_value + addend; + WRITE_UNALIGNED(dbg,target_section + offset, + &outval,sizeof(outval),reloc_size); + } +} + + + +static int +apply_rela_entries(Dwarf_Debug dbg, + Dwarf_Bool is_64bit, + Dwarf_Endianness endianess, + Dwarf_Half machine, + Dwarf_Small *target_section, + Dwarf_Small *symtab_section, + struct Dwarf_Elf_Rela *relas, unsigned int nrelas, + int *error) +{ + if ((target_section != NULL) && (relas != NULL)) { + unsigned int i; + for (i = 0; i < nrelas; i++) { + update_entry(dbg, is_64bit, + endianess, + machine, + &(relas)[i], + target_section, + symtab_section); + } + } + return DW_DLV_OK; +} + + +static int +loop_through_relocations( + Dwarf_Debug dbg, + dwarf_elf_object_access_internals_t* obj, + struct Dwarf_Section_s *relocatablesec, + int *error) +{ + Dwarf_Small *target_section = 0; + Dwarf_Small *symtab_section = obj->symtab->dss_data; + Dwarf_Small *relocation_section = relocatablesec->dss_reloc_data; + Dwarf_Unsigned relocation_section_size = + relocatablesec->dss_reloc_size; + int ret = DW_DLV_ERROR; + struct Dwarf_Elf_Rela *relas = 0; + unsigned int nrelas = 0; + Dwarf_Small *mspace = 0; + + ret = get_relocation_entries(obj->is_64bit, + obj->endianness, + obj->machine, + relocation_section, + relocation_section_size, + &relas, &nrelas, error); + if(ret != DW_DLV_OK) { + free(relas); + return ret; + } + + /* Some systems read Elf in read-only memory via mmap or the like. + So the only safe thing is to copy the current data into + malloc space and refer to the malloc space instead of the + space returned by the elf library */ + mspace = malloc(relocatablesec->dss_size); + if(!mspace) { + *error = DW_DLE_RELOC_SECTION_MALLOC_FAIL; + return DW_DLV_ERROR; + } + memcpy(mspace,relocatablesec->dss_data,relocatablesec->dss_size); + relocatablesec->dss_data = mspace; + target_section = relocatablesec->dss_data; + relocatablesec->dss_data_was_malloc = 1; + + ret = apply_rela_entries( + dbg, + obj->is_64bit, + obj->endianness, obj->machine, + target_section, + symtab_section, + relas, nrelas, error); + + free(relas); + + return ret; +} + +/* + Find the section data in dbg and find all the relevant + sections. Then do relocations. +*/ +static int +dwarf_elf_object_relocate_a_section(void* obj_in, + Dwarf_Half section_index, + Dwarf_Debug dbg, + int* error) +{ + int res = DW_DLV_ERROR; + dwarf_elf_object_access_internals_t*obj = 0; + struct Dwarf_Section_s * relocatablesec = 0; + if (section_index == 0) { + return DW_DLV_NO_ENTRY; + } + obj = (dwarf_elf_object_access_internals_t*)obj_in; + + /* The section to relocate must already be loaded into memory. */ + res = find_section_to_relocate(dbg, section_index,&relocatablesec,error); + if(res != DW_DLV_OK) { + return res; + } + + /* Sun and possibly others do not always set sh_link in .debug_* sections. + So we cannot do full consistency checks. */ + if(relocatablesec->dss_reloc_index == 0 ) { + /* Something is wrong. */ + *error = DW_DLE_RELOC_SECTION_MISSING_INDEX; + return DW_DLV_ERROR; + } + /* Now load the relocations themselves. */ + res = dwarf_elf_object_access_load_section(obj_in, + relocatablesec->dss_reloc_index, + &relocatablesec->dss_reloc_data, error); + if(res != DW_DLV_OK) { + return res; + } + + /* Now get the symtab. */ + if (!obj->symtab) { + obj->symtab = &dbg->de_elf_symtab; + obj->strtab = &dbg->de_elf_strtab; + } + if( obj->symtab->dss_index != relocatablesec->dss_reloc_link) { + /* Something is wrong. */ + *error = DW_DLE_RELOC_MISMATCH_RELOC_INDEX; + return DW_DLV_ERROR; + } + if( obj->strtab->dss_index != obj->symtab->dss_link) { + /* Something is wrong. */ + *error = DW_DLE_RELOC_MISMATCH_STRTAB_INDEX; + return DW_DLV_ERROR; + } + if(!obj->symtab->dss_data) { + /* Now load the symtab */ + res = dwarf_elf_object_access_load_section(obj_in, + obj->symtab->dss_index, + &obj->symtab->dss_data, error); + if(res != DW_DLV_OK) { + return res; + } + } + if(! obj->strtab->dss_data) { + /* Now load the strtab */ + res = dwarf_elf_object_access_load_section(obj_in, + obj->strtab->dss_index, + &obj->strtab->dss_data,error); + if(res != DW_DLV_OK){ + return res; + } + } + + /* We have all the data we need in memory. */ + res = loop_through_relocations(dbg,obj,relocatablesec,error); + + return res; +} + +/* + dwarf_elf_object_access_load_section + */ +static int +dwarf_elf_object_access_load_section(void* obj_in, + Dwarf_Half section_index, + Dwarf_Small** section_data, + int* error) +{ + dwarf_elf_object_access_internals_t*obj = + (dwarf_elf_object_access_internals_t*)obj_in; + if (section_index == 0) { + return DW_DLV_NO_ENTRY; + } + + { + Elf_Scn *scn = 0; + Elf_Data *data = 0; + + scn = elf_getscn(obj->elf, section_index); + if (scn == NULL) { + *error = DW_DLE_MDE; + return DW_DLV_ERROR; + } + + /* + When using libelf as a producer, section data may be stored + in multiple buffers. In libdwarf however, we only use libelf + as a consumer (there is a dwarf producer API, but it doesn't + use libelf). Because of this, this single call to elf_getdata + will retrieve the entire section in a single contiguous + buffer. */ + data = elf_getdata(scn, NULL); + if (data == NULL) { + *error = DW_DLE_MDE; + return DW_DLV_ERROR; + } + *section_data = data->d_buf; + } + return DW_DLV_OK; +} + + +/* dwarf_elf_access method table. */ +static const struct Dwarf_Obj_Access_Methods_s dwarf_elf_object_access_methods = +{ + dwarf_elf_object_access_get_section_info, + dwarf_elf_object_access_get_byte_order, + dwarf_elf_object_access_get_length_size, + dwarf_elf_object_access_get_pointer_size, + dwarf_elf_object_access_get_section_count, + dwarf_elf_object_access_load_section, + dwarf_elf_object_relocate_a_section +}; + + +/* + Interface for the ELF object file implementation. + */ +int +dwarf_elf_object_access_init(dwarf_elf_handle elf, + int libdwarf_owns_elf, + Dwarf_Obj_Access_Interface** ret_obj, + int *err) +{ + int res = 0; + dwarf_elf_object_access_internals_t *internals = 0; + Dwarf_Obj_Access_Interface *intfc = 0; + + internals = malloc(sizeof(dwarf_elf_object_access_internals_t)); + if(!internals) { + /* Impossible case, we hope. Give up. */ + return DW_DLV_ERROR; + } + memset(internals,0,sizeof(*internals)); + res = dwarf_elf_object_access_internals_init(internals, elf, err); + if(res != DW_DLV_OK){ + free(internals); + return DW_DLV_ERROR; + } + internals->libdwarf_owns_elf = libdwarf_owns_elf; + + intfc = malloc(sizeof(Dwarf_Obj_Access_Interface)); + if(!intfc) { + /* Impossible case, we hope. Give up. */ + free(internals); + return DW_DLV_ERROR; + } + /* Initialize the interface struct */ + intfc->object = internals; + intfc->methods = &dwarf_elf_object_access_methods; + + *ret_obj = intfc; + return DW_DLV_OK; +} + + + +/* + Clean up the Dwarf_Obj_Access_Interface returned by elf_access_init. + */ +void +dwarf_elf_object_access_finish(Dwarf_Obj_Access_Interface* obj) +{ + if(!obj) { + return; + } + if(obj->object) { + dwarf_elf_object_access_internals_t *internals = + (dwarf_elf_object_access_internals_t *)obj->object; + if(internals->libdwarf_owns_elf){ + elf_end(internals->elf); + } + } + free(obj->object); + free(obj); +} + +/* + This function returns the Elf * pointer + associated with a Dwarf_Debug. + + This function only makes sense if ELF is implied. + */ +int +dwarf_get_elf(Dwarf_Debug dbg, dwarf_elf_handle * elf, + Dwarf_Error * error) +{ + struct Dwarf_Obj_Access_Interface_s * obj = 0; + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + + obj = dbg->de_obj_file; + if(obj) { + dwarf_elf_object_access_internals_t *internals = + (dwarf_elf_object_access_internals_t*)obj->object; + if(internals->elf == NULL) { + _dwarf_error(dbg, error, DW_DLE_FNO); + return (DW_DLV_ERROR); + } + *elf = internals->elf; + return DW_DLV_OK; + + } + _dwarf_error(dbg, error, DW_DLE_FNO); + return DW_DLV_ERROR; +} + + diff --git a/usr/src/lib/libdwarf/common/dwarf_elf_access.h b/usr/src/lib/libdwarf/common/dwarf_elf_access.h new file mode 100644 index 0000000000..fd52c17938 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_elf_access.h @@ -0,0 +1,55 @@ +#ifndef _DWARF_ELF_PORT_H +#define _DWARF_ELF_PORT_H +/* + + Copyright (C) 2008-2010 David Anderson. All rights reserved. + Portions Copyright 2008-2010 Arxan Technologies, Inc. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +/* ELF (usually libelf) object access for the generic object file interface */ + +int +dwarf_elf_object_access_init(dwarf_elf_handle elf , + int libdwarf_owns_elf, + Dwarf_Obj_Access_Interface** ret_obj, + int *err ); + +void +dwarf_elf_object_access_finish(Dwarf_Obj_Access_Interface* obj ); + +/* End ELF object access for the generic object file interface */ + + +#endif diff --git a/usr/src/lib/libdwarf/common/dwarf_error.c b/usr/src/lib/libdwarf/common/dwarf_error.c new file mode 100644 index 0000000000..7327529820 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_error.c @@ -0,0 +1,410 @@ +/* + + Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2008-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "dwarf_incl.h" +#ifdef HAVE_ELF_H +#include +#endif + +#include +#include +#include +#include + +/* Array to hold string representation of errors. Any time a + define is added to the list in libdwarf.h, a string should be + added to this Array +*/ + +const char *_dwarf_errmsgs[] = { + + "No error (0)\n", + "DW_DLE_VMM 1 dwarf format/library version mismatch", + "DW_DLE_MAP 2 memory map failure", + "DW_DLE_LEE 3 libelf error", + "DW_DLE_NDS 4 no debug section", + "DW_DLE_NLS 5 no line section ", + "DW_DLE_ID 6 invalid descriptor for query ", + "DW_DLE_IOF 7 I/O failure ", + "DW_DLE_MAF 8 memory allocation failure ", + "DW_DLE_IA 9 invalid argument ", + "DW_DLE_MDE 10 mangled debugging entry ", + "DW_DLE_MLE 11 mangled line number entry ", + "DW_DLE_FNO 12 file not open ", + "DW_DLE_FNR 13 file not a regular file ", + "DW_DLE_FWA 14 file open with wrong access ", + "DW_DLE_NOB 15 not an object file ", + "DW_DLE_MOF 16 mangled object file header ", + "DW_DLE_EOLL 17 end of location list entries ", + "DW_DLE_NOLL 18 no location list section ", + "DW_DLE_BADOFF 19 Invalid offset ", + "DW_DLE_EOS 20 end of section ", + "DW_DLE_ATRUNC 21 abbreviations section appears truncated", + "DW_DLE_BADBITC 22 Address size passed to dwarf bad", + + "DW_DLE_DBG_ALLOC 23 Unable to malloc a Dwarf_Debug structure", + "DW_DLE_FSTAT_ERROR 24 The file fd passed to dwarf_init " + "cannot be fstat()ed", + "DW_DLE_FSTAT_MODE_ERROR 25 The file mode bits do not " + "indicate that the file being opened via " + "dwarf_init() is a normal file", + "DW_DLE_INIT_ACCESS_WRONG 26 A call to dwarf_init had an " + "access of other than DW_DLC_READ", + "DW_DLE_ELF_BEGIN_ERROR 27 a call to " + "elf_begin(... ELF_C_READ_MMAP... ) failed", + "DW_DLE_ELF_GETEHDR_ERROR 28 a call to " + "elf32_getehdr() or elf64_getehdr() failed", + "DW_DLE_ELF_GETSHDR_ERROR 29 a call to " + "elf32_getshdr() or elf64_getshdr() failed", + "DW_DLE_ELF_STRPTR_ERROR 30 a call to " + "elf_strptr() failed trying to get a section name", + "DW_DLE_DEBUG_INFO_DUPLICATE 31 Only one .debug_info " + "section is allowed", + "DW_DLE_DEBUG_INFO_NULL 32 .debug_info section present but " + "elf_getdata() failed or section is zero-length", + "DW_DLE_DEBUG_ABBREV_DUPLICATE 33 Only one .debug_abbrev " + "section is allowed", + "DW_DLE_DEBUG_ABBREV_NULL 34 .debug_abbrev section present but " + "elf_getdata() failed or section is zero-length", + "DW_DLE_DEBUG_ARANGES_DUPLICATE 35 Only one .debug_aranges " + "section is allowed", + "DW_DLE_DEBUG_ARANGES_NULL 36 .debug_aranges section present but " + "elf_getdata() failed or section is zero-length", + "DW_DLE_DEBUG_LINE_DUPLICATE 37 Only one .debug_line " + "section is allowed", + "DW_DLE_DEBUG_LINE_NULL (38) .debug_line section present but " + "elf_getdata() failed or section is zero-length", + "DW_DLE_DEBUG_LOC_DUPLICATE (39) Only one .debug_loc " + "section is allowed", + "DW_DLE_DEBUG_LOC_NULL (40) .debug_loc section present but " + "elf_getdata() failed or section is zero-length", + "DW_DLE_DEBUG_MACINFO_DUPLICATE (41) Only one .debug_macinfo " + "section is allowed", + "DW_DLE_DEBUG_MACINFO_NULL (42) .debug_macinfo section present but " + "elf_getdata() failed or section is zero-length", + "DW_DLE_DEBUG_PUBNAMES_DUPLICATE (43) Only one .debug_pubnames " + "section is allowed", + "DW_DLE_DEBUG_PUBNAMES_NULL (44) .debug_pubnames section present but " + "elf_getdata() failed or section is zero-length", + "DW_DLE_DEBUG_STR_DUPLICATE (45) Only one .debug_str " + "section is allowed", + "DW_DLE_DEBUG_STR_NULL (46) .debug_str section present but " + "elf_getdata() failed or section is zero-length", + "DW_DLE_CU_LENGTH_ERROR (47)", + "DW_DLE_VERSION_STAMP_ERROR (48)", + "DW_DLE_ABBREV_OFFSET_ERROR (49)", + "DW_DLE_ADDRESS_SIZE_ERROR (50)", + "DW_DLE_DEBUG_INFO_PTR_NULL (51)", + "DW_DLE_DIE_NULL (52)", + "DW_DLE_STRING_OFFSET_BAD (53)", + "DW_DLE_DEBUG_LINE_LENGTH_BAD (54)", + "DW_DLE_LINE_PROLOG_LENGTH_BAD (55)", + "DW_DLE_LINE_NUM_OPERANDS_BAD", + "DW_DLE_LINE_SET_ADDR_ERROR", + "DW_DLE_LINE_EXT_OPCODE_BAD", + "DW_DLE_DWARF_LINE_NULL", + "DW_DLE_INCL_DIR_NUM_BAD", + "DW_DLE_LINE_FILE_NUM_BAD", + "DW_DLE_ALLOC_FAIL", + "DW_DLE_NO_CALLBACK_FUNC", + "DW_DLE_SECT_ALLOC", + "DW_DLE_FILE_ENTRY_ALLOC", + "DW_DLE_LINE_ALLOC", + "DW_DLE_FPGM_ALLOC", + "DW_DLE_INCDIR_ALLOC", + "DW_DLE_STRING_ALLOC", + "DW_DLE_CHUNK_ALLOC", + "DW_DLE_BYTEOFF_ERR", + "DW_DLE_CIE_ALLOC", + "DW_DLE_FDE_ALLOC", + "DW_DLE_REGNO_OVFL", + "DW_DLE_CIE_OFFS_ALLOC", + "DW_DLE_WRONG_ADDRESS", + "DW_DLE_EXTRA_NEIGHBORS", + "DW_DLE_WRONG_TAG", + "DW_DLE_DIE_ALLOC", + "DW_DLE_PARENT_EXISTS", + "DW_DLE_DBG_NULL", + "DW_DLE_DEBUGLINE_ERROR", + "DW_DLE_DEBUGFRAME_ERROR", + "DW_DLE_DEBUGINFO_ERROR", + "DW_DLE_ATTR_ALLOC", + "DW_DLE_ABBREV_ALLOC", + "DW_DLE_OFFSET_UFLW", + "DW_DLE_ELF_SECT_ERR", + "DW_DLE_DEBUG_FRAME_LENGTH_BAD", + "DW_DLE_FRAME_VERSION_BAD", + "DW_DLE_CIE_RET_ADDR_REG_ERROR", + "DW_DLE_FDE_NULL", + "DW_DLE_FDE_DBG_NULL", + "DW_DLE_CIE_NULL", + "DW_DLE_CIE_DBG_NULL", + "DW_DLE_FRAME_TABLE_COL_BAD", + "DW_DLE_PC_NOT_IN_FDE_RANGE", + "DW_DLE_CIE_INSTR_EXEC_ERROR", + "DW_DLE_FRAME_INSTR_EXEC_ERROR", + "DW_DLE_FDE_PTR_NULL", + "DW_DLE_RET_OP_LIST_NULL", + "DW_DLE_LINE_CONTEXT_NULL", + "DW_DLE_DBG_NO_CU_CONTEXT", + "DW_DLE_DIE_NO_CU_CONTEXT", + "DW_DLE_FIRST_DIE_NOT_CU", + "DW_DLE_NEXT_DIE_PTR_NULL", + "DW_DLE_DEBUG_FRAME_DUPLICATE Only one .debug_frame " + "section is allowed", + "DW_DLE_DEBUG_FRAME_NULL .debug_frame section present but " + "elf_getdata() failed or section is zero-length", + "DW_DLE_ABBREV_DECODE_ERROR", + "DW_DLE_DWARF_ABBREV_NULL", + "DW_DLE_ATTR_NULL", + "DW_DLE_DIE_BAD", + "DW_DLE_DIE_ABBREV_BAD", + "DW_DLE_ATTR_FORM_BAD", + "DW_DLE_ATTR_NO_CU_CONTEXT", + "DW_DLE_ATTR_FORM_SIZE_BAD", + "DW_DLE_ATTR_DBG_NULL", + "DW_DLE_BAD_REF_FORM", + "DW_DLE_ATTR_FORM_OFFSET_BAD", + "DW_DLE_LINE_OFFSET_BAD", + "DW_DLE_DEBUG_STR_OFFSET_BAD", + "DW_DLE_STRING_PTR_NULL", + "DW_DLE_PUBNAMES_VERSION_ERROR", + "DW_DLE_PUBNAMES_LENGTH_BAD", + "DW_DLE_GLOBAL_NULL", + "DW_DLE_GLOBAL_CONTEXT_NULL", + "DW_DLE_DIR_INDEX_BAD", + "DW_DLE_LOC_EXPR_BAD", + "DW_DLE_DIE_LOC_EXPR_BAD", + "DW_DLE_ADDR_ALLOC", + "DW_DLE_OFFSET_BAD", + "DW_DLE_MAKE_CU_CONTEXT_FAIL", + "DW_DLE_REL_ALLOC", + "DW_DLE_ARANGE_OFFSET_BAD", + "DW_DLE_SEGMENT_SIZE_BAD", + "DW_DLE_ARANGE_LENGTH_BAD", + "DW_DLE_ARANGE_DECODE_ERROR", + "DW_DLE_ARANGES_NULL", + "DW_DLE_ARANGE_NULL", + "DW_DLE_NO_FILE_NAME", + "DW_DLE_NO_COMP_DIR", + "DW_DLE_CU_ADDRESS_SIZE_BAD", + "DW_DLE_INPUT_ATTR_BAD", + "DW_DLE_EXPR_NULL", + "DW_DLE_BAD_EXPR_OPCODE", + "DW_DLE_EXPR_LENGTH_BAD", + "DW_DLE_MULTIPLE_RELOC_IN_EXPR", + "DW_DLE_ELF_GETIDENT_ERROR", + "DW_DLE_NO_AT_MIPS_FDE", + "DW_DLE_NO_CIE_FOR_FDE", + "DW_DLE_DIE_ABBREV_LIST_NULL", + "DW_DLE_DEBUG_FUNCNAMES_DUPLICATE", + "DW_DLE_DEBUG_FUNCNAMES_NULL .debug_funcnames section present but " + "elf_getdata() failed or section is zero-length", + "DW_DLE_DEBUG_FUNCNAMES_VERSION_ERROR", + "DW_DLE_DEBUG_FUNCNAMES_LENGTH_BAD", + "DW_DLE_FUNC_NULL", + "DW_DLE_FUNC_CONTEXT_NULL", + "DW_DLE_DEBUG_TYPENAMES_DUPLICATE", + "DW_DLE_DEBUG_TYPENAMES_NULL .debug_typenames section present but " + "elf_getdata() failed or section is zero-length", + "DW_DLE_DEBUG_TYPENAMES_VERSION_ERROR", + "DW_DLE_DEBUG_TYPENAMES_LENGTH_BAD", + "DW_DLE_TYPE_NULL", + "DW_DLE_TYPE_CONTEXT_NULL", + "DW_DLE_DEBUG_VARNAMES_DUPLICATE", + "DW_DLE_DEBUG_VARNAMES_NULL .debug_varnames section present but " + "elf_getdata() failed or section is zero-length", + "DW_DLE_DEBUG_VARNAMES_VERSION_ERROR", + "DW_DLE_DEBUG_VARNAMES_LENGTH_BAD", + "DW_DLE_VAR_NULL", + "DW_DLE_VAR_CONTEXT_NULL", + "DW_DLE_DEBUG_WEAKNAMES_DUPLICATE", + "DW_DLE_DEBUG_WEAKNAMES_NULL .debug_weaknames section present but " + "elf_getdata() failed or section is zero-length", + + "DW_DLE_DEBUG_WEAKNAMES_VERSION_ERROR", + "DW_DLE_DEBUG_WEAKNAMES_LENGTH_BAD", + "DW_DLE_WEAK_NULL", + "DW_DLE_WEAK_CONTEXT_NULL (175)", + "DW_DLE_LOCDESC_COUNT_WRONG (176)", + "DW_DLE_MACINFO_STRING_NULL (177)", + "DW_DLE_MACINFO_STRING_EMPTY (178)", + "DW_DLE_MACINFO_INTERNAL_ERROR_SPACE (179)", + "DW_DLE_MACINFO_MALLOC_FAIL (180)", + "DW_DLE_DEBUGMACINFO_ERROR (181)", + "DW_DLE_DEBUG_MACRO_LENGTH_BAD (182)", + "DW_DLE_DEBUG_MACRO_MAX_BAD (183)", + "DW_DLE_DEBUG_MACRO_INTERNAL_ERR (184)", + "DW_DLE_DEBUG_MACRO_MALLOC_SPACE (185)", + "DW_DLE_DEBUG_MACRO_INCONSISTENT (186)", + "DW_DLE_DF_NO_CIE_AUGMENTATION(187)", + "DW_DLE_DF_REG_NUM_TOO_HIGH(188)", + "DW_DLE_DF_MAKE_INSTR_NO_INIT(189)", + "DW_DLE_DF_NEW_LOC_LESS_OLD_LOC(190)", + "DW_DLE_DF_POP_EMPTY_STACK(191)", + "DW_DLE_DF_ALLOC_FAIL(192)", + "DW_DLE_DF_FRAME_DECODING_ERROR(193)", + "DW_DLE_DEBUG_LOC_SECTION_SHORT(194)", + "DW_DLE_FRAME_AUGMENTATION_UNKNOWN(195)", + "DW_DLE_PUBTYPE_CONTEXT(196)", + "DW_DLE_DEBUG_PUBTYPES_LENGTH_BAD(197)", + "DW_DLE_DEBUG_PUBTYPES_VERSION_ERROR(198)", + "DW_DLE_DEBUG_PUBTYPES_DUPLICATE(199)", + "DW_DLE_FRAME_CIE_DECODE_ERROR(200)", + "DW_DLE_FRAME_REGISTER_UNREPRESENTABLE(201)", + "DW_DLE_FRAME_REGISTER_COUNT_MISMATCH(202)", + "DW_DLE_LINK_LOOP(203)", + "DW_DLE_STRP_OFFSET_BAD(204)", + "DW_DLE_DEBUG_RANGES_DUPLICATE(205)", + "DW_DLE_DEBUG_RANGES_OFFSET_BAD(206)", + "DW_DLE_DEBUG_RANGES_MISSING_END(207)", + "DW_DLE_DEBUG_RANGES_OUT_OF_MEM(208)", + "DW_DLE_DEBUG_SYMTAB_ERR(209)", + "DW_DLE_DEBUG_STRTAB_ERR(210)", + "DW_DLE_RELOC_MISMATCH_INDEX(211)", + "DW_DLE_RELOC_MISMATCH_RELOC_INDEX(212)", + "DW_DLE_RELOC_MISMATCH_STRTAB_INDEX(213)", + "DW_DLE_RELOC_SECTION_MISMATCH(214)", + "DW_DLE_RELOC_SECTION_MISSING_INDEX(215)", + "DW_DLE_RELOC_SECTION_LENGTH_ODD(216)", + "DW_DLE_RELOC_SECTION_PTR_NULL(217)", + "DW_DLE_RELOC_SECTION_MALLOC_FAIL(218)", + "DW_DLE_NO_ELF64_SUPPORT(219)", + "DW_DLE_MISSING_ELF64_SUPPORT(220)", + "DW_DLE_ORPHAN_FDE(221)", + "DW_DLE_DUPLICATE_INST_BLOCK(222)", + "DW_DLE_BAD_REF_SIG8_FORM(223)", + "DW_DLE_ATTR_EXPRLOC_FORM_BAD(224)", + "DW_DLE_FORM_SEC_OFFSET_LENGTH_BAD(225)", + "DW_DLE_NOT_REF_FORM(226)", + "DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE(227)" +}; + + + + +/* + This function performs error handling as described in the + libdwarf consumer document section 3. Dbg is the Dwarf_debug + structure being processed. Error is a pointer to the pointer + to the error descriptor that will be returned. Errval is an + error code listed in dwarf_error.h. +*/ +void +_dwarf_error(Dwarf_Debug dbg, Dwarf_Error * error, Dwarf_Sword errval) +{ + Dwarf_Error errptr; + + /* + Allow NULL dbg on entry, since sometimes that can happen and we + want to report the upper-level error, not this one. */ + if (error != NULL) { + + /* + If dbg is NULL, use the alternate error struct. However, + this will overwrite the earlier error. */ + if (dbg != NULL) { + errptr = + (Dwarf_Error) _dwarf_get_alloc(dbg, DW_DLA_ERROR, 1); + if (errptr == NULL) { + fprintf(stderr, + "Could not allocate Dwarf_Error structure, " + "abort() in libdwarf.\n"); + abort(); + } + } else { + /* We have no dbg to work with. dwarf_init failed. We hack + up a special area. */ + errptr = _dwarf_special_no_dbg_error_malloc(); + if (errptr == NULL) { + fprintf(stderr, + "Could not allocate Dwarf_Error structure, " + "abort() in libdwarf..\n"); + abort(); + } + } + + errptr->er_errval = errval; + *error = errptr; + return; + } + + if (dbg != NULL && dbg->de_errhand != NULL) { + errptr = (Dwarf_Error) _dwarf_get_alloc(dbg, DW_DLA_ERROR, 1); + if (errptr == NULL) { + fprintf(stderr, "Could not allocate Dwarf_Error structure," + " abort() in libdwarf.\n"); + abort(); + } + errptr->er_errval = errval; + dbg->de_errhand(errptr, dbg->de_errarg); + return; + } + fprintf(stderr, + "abort() in libdwarf. No error argument, no handler.\n"); + abort(); +} + + +Dwarf_Unsigned +dwarf_errno(Dwarf_Error error) +{ + if (error == NULL) { + return (0); + } + + return (error->er_errval); +} + + +/* +*/ +char * +dwarf_errmsg(Dwarf_Error error) +{ + if (error == NULL) { + return "Dwarf_Error is NULL"; + } + + if (error->er_errval > (sizeof(_dwarf_errmsgs) / sizeof(char *))) { + return "Dwarf_Error value out of range"; + } + + return ((char *) _dwarf_errmsgs[error->er_errval]); +} diff --git a/usr/src/lib/libdwarf/common/dwarf_error.h b/usr/src/lib/libdwarf/common/dwarf_error.h new file mode 100644 index 0000000000..27acf70db0 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_error.h @@ -0,0 +1,43 @@ +/* + + Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +void _dwarf_error(Dwarf_Debug dbg, Dwarf_Error * error, + Dwarf_Sword errval); + +struct Dwarf_Error_s { + Dwarf_Sword er_errval; +}; diff --git a/usr/src/lib/libdwarf/common/dwarf_form.c b/usr/src/lib/libdwarf/common/dwarf_form.c new file mode 100644 index 0000000000..fcdd64230c --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_form.c @@ -0,0 +1,963 @@ +/* + + Copyright (C) 2000,2002,2004,2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2008-2010 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "dwarf_incl.h" +#include "dwarf_die_deliv.h" + +int +dwarf_hasform(Dwarf_Attribute attr, + Dwarf_Half form, + Dwarf_Bool * return_bool, Dwarf_Error * error) +{ + Dwarf_CU_Context cu_context = 0; + + if (attr == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); + return (DW_DLV_ERROR); + } + + cu_context = attr->ar_cu_context; + if (cu_context == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); + return (DW_DLV_ERROR); + } + + if (cu_context->cc_dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); + return (DW_DLV_ERROR); + } + + *return_bool = (attr->ar_attribute_form == form); + return DW_DLV_OK; +} + +/* Not often called, we do not worry about efficiency here. + The dwarf_whatform() call does the sanity checks for us. +*/ +int +dwarf_whatform_direct(Dwarf_Attribute attr, + Dwarf_Half * return_form, Dwarf_Error * error) +{ + int res = dwarf_whatform(attr, return_form, error); + + if (res != DW_DLV_OK) { + return res; + } + + *return_form = attr->ar_attribute_form_direct; + return (DW_DLV_OK); +} +void * +dwarf_uncompress_integer_block( + Dwarf_Debug dbg, + Dwarf_Bool unit_is_signed, + Dwarf_Small unit_length_in_bits, + void* input_block, + Dwarf_Unsigned input_length_in_bytes, + Dwarf_Unsigned* output_length_in_units_ptr, + Dwarf_Error* error +) +{ + Dwarf_Unsigned output_length_in_units = 0; + void * output_block = 0; + int i = 0; + char * ptr = 0; + int remain = 0; + Dwarf_sfixed * array = 0; + + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_DBG_NULL); + return((void *)DW_DLV_BADADDR); + } + + if (unit_is_signed == false || + unit_length_in_bits != 32 || + input_block == NULL || + input_length_in_bytes == 0 || + output_length_in_units_ptr == NULL) { + + _dwarf_error(NULL, error, DW_DLE_BADBITC); + return ((void *) DW_DLV_BADADDR); + } + + /* At this point we assume the format is: signed 32 bit */ + + /* first uncompress everything to find the total size. */ + + output_length_in_units = 0; + remain = input_length_in_bytes; + ptr = input_block; + while (remain > 0) { + Dwarf_Signed num; + Dwarf_Word len; + num = _dwarf_decode_s_leb128((unsigned char *)ptr, &len); + ptr += len; + remain -= len; + output_length_in_units++; + } + + if (remain != 0) { + _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL); + return((void *)DW_DLV_BADADDR); + } + + /* then alloc */ + + output_block = (void *) + _dwarf_get_alloc(dbg, + DW_DLA_STRING, + output_length_in_units * (unit_length_in_bits / 8)); + if (output_block == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return((void*)DW_DLV_BADADDR); + } + + /* then uncompress again and copy into new buffer */ + + array = (Dwarf_sfixed *) output_block; + remain = input_length_in_bytes; + ptr = input_block; + for (i=0; i0; i++) { + Dwarf_Signed num; + Dwarf_Word len; + num = _dwarf_decode_s_leb128((unsigned char *)ptr, &len); + ptr += len; + remain -= len; + array[i] = num; + } + + if (remain != 0) { + dwarf_dealloc(dbg, (unsigned char *)output_block, DW_DLA_STRING); + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return((Dwarf_P_Attribute)DW_DLV_BADADDR); + } + + *output_length_in_units_ptr = output_length_in_units; + return output_block; +} + +void +dwarf_dealloc_uncompressed_block(Dwarf_Debug dbg, void * space) +{ + dwarf_dealloc(dbg, space, DW_DLA_STRING); +} + + +int +dwarf_whatform(Dwarf_Attribute attr, + Dwarf_Half * return_form, Dwarf_Error * error) +{ + Dwarf_CU_Context cu_context = 0; + + if (attr == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); + return (DW_DLV_ERROR); + } + + cu_context = attr->ar_cu_context; + if (cu_context == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); + return (DW_DLV_ERROR); + } + + if (cu_context->cc_dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); + return (DW_DLV_ERROR); + } + + *return_form = attr->ar_attribute_form; + return (DW_DLV_OK); +} + + +/* + This function is analogous to dwarf_whatform. + It returns the attribute in attr instead of + the form. +*/ +int +dwarf_whatattr(Dwarf_Attribute attr, + Dwarf_Half * return_attr, Dwarf_Error * error) +{ + Dwarf_CU_Context cu_context = 0; + + if (attr == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); + return (DW_DLV_ERROR); + } + + cu_context = attr->ar_cu_context; + if (cu_context == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); + return (DW_DLV_ERROR); + } + + if (cu_context->cc_dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); + return (DW_DLV_ERROR); + } + + *return_attr = (attr->ar_attribute); + return DW_DLV_OK; +} + + +/* + A global offset cannot be returned by this interface: + see dwarf_global_formref(). + + DW_FORM_ref_addr is considered an incorrect form + for this call because DW_FORM_ref_addr is a global-offset into + the debug_info section. + + For the same reason DW_FORM_data4/data8 are not returned + from this function. + + For the same reason DW_FORM_sec_offset is not returned + from this function, DW_FORM_sec_offset is a global offset + (to various sections, not a CU relative offset. + + DW_FORM_ref_addr has a value which was documented in + DWARF2 as address-size but which was always an offset + so should have always been offset size (wording + corrected in DWARF3). + + +*/ +int +dwarf_formref(Dwarf_Attribute attr, + Dwarf_Off * ret_offset, Dwarf_Error * error) +{ + Dwarf_Debug dbg = 0; + Dwarf_Unsigned offset = 0; + Dwarf_CU_Context cu_context = 0; + + + if (attr == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); + return (DW_DLV_ERROR); + } + + cu_context = attr->ar_cu_context; + if (cu_context == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); + return (DW_DLV_ERROR); + } + + if (cu_context->cc_dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); + return (DW_DLV_ERROR); + } + dbg = cu_context->cc_dbg; + + switch (attr->ar_attribute_form) { + + case DW_FORM_ref1: + offset = *(Dwarf_Small *) attr->ar_debug_info_ptr; + break; + + case DW_FORM_ref2: + READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, + attr->ar_debug_info_ptr, sizeof(Dwarf_Half)); + break; + + case DW_FORM_ref4: + READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, + attr->ar_debug_info_ptr, sizeof(Dwarf_ufixed)); + break; + + case DW_FORM_ref8: + READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, + attr->ar_debug_info_ptr, sizeof(Dwarf_Unsigned)); + break; + + case DW_FORM_ref_udata: + offset = _dwarf_decode_u_leb128(attr->ar_debug_info_ptr, NULL); + break; + + default: + _dwarf_error(dbg, error, DW_DLE_BAD_REF_FORM); + return (DW_DLV_ERROR); + } + + /* Check that offset is within current cu portion of .debug_info. */ + if (offset >= cu_context->cc_length + + cu_context->cc_length_size + cu_context->cc_extension_size) { + _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_OFFSET_BAD); + return (DW_DLV_ERROR); + } + + *ret_offset = (offset); + return DW_DLV_OK; +} + +/* dwarf_formsig8 returns in the caller-provided 8 byte area + the 8 bytes of a DW_FORM_ref_sig8 (copying the bytes + directly to the caller). Not a string, an 8 byte + MD5 hash. This function is new in DWARF4 libdwarf. +*/ +int dwarf_formsig8(Dwarf_Attribute attr, + Dwarf_Sig8 * returned_sig_bytes, + Dwarf_Error* error) +{ + Dwarf_Debug dbg = 0; + Dwarf_Unsigned field_end_offset = 0; + Dwarf_CU_Context cu_context = 0; + + + if (attr == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); + return (DW_DLV_ERROR); + } + + cu_context = attr->ar_cu_context; + if (cu_context == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); + return (DW_DLV_ERROR); + } + + if (cu_context->cc_dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); + return (DW_DLV_ERROR); + } + dbg = cu_context->cc_dbg; + + if(attr->ar_attribute_form != DW_FORM_ref_sig8 ) { + _dwarf_error(dbg, error, DW_DLE_BAD_REF_SIG8_FORM); + return (DW_DLV_ERROR); + } + + field_end_offset = attr->ar_debug_info_ptr + sizeof(Dwarf_Sig8) - + (dbg->de_debug_info.dss_data + cu_context->cc_debug_info_offset); + /* Check that offset is within current cu portion of .debug_info. */ + if (field_end_offset > cu_context->cc_length + + cu_context->cc_length_size + cu_context->cc_extension_size) { + _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_OFFSET_BAD); + return (DW_DLV_ERROR); + } + + memcpy(returned_sig_bytes, attr->ar_debug_info_ptr, + sizeof(Dwarf_Sig8)); + return DW_DLV_OK; +} + + +/* + Since this returns section-relative debug_info offsets, + this can represent all REFERENCE forms correctly + and allows all applicable forms. + + DW_FORM_ref_addr has a value which was documented in + DWARF2 as address-size but which was always an offset + so should have always been offset size (wording + corrected in DWARF3). + + See the DWARF4 document for the 3 cases fitting + reference forms. The caller must determine which section the + reference 'points' to. The function added in November 2009, + dwarf_get_form_class(), helps in this regard. + +*/ +int +dwarf_global_formref(Dwarf_Attribute attr, + Dwarf_Off * ret_offset, Dwarf_Error * error) +{ + Dwarf_Debug dbg = 0; + Dwarf_Unsigned offset = 0; + Dwarf_Addr ref_addr = 0; + Dwarf_CU_Context cu_context = 0; + Dwarf_Half context_version = 0; + + if (attr == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); + return (DW_DLV_ERROR); + } + + cu_context = attr->ar_cu_context; + if (cu_context == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); + return (DW_DLV_ERROR); + } + context_version = cu_context->cc_version_stamp; + + if (cu_context->cc_dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); + return (DW_DLV_ERROR); + } + dbg = cu_context->cc_dbg; + + switch (attr->ar_attribute_form) { + + case DW_FORM_ref1: + offset = *(Dwarf_Small *) attr->ar_debug_info_ptr; + goto fixoffset; + + case DW_FORM_ref2: + READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, + attr->ar_debug_info_ptr, sizeof(Dwarf_Half)); + goto fixoffset; + + case DW_FORM_ref4: + READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, + attr->ar_debug_info_ptr, sizeof(Dwarf_ufixed)); + goto fixoffset; + + case DW_FORM_ref8: + READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, + attr->ar_debug_info_ptr, sizeof(Dwarf_Unsigned)); + goto fixoffset; + + case DW_FORM_ref_udata: + offset = _dwarf_decode_u_leb128(attr->ar_debug_info_ptr, NULL); + + fixoffset: /* we have a local offset, make it + global */ + + /* check legality of offset */ + if (offset >= cu_context->cc_length + + cu_context->cc_length_size + + cu_context->cc_extension_size) { + _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_OFFSET_BAD); + return (DW_DLV_ERROR); + } + + /* globalize the offset */ + offset += cu_context->cc_debug_info_offset; + break; + /* The DWARF2 document did not make clear that + DW_FORM_data4( and 8) were references with + global offsets to some section. + That was first clearly documented in DWARF3. + In DWARF4 these two forms are no longer references. */ + case DW_FORM_data4: + if(context_version == DW_CU_VERSION4) { + _dwarf_error(dbg, error, DW_DLE_NOT_REF_FORM); + return (DW_DLV_ERROR); + } + READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, + attr->ar_debug_info_ptr, sizeof(Dwarf_ufixed)); + /* The offset is global. */ + break; + case DW_FORM_data8: + if(context_version == DW_CU_VERSION4) { + _dwarf_error(dbg, error, DW_DLE_NOT_REF_FORM); + return (DW_DLV_ERROR); + } + READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, + attr->ar_debug_info_ptr, sizeof(Dwarf_Unsigned)); + /* The offset is global. */ + break; + case DW_FORM_ref_addr: + case DW_FORM_sec_offset: + { + /* DW_FORM_sec_offset first exists in DWARF4.*/ + /* It is up to the caller to know what the offset + of DW_FORM_sec_offset refers to, + the offset is not going to refer to .debug_info! */ + unsigned length_size = cu_context->cc_length_size; + if(length_size == 4) { + READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, + attr->ar_debug_info_ptr, sizeof(Dwarf_ufixed)); + } else if (length_size == 8) { + READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, + attr->ar_debug_info_ptr, sizeof(Dwarf_Unsigned)); + } else { + _dwarf_error(dbg, error, DW_DLE_FORM_SEC_OFFSET_LENGTH_BAD); + return (DW_DLV_ERROR); + } + } + break; + + default: + _dwarf_error(dbg, error, DW_DLE_BAD_REF_FORM); + return (DW_DLV_ERROR); + } + + /* We do not know what section the offset refers to, so + we have no way to check it for correctness. */ + *ret_offset = offset; + return DW_DLV_OK; +} + + +int +dwarf_formaddr(Dwarf_Attribute attr, + Dwarf_Addr * return_addr, Dwarf_Error * error) +{ + Dwarf_Debug dbg = 0; + Dwarf_Addr ret_addr = 0; + Dwarf_CU_Context cu_context = 0; + + if (attr == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); + return (DW_DLV_ERROR); + } + + cu_context = attr->ar_cu_context; + if (cu_context == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); + return (DW_DLV_ERROR); + } + + if (cu_context->cc_dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); + return (DW_DLV_ERROR); + } + dbg = cu_context->cc_dbg; + + if (attr->ar_attribute_form == DW_FORM_addr + /* || attr->ar_attribute_form == DW_FORM_ref_addr Allowance of + DW_FORM_ref_addr was a mistake. The value returned in that + case is NOT an address it is a global debug_info offset (ie, + not CU-relative offset within the CU in debug_info). The + Dwarf document refers to it as an address (misleadingly) in + sec 6.5.4 where it describes the reference form. It is + address-sized so that the linker can easily update it, but + it is a reference inside the debug_info section. No longer + allowed. */ + ) { + + READ_UNALIGNED(dbg, ret_addr, Dwarf_Addr, + attr->ar_debug_info_ptr, + cu_context->cc_address_size); + *return_addr = ret_addr; + return (DW_DLV_OK); + } + + _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD); + return (DW_DLV_ERROR); +} + + +int +dwarf_formflag(Dwarf_Attribute attr, + Dwarf_Bool * ret_bool, Dwarf_Error * error) +{ + Dwarf_CU_Context cu_context = 0; + + if (attr == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); + return (DW_DLV_ERROR); + } + + cu_context = attr->ar_cu_context; + if (cu_context == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); + return (DW_DLV_ERROR); + } + + if (cu_context->cc_dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); + return (DW_DLV_ERROR); + } + if (attr->ar_attribute_form == DW_FORM_flag_present) { + /* Implicit means we don't read any data at all. Just + the existence of the Form does it. DWARF4. */ + *ret_bool = 1; + return (DW_DLV_OK); + } + + if (attr->ar_attribute_form == DW_FORM_flag) { + *ret_bool = (*(Dwarf_Small *) attr->ar_debug_info_ptr != 0); + return (DW_DLV_OK); + } + _dwarf_error(cu_context->cc_dbg, error, DW_DLE_ATTR_FORM_BAD); + return (DW_DLV_ERROR); +} + + +int +dwarf_formudata(Dwarf_Attribute attr, + Dwarf_Unsigned * return_uval, Dwarf_Error * error) +{ + Dwarf_Unsigned ret_value = 0; + Dwarf_Debug dbg = 0; + Dwarf_CU_Context cu_context = 0; + + if (attr == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); + return (DW_DLV_ERROR); + } + + + cu_context = attr->ar_cu_context; + if (cu_context == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); + return (DW_DLV_ERROR); + } + + dbg = cu_context->cc_dbg; + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); + return (DW_DLV_ERROR); + } + + switch (attr->ar_attribute_form) { + + case DW_FORM_data1: + READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, + attr->ar_debug_info_ptr, sizeof(Dwarf_Small)); + *return_uval = ret_value; + return DW_DLV_OK; + + /* READ_UNALIGNED does the right thing as it reads + the right number bits and generates host order. + So we can just assign to *return_uval. */ + case DW_FORM_data2:{ + READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, + attr->ar_debug_info_ptr, sizeof(Dwarf_Half)); + *return_uval = ret_value; + return DW_DLV_OK; + } + + case DW_FORM_data4:{ + READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, + attr->ar_debug_info_ptr, + sizeof(Dwarf_ufixed)); + *return_uval = ret_value; + return DW_DLV_OK; + } + + case DW_FORM_data8:{ + READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, + attr->ar_debug_info_ptr, + sizeof(Dwarf_Unsigned)); + *return_uval = ret_value; + return DW_DLV_OK; + } + break; + case DW_FORM_udata: + ret_value = + (_dwarf_decode_u_leb128(attr->ar_debug_info_ptr, NULL)); + *return_uval = ret_value; + return DW_DLV_OK; + + + /* see bug 583450. We do not allow reading sdata from a udata + value. Caller can retry, calling sdata */ + + + default: + break; + } + _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD); + return (DW_DLV_ERROR); +} + + +int +dwarf_formsdata(Dwarf_Attribute attr, + Dwarf_Signed * return_sval, Dwarf_Error * error) +{ + Dwarf_Signed ret_value = 0; + Dwarf_Debug dbg = 0; + Dwarf_CU_Context cu_context = 0; + + if (attr == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); + return (DW_DLV_ERROR); + } + + cu_context = attr->ar_cu_context; + if (cu_context == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); + return (DW_DLV_ERROR); + } + + dbg = cu_context->cc_dbg; + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); + return (DW_DLV_ERROR); + } + + switch (attr->ar_attribute_form) { + + case DW_FORM_data1: + *return_sval = (*(Dwarf_Sbyte *) attr->ar_debug_info_ptr); + return DW_DLV_OK; + + /* READ_UNALIGNED does not sign extend. + So we have to use a cast to get the + value sign extended in the right way for each case. */ + case DW_FORM_data2:{ + READ_UNALIGNED(dbg, ret_value, Dwarf_Signed, + attr->ar_debug_info_ptr, + sizeof(Dwarf_Shalf)); + *return_sval = (Dwarf_Shalf) ret_value; + return DW_DLV_OK; + + } + + case DW_FORM_data4:{ + READ_UNALIGNED(dbg, ret_value, Dwarf_Signed, + attr->ar_debug_info_ptr, + sizeof(Dwarf_sfixed)); + *return_sval = (Dwarf_sfixed) ret_value; + return DW_DLV_OK; + } + + case DW_FORM_data8:{ + READ_UNALIGNED(dbg, ret_value, Dwarf_Signed, + attr->ar_debug_info_ptr, + sizeof(Dwarf_Signed)); + *return_sval = (Dwarf_Signed) ret_value; + return DW_DLV_OK; + } + + case DW_FORM_sdata: + ret_value = + (_dwarf_decode_s_leb128(attr->ar_debug_info_ptr, NULL)); + *return_sval = ret_value; + return DW_DLV_OK; + + + /* see bug 583450. We do not allow reading sdata from a udata + value. Caller can retry, calling sdata */ + + + default: + break; + } + _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD); + return (DW_DLV_ERROR); +} + + +int +dwarf_formblock(Dwarf_Attribute attr, + Dwarf_Block ** return_block, Dwarf_Error * error) +{ + Dwarf_CU_Context cu_context = 0; + Dwarf_Debug dbg = 0; + Dwarf_Unsigned length = 0; + Dwarf_Small *data = 0; + Dwarf_Word leb128_length = 0; + Dwarf_Block *ret_block = 0; + + if (attr == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); + return (DW_DLV_ERROR); + } + + cu_context = attr->ar_cu_context; + if (cu_context == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); + return (DW_DLV_ERROR); + } + + if (cu_context->cc_dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); + return (DW_DLV_ERROR); + } + dbg = cu_context->cc_dbg; + + switch (attr->ar_attribute_form) { + + case DW_FORM_block1: + length = *(Dwarf_Small *) attr->ar_debug_info_ptr; + data = attr->ar_debug_info_ptr + sizeof(Dwarf_Small); + break; + + case DW_FORM_block2: + READ_UNALIGNED(dbg, length, Dwarf_Unsigned, + attr->ar_debug_info_ptr, sizeof(Dwarf_Half)); + data = attr->ar_debug_info_ptr + sizeof(Dwarf_Half); + break; + + case DW_FORM_block4: + READ_UNALIGNED(dbg, length, Dwarf_Unsigned, + attr->ar_debug_info_ptr, sizeof(Dwarf_ufixed)); + data = attr->ar_debug_info_ptr + sizeof(Dwarf_ufixed); + break; + + case DW_FORM_block: + length = _dwarf_decode_u_leb128(attr->ar_debug_info_ptr, + &leb128_length); + data = attr->ar_debug_info_ptr + leb128_length; + break; + + default: + _dwarf_error(cu_context->cc_dbg, error, DW_DLE_ATTR_FORM_BAD); + return (DW_DLV_ERROR); + } + + /* Check that block lies within current cu in .debug_info. */ + if (attr->ar_debug_info_ptr + length >= + dbg->de_debug_info.dss_data + cu_context->cc_debug_info_offset + + cu_context->cc_length + cu_context->cc_length_size + + cu_context->cc_extension_size) { + _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_SIZE_BAD); + return (DW_DLV_ERROR); + } + + ret_block = (Dwarf_Block *) _dwarf_get_alloc(dbg, DW_DLA_BLOCK, 1); + if (ret_block == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + ret_block->bl_len = length; + ret_block->bl_data = (Dwarf_Ptr) data; + ret_block->bl_from_loclist = 0; + ret_block->bl_section_offset = data - dbg->de_debug_info.dss_data; + + + *return_block = ret_block; + return (DW_DLV_OK); +} + + +/* Contrary to long standing documentation, + The string pointer returned thru return_str must + never have dwarf_dealloc() applied to it. + Documentation fixed July 2005. +*/ +int +dwarf_formstring(Dwarf_Attribute attr, + char **return_str, Dwarf_Error * error) +{ + Dwarf_CU_Context cu_context = 0; + Dwarf_Debug dbg = 0; + Dwarf_Unsigned offset = 0; + int res = DW_DLV_ERROR; + + if (attr == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); + return (DW_DLV_ERROR); + } + + cu_context = attr->ar_cu_context; + if (cu_context == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); + return (DW_DLV_ERROR); + } + + if (cu_context->cc_dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); + return (DW_DLV_ERROR); + } + dbg = cu_context->cc_dbg; + + if (attr->ar_attribute_form == DW_FORM_string) { + + void *begin = attr->ar_debug_info_ptr; + + if (0 == dbg->de_assume_string_in_bounds) { + /* Check that string lies within current cu in .debug_info. + */ + void *end = dbg->de_debug_info.dss_data + + cu_context->cc_debug_info_offset + + cu_context->cc_length + cu_context->cc_length_size + + cu_context->cc_extension_size; + if (0 == _dwarf_string_valid(begin, end)) { + _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_SIZE_BAD); + return (DW_DLV_ERROR); + } + } + *return_str = (char *) (begin); + return DW_DLV_OK; + } + + if (attr->ar_attribute_form == DW_FORM_strp) { + READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, + attr->ar_debug_info_ptr, + cu_context->cc_length_size); + + res = _dwarf_load_section(dbg, &dbg->de_debug_str,error); + if (res != DW_DLV_OK) { + return res; + } + if (0 == dbg->de_assume_string_in_bounds) { + /* Check that string lies within current cu in .debug_info. + */ + void *end = dbg->de_debug_str.dss_data + + dbg->de_debug_str.dss_size; + void*begin = dbg->de_debug_str.dss_data + offset; + if (0 == _dwarf_string_valid(begin, end)) { + _dwarf_error(dbg, error, DW_DLE_STRP_OFFSET_BAD); + return (DW_DLV_ERROR); + } + } + *return_str = (char *) (dbg->de_debug_str.dss_data + offset); + return DW_DLV_OK; + } + + _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD); + return (DW_DLV_ERROR); +} + +int +dwarf_formexprloc(Dwarf_Attribute attr, + Dwarf_Unsigned * return_exprlen, + Dwarf_Ptr * block_ptr, + Dwarf_Error * error) +{ + Dwarf_Debug dbg = 0; + Dwarf_CU_Context cu_context = 0; + + if (attr == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); + return (DW_DLV_ERROR); + } + + cu_context = attr->ar_cu_context; + if (cu_context == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); + return (DW_DLV_ERROR); + } + + dbg = cu_context->cc_dbg; + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); + return (DW_DLV_ERROR); + } + + if (attr->ar_attribute_form == DW_FORM_exprloc ) { + Dwarf_Unsigned exprlen = + (_dwarf_decode_u_leb128(attr->ar_debug_info_ptr, NULL)); + Dwarf_Small * addr = attr->ar_debug_info_ptr; + *return_exprlen = exprlen; + *block_ptr = addr + exprlen; + return DW_DLV_OK; + + } + _dwarf_error(dbg, error, DW_DLE_ATTR_EXPRLOC_FORM_BAD); + return (DW_DLV_ERROR); +} diff --git a/usr/src/lib/libdwarf/common/dwarf_frame.c b/usr/src/lib/libdwarf/common/dwarf_frame.c new file mode 100644 index 0000000000..3a825ee925 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_frame.c @@ -0,0 +1,2442 @@ +/* + + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + + + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include +#include +#include "dwarf_frame.h" +#include "dwarf_arange.h" /* Using Arange as a way to build a + list */ + +#define FDE_NULL_CHECKS_AND_SET_DBG(fde,dbg ) \ + do { \ + if ((fde) == NULL) { \ + _dwarf_error(NULL, error, DW_DLE_FDE_NULL); \ + return (DW_DLV_ERROR); \ + } \ + (dbg)= (fde)->fd_dbg; \ + if ((dbg) == NULL) { \ + _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);\ + return (DW_DLV_ERROR); \ + } } while (0) + + +#define MIN(a,b) (((a) < (b))? a:b) + +static void _dwarf_init_regrule_table(struct Dwarf_Reg_Rule_s *t1reg, + int last_reg_num, + int initial_value); +static int dwarf_initialize_fde_table(Dwarf_Debug dbg, + struct Dwarf_Frame_s *fde_table, + unsigned table_real_data_size, + Dwarf_Error * error); +static void dwarf_free_fde_table(struct Dwarf_Frame_s *fde_table); + +#if 0 +/* Only used for debugging libdwarf. */ +static void dump_frame_rule(char *msg, + struct Dwarf_Reg_Rule_s *reg_rule); +#endif + + + +/* + This function is the heart of the debug_frame stuff. Don't even + think of reading this without reading both the Libdwarf and + consumer API carefully first. This function basically executes + frame instructions contained in a Cie or an Fde, but does in a + number of different ways depending on the information sought. + Start_instr_ptr points to the first byte of the frame instruction + stream, and final_instr_ptr to the to the first byte after the + last. + + The offsets returned in the frame instructions are factored. That + is they need to be multiplied by either the code_alignment_factor + or the data_alignment_factor, as appropriate to obtain the actual + offset. This makes it possible to expand an instruction stream + without the corresponding Cie. However, when an Fde frame instr + sequence is being expanded there must be a valid Cie with a pointer + to an initial table row. + + + If successful, returns DW_DLV_OK + And sets returned_count thru the pointer + if make_instr is true. + If make_instr is false returned_count + should NOT be used by the caller (returned_count + is set to 0 thru the pointer by this routine...) + If unsuccessful, returns DW_DLV_ERROR + and sets returned_error to the error code + + It does not do a whole lot of input validation being a private + function. Please make sure inputs are valid. + + (1) If make_instr is true, it makes a list of pointers to + Dwarf_Frame_Op structures containing the frame instructions + executed. A pointer to this list is returned in ret_frame_instr. + Make_instr is true only when a list of frame instructions is to be + returned. In this case since we are not interested in the contents + of the table, the input Cie can be NULL. This is the only case + where the inpute Cie can be NULL. + + (2) If search_pc is true, frame instructions are executed till + either a location is reached that is greater than the search_pc_val + provided, or all instructions are executed. At this point the + last row of the table generated is returned in a structure. + A pointer to this structure is supplied in table. + + (3) This function is also used to create the initial table row + defined by a Cie. In this case, the Dwarf_Cie pointer cie, is + NULL. For an FDE, however, cie points to the associated Cie. + + make_instr - make list of frame instr? 0/1 + ret_frame_instr - Ptr to list of ptrs to frame instrs + search_pc - Search for a pc value? 0/1 + search_pc_val - Search for this pc value + initial_loc - Initial code location value. + start_instr_ptr - Ptr to start of frame instrs. + final_instr_ptr - Ptr just past frame instrs. + table - Ptr to struct with last row. + cie - Ptr to Cie used by the Fde. + Different cies may have distinct address-sizes, so the cie + is used, not de_pointer_size. + +*/ + +int +_dwarf_exec_frame_instr(Dwarf_Bool make_instr, + Dwarf_Frame_Op ** ret_frame_instr, + Dwarf_Bool search_pc, + Dwarf_Addr search_pc_val, + Dwarf_Addr initial_loc, + Dwarf_Small * start_instr_ptr, + Dwarf_Small * final_instr_ptr, + Dwarf_Frame table, + Dwarf_Cie cie, + Dwarf_Debug dbg, + Dwarf_Half reg_num_of_cfa, + Dwarf_Sword * returned_count, + int *returned_error) +{ +#define ERROR_IF_REG_NUM_TOO_HIGH(macreg,machigh_reg) \ + do { \ + if ((macreg) >= (machigh_reg) || (macreg) < 0) { \ + SIMPLE_ERROR_RETURN(DW_DLE_DF_REG_NUM_TOO_HIGH); \ + } \ + } /*CONSTCOND */ while(0) +#define SIMPLE_ERROR_RETURN(code) \ + free(localregtab); \ + *returned_error = code; \ + return DW_DLV_ERROR + + /* Sweeps the frame instructions. */ + Dwarf_Small *instr_ptr; + + /* Register numbers not limited to just 255, thus not using + Dwarf_Small. */ + typedef int reg_num_type; + + Dwarf_Unsigned factored_N_value; + Dwarf_Signed signed_factored_N_value; + Dwarf_Addr current_loc = initial_loc; /* code location/ + pc-value + corresponding to the + frame instructions. + Starts at zero when + the caller has no + value to pass in. */ + + /* Must be min de_pointer_size bytes and must be at least sizeof + Dwarf_ufixed */ + Dwarf_Unsigned adv_loc = 0; + + int reg_count = dbg->de_frame_reg_rules_entry_count; + struct Dwarf_Reg_Rule_s *localregtab = calloc(reg_count, + sizeof(struct + Dwarf_Reg_Rule_s)); + + struct Dwarf_Reg_Rule_s cfa_reg; + + + /* This is used to end executing frame instructions. */ + /* Becomes true when search_pc is true and current_loc */ + /* is greater than search_pc_val. */ + Dwarf_Bool search_over = false; + + /* Used by the DW_FRAME_advance_loc instr */ + /* to hold the increment in pc value. */ + Dwarf_Addr adv_pc; + + /* Contains the length in bytes of */ + /* an leb128 encoded number. */ + Dwarf_Word leb128_length; + + Dwarf_Half address_size = (cie)? cie->ci_address_size: + dbg->de_pointer_size; + + /* Counts the number of frame instructions executed. */ + Dwarf_Word instr_count = 0; + + /* + These contain the current fields of the current frame + instruction. */ + Dwarf_Small fp_base_op = 0; + Dwarf_Small fp_extended_op; + reg_num_type fp_register; + + /* The value in fp_offset may be signed, though we call it + unsigned. This works ok for 2-s complement arithmetic. */ + Dwarf_Unsigned fp_offset; + Dwarf_Off fp_instr_offset; + + /* + Stack_table points to the row (Dwarf_Frame ie) being pushed or + popped by a remember or restore instruction. Top_stack points to + the top of the stack of rows. */ + Dwarf_Frame stack_table = NULL; + Dwarf_Frame top_stack = NULL; + + /* + These are used only when make_instr is true. Curr_instr is a + pointer to the current frame instruction executed. + Curr_instr_ptr, head_instr_list, and curr_instr_list are used to + form a chain of Dwarf_Frame_Op structs. Dealloc_instr_ptr is + used to deallocate the structs used to form the chain. + Head_instr_block points to a contiguous list of pointers to the + Dwarf_Frame_Op structs executed. */ + Dwarf_Frame_Op *curr_instr; + Dwarf_Chain curr_instr_item, dealloc_instr_item; + Dwarf_Chain head_instr_chain = NULL; + Dwarf_Chain tail_instr_chain = NULL; + Dwarf_Frame_Op *head_instr_block; + + /* + These are the alignment_factors taken from the Cie provided. + When no input Cie is provided they are set to 1, because only + factored offsets are required. */ + Dwarf_Sword code_alignment_factor = 1; + Dwarf_Sword data_alignment_factor = 1; + + /* + This flag indicates when an actual alignment factor is needed. + So if a frame instruction that computes an offset using an + alignment factor is encountered when this flag is set, an error + is returned because the Cie did not have a valid augmentation. */ + Dwarf_Bool need_augmentation = false; + + Dwarf_Word i; + + /* Initialize first row from associated Cie. Using temp regs + explicity */ + + if (localregtab == 0) { + SIMPLE_ERROR_RETURN(DW_DLE_ALLOC_FAIL); + } + { + struct Dwarf_Reg_Rule_s *t1reg = localregtab; + struct Dwarf_Reg_Rule_s *t1end = t1reg + reg_count; + + if (cie != NULL && cie->ci_initial_table != NULL) { + struct Dwarf_Reg_Rule_s *t2reg = + cie->ci_initial_table->fr_reg; + + if (reg_count != cie->ci_initial_table->fr_reg_count) { + /* Should never happen, it makes no sense to have the + table sizes change. There is no real allowance for + the set of registers to change dynamically in a + single Dwarf_Debug (except the size can be set near + initial Dwarf_Debug creation time). */ + SIMPLE_ERROR_RETURN + (DW_DLE_FRAME_REGISTER_COUNT_MISMATCH); + } + + for (; t1reg < t1end; t1reg++, t2reg++) { + *t1reg = *t2reg; + } + cfa_reg = cie->ci_initial_table->fr_cfa_rule; + } else { + _dwarf_init_regrule_table(t1reg, + reg_count, + dbg->de_frame_rule_initial_value); + _dwarf_init_regrule_table(&cfa_reg, 1, + dbg->de_frame_rule_initial_value); + } + } + + /* + The idea here is that the code_alignment_factor and + data_alignment_factor which are needed for certain instructions + are valid only when the Cie has a proper augmentation string. So + if the augmentation is not right, only Frame instruction can be + read. */ + if (cie != NULL && cie->ci_augmentation != NULL) { + code_alignment_factor = cie->ci_code_alignment_factor; + data_alignment_factor = cie->ci_data_alignment_factor; + } else { + need_augmentation = !make_instr; + } + + instr_ptr = start_instr_ptr; + while ((instr_ptr < final_instr_ptr) && (!search_over)) { + Dwarf_Small instr = 0; + Dwarf_Small opcode = 0; + reg_num_type reg_no = 0; + + fp_instr_offset = instr_ptr - start_instr_ptr; + instr = *(Dwarf_Small *) instr_ptr; + instr_ptr += sizeof(Dwarf_Small); + + fp_base_op = (instr & 0xc0) >> 6; + if ((instr & 0xc0) == 0x00) { + opcode = instr; /* is really extended op */ + fp_extended_op = (instr & (~(0xc0))) & 0xff; + } else { + opcode = instr & 0xc0; /* is base op */ + fp_extended_op = 0; + } + + fp_register = 0; + fp_offset = 0; + switch (opcode) { + case DW_CFA_advance_loc: + { + /* base op */ + fp_offset = adv_pc = instr & DW_FRAME_INSTR_OFFSET_MASK; + + if (need_augmentation) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); + } + adv_pc = adv_pc * code_alignment_factor; + + search_over = search_pc && + (current_loc + adv_pc > search_pc_val); + /* If gone past pc needed, retain old pc. */ + if (!search_over) { + current_loc = current_loc + adv_pc; + } + break; + } + + case DW_CFA_offset: + { /* base op */ + reg_no = + (reg_num_type) (instr & DW_FRAME_INSTR_OFFSET_MASK); + ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); + + factored_N_value = + _dwarf_decode_u_leb128(instr_ptr, &leb128_length); + instr_ptr = instr_ptr + leb128_length; + + fp_register = reg_no; + fp_offset = factored_N_value; + + if (need_augmentation) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); + } + + localregtab[reg_no].ru_is_off = 1; + localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; + localregtab[reg_no].ru_register = reg_num_of_cfa; + localregtab[reg_no].ru_offset_or_block_len = + factored_N_value * data_alignment_factor; + + break; + } + + case DW_CFA_restore: + { /* base op */ + reg_no = (instr & DW_FRAME_INSTR_OFFSET_MASK); + ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); + + fp_register = reg_no; + + if (cie != NULL && cie->ci_initial_table != NULL) + localregtab[reg_no] = + cie->ci_initial_table->fr_reg[reg_no]; + else if (!make_instr) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_MAKE_INSTR_NO_INIT); + } + + break; + } + case DW_CFA_set_loc: + { + Dwarf_Addr new_loc = 0; + + READ_UNALIGNED(dbg, new_loc, Dwarf_Addr, + instr_ptr, address_size); + instr_ptr += address_size; + if (new_loc != 0 && current_loc != 0) { + /* Pre-relocation or before current_loc is set the + test comparing new_loc and current_loc makes no + sense. Testing for non-zero (above) is a way + (fallible) to check that current_loc, new_loc + are already relocated. */ + if (new_loc <= current_loc) { + /* Within a frame, address must increase. + Seemingly it has not. Seems to be an error. */ + + SIMPLE_ERROR_RETURN + (DW_DLE_DF_NEW_LOC_LESS_OLD_LOC); + } + } + + search_over = search_pc && (new_loc > search_pc_val); + + /* If gone past pc needed, retain old pc. */ + if (!search_over) { + current_loc = new_loc; + } + fp_offset = new_loc; + break; + } + + case DW_CFA_advance_loc1: + { + fp_offset = adv_loc = *(Dwarf_Small *) instr_ptr; + instr_ptr += sizeof(Dwarf_Small); + + if (need_augmentation) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); + } + adv_loc *= code_alignment_factor; + + search_over = search_pc && + (current_loc + adv_loc > search_pc_val); + + /* If gone past pc needed, retain old pc. */ + if (!search_over) { + current_loc = current_loc + adv_loc; + } + break; + } + + case DW_CFA_advance_loc2: + { + READ_UNALIGNED(dbg, adv_loc, Dwarf_Unsigned, + instr_ptr, sizeof(Dwarf_Half)); + instr_ptr += sizeof(Dwarf_Half); + fp_offset = adv_loc; + + if (need_augmentation) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); + } + adv_loc *= code_alignment_factor; + + search_over = search_pc && + (current_loc + adv_loc > search_pc_val); + + /* If gone past pc needed, retain old pc. */ + if (!search_over) { + current_loc = current_loc + adv_loc; + } + break; + } + + case DW_CFA_advance_loc4: + { + READ_UNALIGNED(dbg, adv_loc, Dwarf_Unsigned, + instr_ptr, sizeof(Dwarf_ufixed)); + instr_ptr += sizeof(Dwarf_ufixed); + fp_offset = adv_loc; + + if (need_augmentation) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); + } + adv_loc *= code_alignment_factor; + + search_over = search_pc && + (current_loc + adv_loc > search_pc_val); + + /* If gone past pc needed, retain old pc. */ + if (!search_over) { + current_loc = current_loc + adv_loc; + } + break; + } + + case DW_CFA_offset_extended: + { + Dwarf_Unsigned lreg; + + DECODE_LEB128_UWORD(instr_ptr, lreg); + reg_no = (reg_num_type) lreg; + ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);; + factored_N_value = + _dwarf_decode_u_leb128(instr_ptr, &leb128_length); + instr_ptr += leb128_length; + + if (need_augmentation) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); + } + localregtab[reg_no].ru_is_off = 1; + localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; + localregtab[reg_no].ru_register = reg_num_of_cfa; + localregtab[reg_no].ru_offset_or_block_len = factored_N_value * + data_alignment_factor; + + fp_register = reg_no; + fp_offset = factored_N_value; + break; + } + + case DW_CFA_restore_extended: + { + Dwarf_Unsigned lreg; + + DECODE_LEB128_UWORD(instr_ptr, lreg); + reg_no = (reg_num_type) lreg; + + ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); + + if (cie != NULL && cie->ci_initial_table != NULL) { + localregtab[reg_no] = cie->ci_initial_table->fr_reg[reg_no]; + } else { + if (!make_instr) { + SIMPLE_ERROR_RETURN + (DW_DLE_DF_MAKE_INSTR_NO_INIT); + } + } + + fp_register = reg_no; + break; + } + + case DW_CFA_undefined: + { + Dwarf_Unsigned lreg; + + DECODE_LEB128_UWORD(instr_ptr, lreg); + reg_no = (reg_num_type) lreg; + ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); + + localregtab[reg_no].ru_is_off = 0; + localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; + localregtab[reg_no].ru_register = + dbg->de_frame_undefined_value_number; + localregtab[reg_no].ru_offset_or_block_len = 0; + + fp_register = reg_no; + break; + } + + case DW_CFA_same_value: + { + Dwarf_Unsigned lreg; + + DECODE_LEB128_UWORD(instr_ptr, lreg); + reg_no = (reg_num_type) lreg; + ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); + + localregtab[reg_no].ru_is_off = 0; + localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; + localregtab[reg_no].ru_register = + dbg->de_frame_same_value_number; + localregtab[reg_no].ru_offset_or_block_len = 0; + fp_register = reg_no; + break; + } + + case DW_CFA_register: + { + Dwarf_Unsigned lreg; + reg_num_type reg_noA = 0; + reg_num_type reg_noB = 0; + + DECODE_LEB128_UWORD(instr_ptr, lreg); + reg_noA = (reg_num_type) lreg; + + ERROR_IF_REG_NUM_TOO_HIGH(reg_noA, reg_count); + + DECODE_LEB128_UWORD(instr_ptr, lreg); + reg_noB = (reg_num_type) lreg; + + if (reg_noB > reg_count) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_REG_NUM_TOO_HIGH); + } + + + localregtab[reg_noA].ru_is_off = 0; + localregtab[reg_noA].ru_value_type = DW_EXPR_OFFSET; + localregtab[reg_noA].ru_register = reg_noB; + localregtab[reg_noA].ru_offset_or_block_len = 0; + + fp_register = reg_noA; + fp_offset = reg_noB; + break; + } + + case DW_CFA_remember_state: + { + stack_table = (Dwarf_Frame) + _dwarf_get_alloc(dbg, DW_DLA_FRAME, 1); + if (stack_table == NULL) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL); + } + + for (i = 0; i < reg_count; i++) + stack_table->fr_reg[i] = localregtab[i]; + stack_table->fr_cfa_rule = cfa_reg; + + if (top_stack != NULL) + stack_table->fr_next = top_stack; + top_stack = stack_table; + + break; + } + + case DW_CFA_restore_state: + { + if (top_stack == NULL) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_POP_EMPTY_STACK); + } + stack_table = top_stack; + top_stack = stack_table->fr_next; + + for (i = 0; i < reg_count; i++) + localregtab[i] = stack_table->fr_reg[i]; + cfa_reg = stack_table->fr_cfa_rule; + + dwarf_dealloc(dbg, stack_table, DW_DLA_FRAME); + break; + } + + case DW_CFA_def_cfa: + { + Dwarf_Unsigned lreg; + + DECODE_LEB128_UWORD(instr_ptr, lreg); + reg_no = (reg_num_type) lreg; + + ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); + + factored_N_value = + _dwarf_decode_u_leb128(instr_ptr, &leb128_length); + instr_ptr += leb128_length; + + if (need_augmentation) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); + } + cfa_reg.ru_is_off = 1; + cfa_reg.ru_value_type = DW_EXPR_OFFSET; + cfa_reg.ru_register = reg_no; + cfa_reg.ru_offset_or_block_len = factored_N_value; + + fp_register = reg_no; + fp_offset = factored_N_value; + break; + } + + case DW_CFA_def_cfa_register: + { + Dwarf_Unsigned lreg; + + DECODE_LEB128_UWORD(instr_ptr, lreg); + reg_no = (reg_num_type) lreg; + ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); + + cfa_reg.ru_register = reg_no; + /* Do NOT set ru_offset_or_block_len or ru_is_off here. + See dwarf2/3 spec. */ + fp_register = reg_no; + break; + } + + case DW_CFA_def_cfa_offset: + { + factored_N_value = + _dwarf_decode_u_leb128(instr_ptr, &leb128_length); + instr_ptr += leb128_length; + + if (need_augmentation) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); + } + /* Do set ru_is_off here, as here factored_N_value + counts. */ + cfa_reg.ru_is_off = 1; + cfa_reg.ru_value_type = DW_EXPR_OFFSET; + cfa_reg.ru_offset_or_block_len = factored_N_value; + + fp_offset = factored_N_value; + break; + } + case DW_CFA_nop: + { + break; + } + /* DWARF3 ops begin here. */ + case DW_CFA_def_cfa_expression: + { + /* A single DW_FORM_block representing a dwarf + expression. The form block establishes the way to + compute the CFA. */ + Dwarf_Unsigned block_len = 0; + + DECODE_LEB128_UWORD(instr_ptr, block_len); + cfa_reg.ru_is_off = 0; /* arbitrary */ + cfa_reg.ru_value_type = DW_EXPR_EXPRESSION; + cfa_reg.ru_offset_or_block_len = block_len; + cfa_reg.ru_block = instr_ptr; + fp_offset = (Dwarf_Unsigned)(uintptr_t)instr_ptr; + instr_ptr += block_len; + } + break; + case DW_CFA_expression: + { + /* An unsigned leb128 value is the first operand (a + register number). The second operand is single + DW_FORM_block representing a dwarf expression. The + evaluator pushes the CFA on the evaluation stack + then evaluates the expression to compute the value + of the register contents. */ + Dwarf_Unsigned lreg = 0; + Dwarf_Unsigned block_len = 0; + + DECODE_LEB128_UWORD(instr_ptr, lreg); + reg_no = (reg_num_type) lreg; + ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); + DECODE_LEB128_UWORD(instr_ptr, block_len); + localregtab[lreg].ru_is_off = 0; /* arbitrary */ + localregtab[lreg].ru_value_type = DW_EXPR_EXPRESSION; + localregtab[lreg].ru_offset_or_block_len = block_len; + localregtab[lreg].ru_block = instr_ptr; + fp_offset = (Dwarf_Unsigned)(uintptr_t)instr_ptr; + fp_register = reg_no; + instr_ptr += block_len; + } + break; + case DW_CFA_offset_extended_sf: + { + /* The first operand is an unsigned leb128 register + number. The second is a signed factored offset. + Identical to DW_CFA_offset_extended except the + secondoperand is signed */ + Dwarf_Unsigned lreg; + + DECODE_LEB128_UWORD(instr_ptr, lreg); + reg_no = (reg_num_type) lreg; + ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); + signed_factored_N_value = + _dwarf_decode_s_leb128(instr_ptr, &leb128_length); + instr_ptr += leb128_length; + + if (need_augmentation) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); + } + localregtab[reg_no].ru_is_off = 1; + localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; + localregtab[reg_no].ru_register = reg_num_of_cfa; + localregtab[reg_no].ru_offset_or_block_len = + signed_factored_N_value * data_alignment_factor; + + fp_register = reg_no; + fp_offset = signed_factored_N_value; + } + break; + case DW_CFA_def_cfa_sf: + { + /* The first operand is an unsigned leb128 register + number. The second is a signed leb128 factored + offset. Identical to DW_CFA_def_cfa except that the + second operand is signed and factored. */ + Dwarf_Unsigned lreg; + + DECODE_LEB128_UWORD(instr_ptr, lreg); + reg_no = (reg_num_type) lreg; + ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); + + signed_factored_N_value = + _dwarf_decode_s_leb128(instr_ptr, &leb128_length); + instr_ptr += leb128_length; + + if (need_augmentation) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); + } + cfa_reg.ru_is_off = 1; + cfa_reg.ru_value_type = DW_EXPR_OFFSET; + cfa_reg.ru_register = reg_no; + cfa_reg.ru_offset_or_block_len = + signed_factored_N_value * data_alignment_factor; + + fp_register = reg_no; + fp_offset = signed_factored_N_value; + } + break; + case DW_CFA_def_cfa_offset_sf: + { + /* The operand is a signed leb128 operand representing + a factored offset. Identical to + DW_CFA_def_cfa_offset excep the operand is signed + and factored. */ + + signed_factored_N_value = + _dwarf_decode_s_leb128(instr_ptr, &leb128_length); + instr_ptr += leb128_length; + + if (need_augmentation) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); + } + /* Do set ru_is_off here, as here factored_N_value + counts. */ + cfa_reg.ru_is_off = 1; + cfa_reg.ru_value_type = DW_EXPR_OFFSET; + cfa_reg.ru_offset_or_block_len = + signed_factored_N_value * data_alignment_factor; + + fp_offset = signed_factored_N_value; + } + break; + case DW_CFA_val_offset: + { + /* The first operand is an unsigned leb128 register + number. The second is a factored unsigned offset. + Makes the register be a val_offset(N) rule with N = + factored_offset*data_alignment_factor. */ + + Dwarf_Unsigned lreg; + + DECODE_LEB128_UWORD(instr_ptr, lreg); + reg_no = (reg_num_type) lreg; + + ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); + + factored_N_value = + _dwarf_decode_u_leb128(instr_ptr, &leb128_length); + instr_ptr += leb128_length; + + if (need_augmentation) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); + } + /* Do set ru_is_off here, as here factored_N_value + counts. */ + localregtab[reg_no].ru_is_off = 1; + localregtab[reg_no].ru_register = reg_num_of_cfa; + localregtab[reg_no].ru_value_type = DW_EXPR_VAL_OFFSET; + localregtab[reg_no].ru_offset_or_block_len = + factored_N_value * data_alignment_factor; + + fp_offset = factored_N_value; + break; + } + case DW_CFA_val_offset_sf: + { + /* The first operand is an unsigned leb128 register + number. The second is a factored signed offset. + Makes the register be a val_offset(N) rule with N = + factored_offset*data_alignment_factor. */ + Dwarf_Unsigned lreg; + + DECODE_LEB128_UWORD(instr_ptr, lreg); + reg_no = (reg_num_type) lreg; + + ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); + signed_factored_N_value = + _dwarf_decode_s_leb128(instr_ptr, &leb128_length); + instr_ptr += leb128_length; + + if (need_augmentation) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); + } + /* Do set ru_is_off here, as here factored_N_value + counts. */ + localregtab[reg_no].ru_is_off = 1; + localregtab[reg_no].ru_value_type = DW_EXPR_VAL_OFFSET; + localregtab[reg_no].ru_offset_or_block_len = + signed_factored_N_value * data_alignment_factor; + + fp_offset = signed_factored_N_value; + + } + break; + case DW_CFA_val_expression: + { + /* The first operand is an unsigned leb128 register + number. The second is a DW_FORM_block representing a + DWARF expression. The rule for the register number + becomes a val_expression(E) rule. */ + Dwarf_Unsigned lreg = 0; + Dwarf_Unsigned block_len = 0; + + DECODE_LEB128_UWORD(instr_ptr, lreg); + reg_no = (reg_num_type) lreg; + ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); + DECODE_LEB128_UWORD(instr_ptr, block_len); + localregtab[lreg].ru_is_off = 0; /* arbitrary */ + localregtab[lreg].ru_value_type = DW_EXPR_VAL_EXPRESSION; + localregtab[lreg].ru_offset_or_block_len = block_len; + localregtab[lreg].ru_block = instr_ptr; + fp_offset = (Dwarf_Unsigned)(uintptr_t)instr_ptr; + + instr_ptr += block_len; + fp_register = reg_no; + + } + break; + + /* END DWARF3 new ops. */ + + +#ifdef DW_CFA_GNU_window_save + case DW_CFA_GNU_window_save: + { + /* no information: this just tells unwinder to restore + the window registers from the previous frame's + window save area */ + break; + } +#endif +#ifdef DW_CFA_GNU_args_size + /* single uleb128 is the current arg area size in bytes. No + register exists yet to save this in */ + case DW_CFA_GNU_args_size: + { + Dwarf_Unsigned lreg; + + DECODE_LEB128_UWORD(instr_ptr, lreg); + reg_no = (reg_num_type) lreg; + + break; + } +#endif + default: + /* ERROR, we have an opcode we know nothing about. Memory + leak here, but an error like this is not supposed to + happen so we ignore the leak. These used to be ignored, + now we notice and report. */ + SIMPLE_ERROR_RETURN(DW_DLE_DF_FRAME_DECODING_ERROR); + + } + + if (make_instr) { + instr_count++; + + curr_instr = (Dwarf_Frame_Op *) + _dwarf_get_alloc(dbg, DW_DLA_FRAME_OP, 1); + if (curr_instr == NULL) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL); + } + + curr_instr->fp_base_op = fp_base_op; + curr_instr->fp_extended_op = fp_extended_op; + curr_instr->fp_register = fp_register; + curr_instr->fp_offset = fp_offset; + curr_instr->fp_instr_offset = fp_instr_offset; + + curr_instr_item = (Dwarf_Chain) + _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); + if (curr_instr_item == NULL) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL); + } + + curr_instr_item->ch_item = curr_instr; + if (head_instr_chain == NULL) + head_instr_chain = tail_instr_chain = curr_instr_item; + else { + tail_instr_chain->ch_next = curr_instr_item; + tail_instr_chain = curr_instr_item; + } + } + } + + /* + If frame instruction decoding was right we would stop exactly at + final_instr_ptr. */ + if (instr_ptr > final_instr_ptr) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_FRAME_DECODING_ERROR); + } + + /* Fill in the actual output table, the space the caller passed in. */ + if (table != NULL) { + + struct Dwarf_Reg_Rule_s *t2reg = table->fr_reg; + struct Dwarf_Reg_Rule_s *t3reg = localregtab; + struct Dwarf_Reg_Rule_s *t3end = t3reg + reg_count; + + table->fr_loc = current_loc; + for (; t3reg < t3end; t3reg++, t2reg++) { + *t2reg = *t3reg; + } + + /* CONSTCOND */ + /* Do not update the main table with the cfa_reg. + Just leave cfa_reg as cfa_reg. */ + table->fr_cfa_rule = cfa_reg; + } + + /* Dealloc anything remaining on stack. */ + for (; top_stack != NULL;) { + stack_table = top_stack; + top_stack = top_stack->fr_next; + dwarf_dealloc(dbg, stack_table, DW_DLA_FRAME); + } + + if (make_instr) { + /* Allocate list of pointers to Dwarf_Frame_Op's. */ + head_instr_block = (Dwarf_Frame_Op *) + _dwarf_get_alloc(dbg, DW_DLA_FRAME_BLOCK, instr_count); + if (head_instr_block == NULL) { + SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL); + } + + /* + Store pointers to Dwarf_Frame_Op's in this list and + deallocate the structs that chain the Dwarf_Frame_Op's. */ + curr_instr_item = head_instr_chain; + for (i = 0; i < instr_count; i++) { + *(head_instr_block + i) = + *(Dwarf_Frame_Op *) curr_instr_item->ch_item; + dealloc_instr_item = curr_instr_item; + curr_instr_item = curr_instr_item->ch_next; + dwarf_dealloc(dbg, dealloc_instr_item->ch_item, + DW_DLA_FRAME_OP); + dwarf_dealloc(dbg, dealloc_instr_item, DW_DLA_CHAIN); + } + *ret_frame_instr = head_instr_block; + + *returned_count = (Dwarf_Sword) instr_count; + } else { + *returned_count = 0; + } + free(localregtab); + return DW_DLV_OK; +#undef ERROR_IF_REG_NUM_TOO_HIGH +#undef SIMPLE_ERROR_RETURN +} + +/* Depending on version, either read the return address register + as a ubyte or as an leb number. + The form of this value changed for DWARF3. +*/ +Dwarf_Unsigned +_dwarf_get_return_address_reg(Dwarf_Small * frame_ptr, + int version, unsigned long *size) +{ + Dwarf_Unsigned uvalue = 0; + Dwarf_Word leb128_length = 0; + + if (version == 1) { + *size = 1; + uvalue = *(unsigned char *) frame_ptr; + return uvalue; + } + uvalue = _dwarf_decode_u_leb128(frame_ptr, &leb128_length); + *size = leb128_length; + return uvalue; +} + + +/* Trivial consumer function. +*/ +int +dwarf_get_cie_of_fde(Dwarf_Fde fde, + Dwarf_Cie * cie_returned, Dwarf_Error * error) +{ + if (fde == NULL) { + _dwarf_error(NULL, error, DW_DLE_FDE_NULL); + return (DW_DLV_ERROR); + } + + *cie_returned = fde->fd_cie; + return DW_DLV_OK; + +} + +int dwarf_get_cie_index( + Dwarf_Cie cie, + Dwarf_Signed* index, + Dwarf_Error* error ) +{ + if( cie == NULL ) + { + _dwarf_error(NULL, error, DW_DLE_CIE_NULL); + return (DW_DLV_ERROR); + } + + *index = cie->ci_index; + return (DW_DLV_OK); +} + + +/* + For g++ .eh_frame fde and cie. + the cie id is different as the + definition of the cie_id in an fde + is the distance back from the address of the + value to the cie. + Or 0 if this is a true cie. + Non standard dwarf, designed this way to be + convenient at run time for an allocated + (mapped into memory as part of the running image) section. +*/ +int +dwarf_get_fde_list_eh(Dwarf_Debug dbg, + Dwarf_Cie ** cie_data, + Dwarf_Signed * cie_element_count, + Dwarf_Fde ** fde_data, + Dwarf_Signed * fde_element_count, + Dwarf_Error * error) +{ + int res = _dwarf_load_section(dbg, &dbg->de_debug_frame_eh_gnu,error); + if (res != DW_DLV_OK) { + return res; + } + + res = _dwarf_get_fde_list_internal(dbg, + cie_data, + cie_element_count, + fde_data, + fde_element_count, + dbg->de_debug_frame_eh_gnu.dss_data, + dbg->de_debug_frame_eh_gnu.dss_index, + dbg->de_debug_frame_eh_gnu.dss_size, + /* cie_id_value */ 0, + /* use_gnu_cie_calc= */ 1, + error); + return res; +} + + + +/* + For standard dwarf .debug_frame + cie_id is -1 in a cie, and + is the section offset in the .debug_frame section + of the cie otherwise. Standard dwarf +*/ +int +dwarf_get_fde_list(Dwarf_Debug dbg, + Dwarf_Cie ** cie_data, + Dwarf_Signed * cie_element_count, + Dwarf_Fde ** fde_data, + Dwarf_Signed * fde_element_count, + Dwarf_Error * error) +{ + int res = _dwarf_load_section(dbg, &dbg->de_debug_frame,error); + if (res != DW_DLV_OK) { + return res; + } + + res = _dwarf_get_fde_list_internal(dbg, cie_data, + cie_element_count, + fde_data, + fde_element_count, + dbg->de_debug_frame.dss_data, + dbg->de_debug_frame.dss_index, + dbg->de_debug_frame.dss_size, + DW_CIE_ID, + /* use_gnu_cie_calc= */ 0, + error); + + return res; +} + + +/* + Only works on dwarf sections, not eh_frame + Given a Dwarf_Die, see if it has a + DW_AT_MIPS_fde attribute and if so use that + to get an fde offset. + Then create a Dwarf_Fde to return thru the ret_fde pointer. + Also creates a cie (pointed at from the Dwarf_Fde). +*/ +int +dwarf_get_fde_for_die(Dwarf_Debug dbg, + Dwarf_Die die, + Dwarf_Fde * ret_fde, Dwarf_Error * error) +{ + Dwarf_Attribute attr; + Dwarf_Unsigned fde_offset = 0; + Dwarf_Signed signdval = 0; + Dwarf_Fde new_fde = 0; + unsigned char *fde_ptr = 0; + unsigned char *cie_ptr = 0; + Dwarf_Unsigned cie_id = 0; + + /* Fields for the current Cie being read. */ + int res = 0; + int resattr = 0; + int sdatares = 0; + + struct cie_fde_prefix_s prefix; + struct cie_fde_prefix_s prefix_c; + + if (die == NULL) { + _dwarf_error(NULL, error, DW_DLE_DIE_NULL); + return (DW_DLV_ERROR); + } + + resattr = dwarf_attr(die, DW_AT_MIPS_fde, &attr, error); + if (resattr != DW_DLV_OK) { + return resattr; + } + + /* why is this formsdata? FIX */ + sdatares = dwarf_formsdata(attr, &signdval, error); + if (sdatares != DW_DLV_OK) { + return sdatares; + } + + res = _dwarf_load_section(dbg, &dbg->de_debug_frame,error); + if (res != DW_DLV_OK) { + return res; + } + + fde_offset = signdval; + fde_ptr = (dbg->de_debug_frame.dss_data + fde_offset); + + + /* First read in the 'common prefix' to figure out what * we are to + do with this entry. */ + memset(&prefix_c, 0, sizeof(prefix_c)); + memset(&prefix, 0, sizeof(prefix)); + res = dwarf_read_cie_fde_prefix(dbg, fde_ptr, + dbg->de_debug_frame.dss_data, + dbg->de_debug_frame.dss_index, + dbg->de_debug_frame.dss_size, + &prefix, + error); + if (res == DW_DLV_ERROR) { + return res; + } + if (res == DW_DLV_NO_ENTRY) + return res; + fde_ptr = prefix.cf_addr_after_prefix; + cie_id = prefix.cf_cie_id; + /* Pass NULL, not section pointer, for 3rd argument. + de_debug_frame.dss_data has no eh_frame relevance. */ + res = dwarf_create_fde_from_after_start(dbg, &prefix, + (Dwarf_Small *) NULL, + fde_ptr, + /* use_gnu_cie_calc= */ 0, + /* Dwarf_Cie = */ 0, + &new_fde, error); + if (res == DW_DLV_ERROR) { + return res; + } else if (res == DW_DLV_NO_ENTRY) { + return res; + } + /* DW_DLV_OK */ + + /* now read the cie corresponding to the fde */ + cie_ptr = new_fde->fd_section_ptr + cie_id; + res = dwarf_read_cie_fde_prefix(dbg, cie_ptr, + dbg->de_debug_frame.dss_data, + dbg->de_debug_frame.dss_index, + dbg->de_debug_frame.dss_size, + &prefix_c, error); + if (res == DW_DLV_ERROR) { + return res; + } + if (res == DW_DLV_NO_ENTRY) + return res; + + cie_ptr = prefix_c.cf_addr_after_prefix; + cie_id = prefix_c.cf_cie_id; + + if (cie_id == DW_CIE_ID) { + int res2 = 0; + Dwarf_Cie new_cie = 0; + + /* Pass NULL, not section pointer, for 3rd argument. + de_debug_frame.dss_data has no eh_frame relevance. */ + res2 = dwarf_create_cie_from_after_start(dbg, + &prefix_c, + (Dwarf_Small *) NULL, + cie_ptr, + /* cie_count= */ 0, + /* use_gnu_cie_calc= */ + 0, &new_cie, error); + if (res2 == DW_DLV_ERROR) { + dwarf_dealloc(dbg, new_fde, DW_DLA_FDE); + return res; + } else if (res2 == DW_DLV_NO_ENTRY) { + dwarf_dealloc(dbg, new_fde, DW_DLA_FDE); + return res; + } + new_fde->fd_cie = new_cie; + } else { + _dwarf_error(dbg, error, DW_DLE_NO_CIE_FOR_FDE); + return (DW_DLV_ERROR); + } + + *ret_fde = new_fde; + return DW_DLV_OK; +} + +/* A dwarf consumer operation, see the consumer library documentation. +*/ +int +dwarf_get_fde_range(Dwarf_Fde fde, + Dwarf_Addr * low_pc, + Dwarf_Unsigned * func_length, + Dwarf_Ptr * fde_bytes, + Dwarf_Unsigned * fde_byte_length, + Dwarf_Off * cie_offset, + Dwarf_Signed * cie_index, + Dwarf_Off * fde_offset, Dwarf_Error * error) +{ + Dwarf_Debug dbg; + + if (fde == NULL) { + _dwarf_error(NULL, error, DW_DLE_FDE_NULL); + return (DW_DLV_ERROR); + } + + dbg = fde->fd_dbg; + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL); + return (DW_DLV_ERROR); + } + + + /* We have always already done the section load here, so no need to + load the section. We did the section load in order to create the + Dwarf_Fde pointer passed in here. */ + + + if (low_pc != NULL) + *low_pc = fde->fd_initial_location; + if (func_length != NULL) + *func_length = fde->fd_address_range; + if (fde_bytes != NULL) + *fde_bytes = fde->fd_fde_start; + if (fde_byte_length != NULL) + *fde_byte_length = fde->fd_length; + if (cie_offset != NULL) + *cie_offset = fde->fd_cie_offset; + if (cie_index != NULL) + *cie_index = fde->fd_cie_index; + if (fde_offset != NULL) + *fde_offset = fde->fd_fde_start - fde->fd_section_ptr; + + return DW_DLV_OK; +} + +/* IRIX specific function. The exception tables + have C++ destructor information and are + at present undocumented. */ +int +dwarf_get_fde_exception_info(Dwarf_Fde fde, + Dwarf_Signed * + offset_into_exception_tables, + Dwarf_Error * error) +{ + Dwarf_Debug dbg; + + dbg = fde->fd_dbg; + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL); + return (DW_DLV_ERROR); + } + *offset_into_exception_tables = + fde->fd_offset_into_exception_tables; + return DW_DLV_OK; +} + + +/* A consumer code function. + Given a CIE pointer, return the normal CIE data thru + pointers. + Special augmentation data is not returned here. +*/ +int +dwarf_get_cie_info(Dwarf_Cie cie, + Dwarf_Unsigned * bytes_in_cie, + Dwarf_Small * ptr_to_version, + char **augmenter, + Dwarf_Unsigned * code_alignment_factor, + Dwarf_Signed * data_alignment_factor, + Dwarf_Half * return_address_register, + Dwarf_Ptr * initial_instructions, + Dwarf_Unsigned * initial_instructions_length, + Dwarf_Error * error) +{ + Dwarf_Debug dbg; + + if (cie == NULL) { + _dwarf_error(NULL, error, DW_DLE_CIE_NULL); + return (DW_DLV_ERROR); + } + + dbg = cie->ci_dbg; + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_CIE_DBG_NULL); + return (DW_DLV_ERROR); + } + + if (ptr_to_version != NULL) + *ptr_to_version = cie->ci_cie_version_number; + if (augmenter != NULL) + *augmenter = cie->ci_augmentation; + if (code_alignment_factor != NULL) + *code_alignment_factor = cie->ci_code_alignment_factor; + if (data_alignment_factor != NULL) + *data_alignment_factor = cie->ci_data_alignment_factor; + if (return_address_register != NULL) + *return_address_register = cie->ci_return_address_register; + if (initial_instructions != NULL) + *initial_instructions = cie->ci_cie_instr_start; + if (initial_instructions_length != NULL) { + *initial_instructions_length = cie->ci_length + + cie->ci_length_size + + cie->ci_extension_size - + (cie->ci_cie_instr_start - cie->ci_cie_start); + + } + *bytes_in_cie = (cie->ci_length); + return (DW_DLV_OK); +} + +/* Return the register rules for all registers at a given pc. +*/ +static int +_dwarf_get_fde_info_for_a_pc_row(Dwarf_Fde fde, + Dwarf_Addr pc_requested, + Dwarf_Frame table, + Dwarf_Half cfa_reg_col_num, + Dwarf_Error * error) +{ + Dwarf_Debug dbg = 0; + Dwarf_Cie cie = 0; + int dw_err = 0; + Dwarf_Sword icount = 0; + int res = 0; + + if (fde == NULL) { + _dwarf_error(NULL, error, DW_DLE_FDE_NULL); + return (DW_DLV_ERROR); + } + + dbg = fde->fd_dbg; + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL); + return (DW_DLV_ERROR); + } + + if (pc_requested < fde->fd_initial_location || + pc_requested >= + fde->fd_initial_location + fde->fd_address_range) { + _dwarf_error(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE); + return (DW_DLV_ERROR); + } + + cie = fde->fd_cie; + if (cie->ci_initial_table == NULL) { + cie->ci_initial_table = _dwarf_get_alloc(dbg, DW_DLA_FRAME, 1); + + if (cie->ci_initial_table == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + _dwarf_init_regrule_table(cie->ci_initial_table->fr_reg, + dbg->de_frame_reg_rules_entry_count, + dbg->de_frame_rule_initial_value); + _dwarf_init_regrule_table(&cie->ci_initial_table->fr_cfa_rule, + 1, dbg->de_frame_rule_initial_value); + res = _dwarf_exec_frame_instr( /* make_instr= */ false, + /* ret_frame_instr= */ NULL, + /* search_pc */ false, + /* search_pc_val */ 0, + /* location */ 0, + cie->ci_cie_instr_start, + cie->ci_cie_instr_start + (cie->ci_length + + cie->ci_length_size + + cie->ci_extension_size - + (cie->ci_cie_instr_start - + cie->ci_cie_start)), + cie->ci_initial_table, cie, dbg, + cfa_reg_col_num, &icount, + &dw_err); + if (res == DW_DLV_ERROR) { + _dwarf_error(dbg, error, dw_err); + return (res); + } else if (res == DW_DLV_NO_ENTRY) { + return res; + } + } + + { + Dwarf_Small *instr_end = fde->fd_fde_instr_start + + fde->fd_length + + fde->fd_length_size + + fde->fd_extension_size - (fde->fd_fde_instr_start - + fde->fd_fde_start); + + res = _dwarf_exec_frame_instr( /* make_instr= */ false, + /* ret_frame_instr= */ NULL, + /* search_pc */ true, + /* search_pc_val */ pc_requested, + fde->fd_initial_location, + fde->fd_fde_instr_start, + instr_end, + table, + cie, dbg, + cfa_reg_col_num, &icount, + &dw_err); + } + if (res == DW_DLV_ERROR) { + _dwarf_error(dbg, error, dw_err); + return (res); + } else if (res == DW_DLV_NO_ENTRY) { + return res; + } + + return DW_DLV_OK; +} + +/* A consumer call for efficiently getting the register info + for all registers in one call. + + The output table rules array is size DW_REG_TABLE_SIZE. + The frame info rules array in fde_table is of size + DW_REG_TABLE_SIZE too. + + This interface really only works well with MIPS/IRIX + where DW_FRAME_CFA_COL is zero (in that case it's safe). + + It is also restricted to the case where + DW_REG_TABLE_SIZE == DW_FRAME_LAST_REG_NUM == + dbg->de_frame_reg_rules_entry_count (true for MIPS/IRIX). + If this condition is not met calling this routine can result in + incorrect output or in memory corruption. + + It is much better to use dwarf_get_fde_info_for_all_regs3() + instead of this interface. +*/ +int +dwarf_get_fde_info_for_all_regs(Dwarf_Fde fde, + Dwarf_Addr pc_requested, + Dwarf_Regtable * reg_table, + Dwarf_Addr * row_pc, + Dwarf_Error * error) +{ + + /* Table size: DW_REG_TABLE_SIZE */ + struct Dwarf_Frame_s fde_table; + Dwarf_Sword i = 0; + struct Dwarf_Reg_Rule_s *rule = NULL; + struct Dwarf_Regtable_Entry_s *out_rule = NULL; + int res = 0; + Dwarf_Debug dbg = 0; + + /* For this interface the size is fixed at compile time. */ + int output_table_real_data_size = DW_REG_TABLE_SIZE; + + FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); + + res = dwarf_initialize_fde_table(dbg, &fde_table, + output_table_real_data_size, + error); + if (res != DW_DLV_OK) + return res; + + /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks + */ + res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, + &fde_table, dbg->de_frame_cfa_col_number, error); + if (res != DW_DLV_OK) { + dwarf_free_fde_table(&fde_table); + return res; + } + + out_rule = ®_table->rules[0]; + rule = &fde_table.fr_reg[0]; + for (i = 0; i < output_table_real_data_size; + i++, ++out_rule, ++rule) { + out_rule->dw_offset_relevant = rule->ru_is_off; + out_rule->dw_value_type = rule->ru_value_type; + out_rule->dw_regnum = rule->ru_register; + out_rule->dw_offset = rule->ru_offset_or_block_len; + } + for (; i < DW_REG_TABLE_SIZE; ++i, ++out_rule) { + out_rule->dw_offset_relevant = 0; + out_rule->dw_value_type = DW_EXPR_OFFSET; + out_rule->dw_regnum = dbg->de_frame_undefined_value_number; + out_rule->dw_offset = 0; + } + + /* The test is just in case it's not inside the table. For non-MIPS + it could be outside the table and that is just fine, it was + really a mistake to put it in the table in 1993. */ + /* CONSTCOND */ + if (dbg->de_frame_cfa_col_number < DW_REG_TABLE_SIZE) { + out_rule = ®_table->rules[dbg->de_frame_cfa_col_number]; + out_rule->dw_offset_relevant = fde_table.fr_cfa_rule.ru_is_off; + out_rule->dw_value_type = fde_table.fr_cfa_rule.ru_value_type; + out_rule->dw_regnum = fde_table.fr_cfa_rule.ru_register; + out_rule->dw_offset = + fde_table.fr_cfa_rule.ru_offset_or_block_len; + } + + if (row_pc != NULL) + *row_pc = fde_table.fr_loc; + dwarf_free_fde_table(&fde_table); + return DW_DLV_OK; +} + +/* A consumer call for efficiently getting the register info + for all registers in one call. + + The output table rules array is size output_table_real_data_size. + (normally DW_REG_TABLE_SIZE). + The frame info rules array in fde_table is normally of size + DW_FRAME_LAST_REG_NUM. +*/ +int +dwarf_get_fde_info_for_all_regs3(Dwarf_Fde fde, + Dwarf_Addr pc_requested, + Dwarf_Regtable3 * reg_table, + Dwarf_Addr * row_pc, + Dwarf_Error * error) +{ + + struct Dwarf_Frame_s fde_table; + Dwarf_Sword i = 0; + int res = 0; + struct Dwarf_Reg_Rule_s *rule = NULL; + struct Dwarf_Regtable_Entry3_s *out_rule = NULL; + Dwarf_Debug dbg = 0; + int output_table_real_data_size = reg_table->rt3_reg_table_size; + + FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); + + output_table_real_data_size = + MIN(output_table_real_data_size, + dbg->de_frame_reg_rules_entry_count); + + res = dwarf_initialize_fde_table(dbg, &fde_table, + output_table_real_data_size, + error); + + /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks + */ + res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, + &fde_table, + dbg->de_frame_cfa_col_number, + error); + if (res != DW_DLV_OK) { + dwarf_free_fde_table(&fde_table); + return res; + } + + out_rule = ®_table->rt3_rules[0]; + rule = &fde_table.fr_reg[0]; + for (i = 0; i < output_table_real_data_size; + i++, ++out_rule, ++rule) { + out_rule->dw_offset_relevant = rule->ru_is_off; + out_rule->dw_value_type = rule->ru_value_type; + out_rule->dw_regnum = rule->ru_register; + out_rule->dw_offset_or_block_len = rule->ru_offset_or_block_len; + out_rule->dw_block_ptr = rule->ru_block; + } + for (; i < reg_table->rt3_reg_table_size; i++, ++out_rule) { + out_rule->dw_offset_relevant = 0; + out_rule->dw_value_type = DW_EXPR_OFFSET; + out_rule->dw_regnum = dbg->de_frame_undefined_value_number; + out_rule->dw_offset_or_block_len = 0; + out_rule->dw_block_ptr = 0; + } + reg_table->rt3_cfa_rule.dw_offset_relevant = + fde_table.fr_cfa_rule.ru_is_off; + reg_table->rt3_cfa_rule.dw_value_type = + fde_table.fr_cfa_rule.ru_value_type; + reg_table->rt3_cfa_rule.dw_regnum = + fde_table.fr_cfa_rule.ru_register; + reg_table->rt3_cfa_rule.dw_offset_or_block_len = + fde_table.fr_cfa_rule.ru_offset_or_block_len; + reg_table->rt3_cfa_rule.dw_block_ptr = + fde_table.fr_cfa_rule.ru_block; + + if (row_pc != NULL) + *row_pc = fde_table.fr_loc; + + dwarf_free_fde_table(&fde_table); + return DW_DLV_OK; +} + + +/* Gets the register info for a single register at a given PC value + for the FDE specified. + + This is the old MIPS interface and should no longer be used. + Use dwarf_get_fde_info_for_reg3() instead. +*/ +int +dwarf_get_fde_info_for_reg(Dwarf_Fde fde, + Dwarf_Half table_column, + Dwarf_Addr pc_requested, + Dwarf_Signed * offset_relevant, + Dwarf_Signed * register_num, + Dwarf_Signed * offset, + Dwarf_Addr * row_pc, Dwarf_Error * error) +{ + struct Dwarf_Frame_s fde_table; + int res = DW_DLV_ERROR; + Dwarf_Debug dbg = 0; + int output_table_real_data_size = 0; + + FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); + output_table_real_data_size = dbg->de_frame_reg_rules_entry_count; + + res = dwarf_initialize_fde_table(dbg, &fde_table, + output_table_real_data_size, + error); + if (res != DW_DLV_OK) + return res; + + if (table_column >= output_table_real_data_size) { + dwarf_free_fde_table(&fde_table); + _dwarf_error(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD); + return (DW_DLV_ERROR); + } + + /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks + */ + res = + _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table, + dbg->de_frame_cfa_col_number, error); + if (res != DW_DLV_OK) { + dwarf_free_fde_table(&fde_table); + return res; + } + + if (fde_table.fr_reg[table_column].ru_value_type != DW_EXPR_OFFSET) { + /* The problem here is that this interface cannot deal with + other sorts of (newer) dwarf frame values. Code must + use dwarf_get_fde_info_for_reg3() to get these + values correctly. We error rather than return + misleading incomplete data. */ + dwarf_free_fde_table(&fde_table); + _dwarf_error(NULL, error, + DW_DLE_FRAME_REGISTER_UNREPRESENTABLE); + return (DW_DLV_ERROR); + } + if(table_column == dbg->de_frame_cfa_col_number) { + if (register_num != NULL) + *register_num = fde_table.fr_cfa_rule.ru_register; + if (offset != NULL) + *offset = fde_table.fr_cfa_rule.ru_offset_or_block_len; + if (row_pc != NULL) + *row_pc = fde_table.fr_loc; + *offset_relevant = fde_table.fr_cfa_rule.ru_is_off; + + } else { + if (register_num != NULL) + *register_num = fde_table.fr_reg[table_column].ru_register; + if (offset != NULL) + *offset = fde_table.fr_reg[table_column].ru_offset_or_block_len; + if (row_pc != NULL) + *row_pc = fde_table.fr_loc; + + *offset_relevant = fde_table.fr_reg[table_column].ru_is_off; + } + dwarf_free_fde_table(&fde_table); + return DW_DLV_OK; +} + +/* In this interface, table_column of DW_FRAME_CFA_COL + is not meaningful. + Use dwarf_get_fde_info_for_cfa_reg3() to get the CFA. + Call dwarf_set_frame_cfa_value() to set the correct column + after calling dwarf_init() + (DW_FRAME_CFA_COL3 is a sensible column to use). +*/ +int +dwarf_get_fde_info_for_reg3(Dwarf_Fde fde, + Dwarf_Half table_column, + Dwarf_Addr pc_requested, + Dwarf_Small * value_type, + Dwarf_Signed * offset_relevant, + Dwarf_Signed * register_num, + Dwarf_Signed * offset_or_block_len, + Dwarf_Ptr * block_ptr, + Dwarf_Addr * row_pc_out, + Dwarf_Error * error) +{ + struct Dwarf_Frame_s fde_table; + int res = DW_DLV_ERROR; + + Dwarf_Debug dbg = 0; + int table_real_data_size = 0; + + FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); + table_real_data_size = dbg->de_frame_reg_rules_entry_count; + res = dwarf_initialize_fde_table(dbg, &fde_table, + table_real_data_size, error); + if (res != DW_DLV_OK) + return res; + if (table_column >= table_real_data_size) { + dwarf_free_fde_table(&fde_table); + _dwarf_error(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD); + return (DW_DLV_ERROR); + } + + /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks + */ + res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table, + dbg->de_frame_cfa_col_number, + error); + if (res != DW_DLV_OK) { + dwarf_free_fde_table(&fde_table); + return res; + } + + if (register_num != NULL) + *register_num = fde_table.fr_reg[table_column].ru_register; + if (offset_or_block_len != NULL) + *offset_or_block_len = + fde_table.fr_reg[table_column].ru_offset_or_block_len; + if (row_pc_out != NULL) + *row_pc_out = fde_table.fr_loc; + if (block_ptr) + *block_ptr = fde_table.fr_reg[table_column].ru_block; + + /* Without value_type the data cannot be understood, so we insist + on it being present, we don't test it. */ + *value_type = fde_table.fr_reg[table_column].ru_value_type; + *offset_relevant = (fde_table.fr_reg[table_column].ru_is_off); + dwarf_free_fde_table(&fde_table); + return DW_DLV_OK; + +} + +/* For latest DWARF, this is the preferred interface. + It more portably deals with the CFA by not + making the CFA a column number, which means + DW_FRAME_CFA_COL3 becomes, like DW_CFA_SAME_VALUE, + a special value, not something one uses as an index. + + Call dwarf_set_frame_cfa_value() to set the correct column + after calling dwarf_init() + (DW_FRAME_CFA_COL3 is a sensible column to use, and + is the default unless '--enable-oldframecol' + is used to configure libdwarf). */ +int +dwarf_get_fde_info_for_cfa_reg3(Dwarf_Fde fde, + Dwarf_Addr pc_requested, + Dwarf_Small * value_type, + Dwarf_Signed * offset_relevant, + Dwarf_Signed * register_num, + Dwarf_Signed * offset_or_block_len, + Dwarf_Ptr * block_ptr, + Dwarf_Addr * row_pc_out, + Dwarf_Error * error) +{ + struct Dwarf_Frame_s fde_table; + int res = DW_DLV_ERROR; + Dwarf_Debug dbg = 0; + + int table_real_data_size = 0; + + FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); + + table_real_data_size = dbg->de_frame_reg_rules_entry_count; + res = dwarf_initialize_fde_table(dbg, &fde_table, + table_real_data_size, error); + if (res != DW_DLV_OK) + return res; + res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table, + dbg->de_frame_cfa_col_number,error); + if (res != DW_DLV_OK) { + dwarf_free_fde_table(&fde_table); + return res; + } + + if (register_num != NULL) + *register_num = fde_table.fr_cfa_rule.ru_register; + if (offset_or_block_len != NULL) + *offset_or_block_len = + fde_table.fr_cfa_rule.ru_offset_or_block_len; + if (row_pc_out != NULL) + *row_pc_out = fde_table.fr_loc; + if (block_ptr) + *block_ptr = fde_table.fr_cfa_rule.ru_block; + + /* Without value_type the data cannot be understood, so we insist + on it being present, we don't test it. */ + *value_type = fde_table.fr_cfa_rule.ru_value_type; + *offset_relevant = fde_table.fr_cfa_rule.ru_is_off; + dwarf_free_fde_table(&fde_table); + return DW_DLV_OK; +} + + + +/* + Return pointer to the instructions in the dwarf + fde. +*/ +int +dwarf_get_fde_instr_bytes(Dwarf_Fde inFde, Dwarf_Ptr * outinstraddr, + Dwarf_Unsigned * outaddrlen, + Dwarf_Error * error) +{ + Dwarf_Unsigned len = 0; + unsigned char *instrs = 0; + Dwarf_Debug dbg = 0; + + if (inFde == NULL) { + _dwarf_error(dbg, error, DW_DLE_FDE_NULL); + return (DW_DLV_ERROR); + } + + dbg = inFde->fd_dbg; + if (dbg == NULL) { + _dwarf_error(dbg, error, DW_DLE_FDE_DBG_NULL); + return (DW_DLV_ERROR); + } + + instrs = inFde->fd_fde_instr_start; + + len = (inFde->fd_fde_start + inFde->fd_length + + inFde->fd_length_size + inFde->fd_extension_size) - instrs; + + *outinstraddr = instrs; + *outaddrlen = len; + return DW_DLV_OK; +} + +/* Allows getting an fde from its table via an index. + With more error checking than simply indexing oneself. +*/ +int +dwarf_get_fde_n(Dwarf_Fde * fde_data, + Dwarf_Unsigned fde_index, + Dwarf_Fde * returned_fde, Dwarf_Error * error) +{ + Dwarf_Debug dbg = 0; + Dwarf_Signed fdecount = 0; + + if (fde_data == NULL) { + _dwarf_error(dbg, error, DW_DLE_FDE_PTR_NULL); + return (DW_DLV_ERROR); + } + + FDE_NULL_CHECKS_AND_SET_DBG(*fde_data, dbg); + /* Assumes fde_data table has at least one entry. */ + fdecount = fde_data[0]->fd_is_eh? + dbg->de_fde_count_eh:dbg->de_fde_count; + if (fde_index >= fdecount) { + return (DW_DLV_NO_ENTRY); + } + *returned_fde = (*(fde_data + fde_index)); + return DW_DLV_OK; +} + + +/* + Lopc and hipc are extensions to the interface to + return the range of addresses that are described + by the returned fde. +*/ +int +dwarf_get_fde_at_pc(Dwarf_Fde * fde_data, + Dwarf_Addr pc_of_interest, + Dwarf_Fde * returned_fde, + Dwarf_Addr * lopc, + Dwarf_Addr * hipc, Dwarf_Error * error) +{ + Dwarf_Debug dbg = NULL; + Dwarf_Fde fde = NULL; + Dwarf_Fde entryfde = NULL; + Dwarf_Signed fdecount = 0; + + if (fde_data == NULL) { + _dwarf_error(NULL, error, DW_DLE_FDE_PTR_NULL); + return (DW_DLV_ERROR); + } + + /* Assumes fde_data table has at least one entry. */ + entryfde = *fde_data; + FDE_NULL_CHECKS_AND_SET_DBG(entryfde, dbg); + + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL); + return (DW_DLV_ERROR); + } + fdecount = entryfde->fd_is_eh? + dbg->de_fde_count_eh:dbg->de_fde_count; + { + /* The fde's are sorted by their addresses. Binary search to + find correct fde. */ + Dwarf_Signed low = 0; + Dwarf_Signed high = fdecount - 1L; + Dwarf_Signed middle = 0; + Dwarf_Fde cur_fde; + + while (low <= high) { + middle = (low + high) / 2; + cur_fde = fde_data[middle]; + if (pc_of_interest < cur_fde->fd_initial_location) { + high = middle - 1; + } else if (pc_of_interest >= + (cur_fde->fd_initial_location + + cur_fde->fd_address_range)) { + low = middle + 1; + } else { + fde = fde_data[middle]; + break; + } + } + } + + if (fde) { + if (lopc != NULL) + *lopc = fde->fd_initial_location; + if (hipc != NULL) + *hipc = + fde->fd_initial_location + fde->fd_address_range - 1; + *returned_fde = fde; + return (DW_DLV_OK); + } + + return (DW_DLV_NO_ENTRY); +} + + +/* Expands a single frame instruction block + from a specific cie + into a n array of Dwarf_Frame_Op-s. + This depends on having the cfa column set sensibly. + + Call dwarf_set_frame_cfa_value() to set the correct column + after calling dwarf_init() unless you are using + the old MIPS frame interfaces (in which case the default + will be ok). (DW_FRAME_CFA_COL3 is a sensible column to use ). +*/ +int +dwarf_expand_frame_instructions(Dwarf_Cie cie, + Dwarf_Ptr instruction, + Dwarf_Unsigned i_length, + Dwarf_Frame_Op ** returned_op_list, + Dwarf_Signed * returned_op_count, + Dwarf_Error * error) +{ + Dwarf_Sword instr_count; + int res = DW_DLV_ERROR; + int dw_err; + Dwarf_Debug dbg = 0; + + if (cie == 0) { + _dwarf_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + dbg = cie->ci_dbg; + + if (returned_op_list == 0 || returned_op_count == 0) { + _dwarf_error(dbg, error, DW_DLE_RET_OP_LIST_NULL); + return (DW_DLV_ERROR); + } + + /* The cast to Dwarf_Ptr may get a compiler warning, but it is safe + as it is just an i_length offset from 'instruction' itself. A + caller has made a big mistake if the result is not a valid + pointer. */ + res = _dwarf_exec_frame_instr( /* make_instr= */ true, + returned_op_list, + /* search_pc */ false, + /* search_pc_val */ 0, + /* location */ 0, + instruction, + (Dwarf_Ptr)((char *)instruction + i_length), + /* Dwarf_Frame */ NULL, + cie, + dbg, + dbg->de_frame_cfa_col_number, &instr_count, + &dw_err); + if (res != DW_DLV_OK) { + if (res == DW_DLV_ERROR) { + _dwarf_error(dbg, error, dw_err); + } + return (res); + } + + *returned_op_count = instr_count; + return DW_DLV_OK; +} + + +/* Used by dwarfdump -v to print offsets, for debugging + dwarf info. + The dwarf_ version is preferred over the obsolete _dwarf version. + _dwarf version kept for compatibility. +*/ +/* ARGSUSED 4 */ +int +_dwarf_fde_section_offset(Dwarf_Debug dbg, Dwarf_Fde in_fde, + Dwarf_Off * fde_off, Dwarf_Off * cie_off, + Dwarf_Error * err) +{ + return dwarf_fde_section_offset(dbg,in_fde,fde_off, + cie_off,err); +} +/* ARGSUSED 4 */ +int +dwarf_fde_section_offset(Dwarf_Debug dbg, Dwarf_Fde in_fde, + Dwarf_Off * fde_off, Dwarf_Off * cie_off, + Dwarf_Error * err) +{ + char *start = 0; + char *loc = 0; + + + + start = (char *) in_fde->fd_section_ptr; + loc = (char *) in_fde->fd_fde_start; + + *fde_off = (loc - start); + *cie_off = in_fde->fd_cie_offset; + return DW_DLV_OK; +} + +/* Used by dwarfdump -v to print offsets, for debugging + dwarf info. + The dwarf_ version is preferred over the obsolete _dwarf version. + _dwarf version kept for compatibility. +*/ +/* ARGSUSED 4 */ +int +_dwarf_cie_section_offset(Dwarf_Debug dbg, Dwarf_Cie in_cie, + Dwarf_Off * cie_off, Dwarf_Error * err) +{ + return dwarf_cie_section_offset(dbg,in_cie,cie_off,err); +} +/* ARGSUSED 4 */ +int +dwarf_cie_section_offset(Dwarf_Debug dbg, Dwarf_Cie in_cie, + Dwarf_Off * cie_off, Dwarf_Error * err) +{ + char *start = 0; + char *loc = 0; + + start = (char *) in_cie->ci_section_ptr; + loc = (char *) in_cie->ci_cie_start; + + *cie_off = (loc - start); + return DW_DLV_OK; +} + +/* Returns a pointer to target-specific augmentation data thru augdata + and returns the length of the data thru augdata_len. + + It's up to the consumer code to know how to interpret the bytes + of target-specific data (endian issues apply too, these + are just raw bytes pointed to). + See Linux Standard Base Core Specification version 3.0 for + the details on .eh_frame info. + + Returns DW_DLV_ERROR if fde is NULL or some other serious + error. + Returns DW_DLV_NO_ENTRY if there is no target-specific + augmentation data. + + The bytes pointed to are in the Dwarf_Cie, and as long as that + is valid the bytes are there. No 'dealloc' call is needed + for the bytes. +*/ +int +dwarf_get_cie_augmentation_data(Dwarf_Cie cie, + Dwarf_Small ** augdata, + Dwarf_Unsigned * augdata_len, + Dwarf_Error * error) +{ + if (cie == NULL) { + _dwarf_error(NULL, error, DW_DLE_CIE_NULL); + return (DW_DLV_ERROR); + } + if (cie->ci_gnu_eh_augmentation_len == 0) { + return DW_DLV_NO_ENTRY; + } + *augdata = (Dwarf_Small *) (cie->ci_gnu_eh_augmentation_bytes); + *augdata_len = cie->ci_gnu_eh_augmentation_len; + return DW_DLV_OK; +} + + +/* Returns a pointer to target-specific augmentation data thru augdata + and returns the length of the data thru augdata_len. + + It's up to the consumer code to know how to interpret the bytes + of target-specific data (endian issues apply too, these + are just raw bytes pointed to). + See Linux Standard Base Core Specification version 3.0 for + the details on .eh_frame info. + + Returns DW_DLV_ERROR if fde is NULL or some other serious + error. + Returns DW_DLV_NO_ENTRY if there is no target-specific + augmentation data. + + The bytes pointed to are in the Dwarf_Fde, and as long as that + is valid the bytes are there. No 'dealloc' call is needed + for the bytes. + +*/ +int +dwarf_get_fde_augmentation_data(Dwarf_Fde fde, + Dwarf_Small * *augdata, + Dwarf_Unsigned * augdata_len, + Dwarf_Error * error) +{ + Dwarf_Cie cie = 0; + + if (fde == NULL) { + _dwarf_error(NULL, error, DW_DLE_FDE_NULL); + return (DW_DLV_ERROR); + } + cie = fde->fd_cie; + if (cie == NULL) { + _dwarf_error(NULL, error, DW_DLE_CIE_NULL); + return (DW_DLV_ERROR); + } + if (cie->ci_gnu_eh_augmentation_len == 0) { + return DW_DLV_NO_ENTRY; + } + *augdata = (Dwarf_Small *) fde->fd_gnu_eh_augmentation_bytes; + *augdata_len = fde->fd_gnu_eh_augmentation_len; + return DW_DLV_OK; +} + + +/* Initialize with same_value , a value which makes sense + for IRIX/MIPS. + The correct value to use is ABI dependent. + For register-windows machines most + or all registers should get DW_FRAME_UNDEFINED_VAL as the + correct initial value. + Some think DW_FRAME_UNDEFINED_VAL is always the + right value. + + For some ABIs a setting which varies by register + would be more appropriate. + + FIXME. */ + +static void +_dwarf_init_regrule_table(struct Dwarf_Reg_Rule_s *t1reg, + int last_reg_num, int initial_value) +{ + struct Dwarf_Reg_Rule_s *t1end = t1reg + last_reg_num; + + for (; t1reg < t1end; t1reg++) { + t1reg->ru_is_off = 0; + t1reg->ru_value_type = DW_EXPR_OFFSET; + t1reg->ru_register = initial_value; + t1reg->ru_offset_or_block_len = 0; + t1reg->ru_block = 0; + } +} + +#if 0 +/* Used solely for debugging libdwarf. */ +static void +dump_frame_rule(char *msg, struct Dwarf_Reg_Rule_s *reg_rule) +{ + printf + ("%s type %s (" DW_PR_DUx "), is_off " + DW_PR_DUu " reg " DW_PR_DUu " offset " DW_PR_DUx " blockp " + DW_PR_DUx "\n", + msg, + (reg_rule->ru_value_type == DW_EXPR_OFFSET) ? + "DW_EXPR_OFFSET" : + (reg_rule->ru_value_type == DW_EXPR_VAL_OFFSET) ? + "DW_EXPR_VAL_OFFSET" : + (reg_rule->ru_value_type == DW_EXPR_VAL_EXPRESSION) ? + "DW_EXPR_VAL_EXPRESSION" : + (reg_rule->ru_value_type == DW_EXPR_EXPRESSION) ? + "DW_EXPR_EXPRESSION" : "Unknown", + (Dwarf_Unsigned) reg_rule->ru_value_type, + (Dwarf_Unsigned) reg_rule->ru_is_off, + (Dwarf_Unsigned) reg_rule->ru_register, + (Dwarf_Unsigned) reg_rule->ru_offset_or_block_len, + (Dwarf_Unsigned) reg_rule->ru_block); + return; +} +#endif + +/* This allows consumers to set the 'initial value' so that + an ISA/ABI specific default can be used, dynamically, + at run time. Useful for dwarfdump and non-MIPS architectures.. + The value defaults to one of + DW_FRAME_SAME_VALUE or DW_FRAME_UNKNOWN_VALUE + but dwarfdump can dump multiple ISA/ABI objects so + we may want to get this set to what the ABI says is correct. + + Returns the value that was present before we changed it here. +*/ +Dwarf_Half +dwarf_set_frame_rule_initial_value(Dwarf_Debug dbg, Dwarf_Half value) +{ + Dwarf_Half orig = dbg->de_frame_rule_initial_value; + dbg->de_frame_rule_initial_value = value; + return orig; +} + +/* The following spelling for backwards compatibility. */ +Dwarf_Half +dwarf_set_frame_rule_inital_value(Dwarf_Debug dbg, Dwarf_Half value) +{ + return dwarf_set_frame_rule_initial_value(dbg,value); +} + +/* This allows consumers to set the array size of the reg rules + table so that + an ISA/ABI specific value can be used, dynamically, + at run time. Useful for non-MIPS archtectures. + The value defaults to DW_FRAME_LAST_REG_NUM. + but dwarfdump can dump multiple ISA/ABI objects so + consumers want to get this set to what the ABI says is correct. + + Returns the value that was present before we changed it here. +*/ + +Dwarf_Half +dwarf_set_frame_rule_table_size(Dwarf_Debug dbg, Dwarf_Half value) +{ + Dwarf_Half orig = dbg->de_frame_reg_rules_entry_count; + dbg->de_frame_reg_rules_entry_count = value; + return orig; +} +/* This allows consumers to set the CFA register value + * so that an ISA/ABI specific value can be used, dynamically, + * at run time. Useful for non-MIPS archtectures. + * The value defaults to DW_FRAME_CFA_COL3 and should be + * higher than any real register in the ABI. + * Dwarfdump can dump multiple ISA/ABI objects so + * consumers want to get this set to what the ABI says is correct. + + * Returns the value that was present before we changed it here. + * */ + +Dwarf_Half +dwarf_set_frame_cfa_value(Dwarf_Debug dbg, Dwarf_Half value) +{ + Dwarf_Half orig = dbg->de_frame_cfa_col_number; + dbg->de_frame_cfa_col_number = value; + return orig; +} +/* Similar to above, but for the other crucial fields for frames. */ +Dwarf_Half +dwarf_set_frame_same_value(Dwarf_Debug dbg, Dwarf_Half value) +{ + Dwarf_Half orig = dbg->de_frame_same_value_number; + dbg->de_frame_same_value_number = value; + return orig; +} +Dwarf_Half +dwarf_set_frame_undefined_value(Dwarf_Debug dbg, Dwarf_Half value) +{ + Dwarf_Half orig = dbg->de_frame_same_value_number; + dbg->de_frame_undefined_value_number = value; + return orig; +} + + + + + +static int +dwarf_initialize_fde_table(Dwarf_Debug dbg, + struct Dwarf_Frame_s *fde_table, + unsigned table_real_data_size, + Dwarf_Error * error) +{ + unsigned entry_size = sizeof(struct Dwarf_Frame_s); + + fde_table->fr_loc = 0; + fde_table->fr_reg_count = table_real_data_size; + fde_table->fr_next = 0; + + fde_table->fr_reg = (struct Dwarf_Reg_Rule_s *) + calloc(entry_size, table_real_data_size); + if (fde_table->fr_reg == 0) { + _dwarf_error(dbg, error, DW_DLE_DF_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + return DW_DLV_OK; + +} +static void +dwarf_free_fde_table(struct Dwarf_Frame_s *fde_table) +{ + free(fde_table->fr_reg); + fde_table->fr_reg_count = 0; + fde_table->fr_reg = 0; +} + + +/* Return DW_DLV_OK if we succeed. else return DW_DLV_ERROR. +*/ +int +_dwarf_frame_constructor(Dwarf_Debug dbg, void *frame) +{ + struct Dwarf_Frame_s *fp = frame; + + if (!dbg) { + return DW_DLV_ERROR; + } + + fp->fr_reg = calloc(dbg->de_frame_reg_rules_entry_count, + sizeof(struct Dwarf_Reg_Rule_s)); + if (!fp->fr_reg) { + return DW_DLV_ERROR; + } + fp->fr_reg_count = dbg->de_frame_reg_rules_entry_count; + return DW_DLV_OK; +} + +void +_dwarf_frame_destructor(void *frame) +{ + struct Dwarf_Frame_s *fp = frame; + + if (fp->fr_reg) { + free(fp->fr_reg); + } + fp->fr_reg = 0; + fp->fr_reg_count = 0; +} diff --git a/usr/src/lib/libdwarf/common/dwarf_frame.h b/usr/src/lib/libdwarf/common/dwarf_frame.h new file mode 100644 index 0000000000..ceb686335b --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_frame.h @@ -0,0 +1,421 @@ +/* + + Copyright (C) 2000, 2004, 2006 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +/* The dwarf 2.0 standard dictates that only the following + * fields can be read when an unexpected augmentation string + * (in the cie) is encountered: CIE length, CIE_id, version and + * augmentation; FDE: length, CIE pointer, initial location and + * address range. Unfortunately, with the above restrictions, it + * is impossible to read the instruction table from a CIE or a FDE + * when a new augmentation string is encountered. + * To fix this problem, the following layout is used, if the + * augmentation string starts with the string "z". + * CIE FDE + * length length + * CIE_id CIE_pointer + * version initial_location + * augmentation address_range + * length_of_augmented_fields (*NEW*) + * code_alignment_factor Any new fields as necessary + * data_alignment_factor instruction_table + * return_address + * length_of_augmented fields + * Any new fields as necessary + * initial_instructions + * + * The type of all the old data items are the same as what is + * described in dwarf 2.0 standard. The length_of_augmented_fields + * is an LEB128 data item that denotes the size (in bytes) of + * the augmented fields (not including the size of + * "length_of_augmented_fields" itself). + + * Handling of cie augmentation strings is necessarly a heuristic. + * See dwarf_frame.c for the currently known augmentation strings. + + + ---START SGI-ONLY COMMENT: + * SGI-IRIX versions of cie or fde were intended to use "z1", "z2" as the + * augmenter strings if required for new augmentation. + * However, that never happened (as of March 2005). + * + * The fde's augmented by the string "z" have a new field + * (signed constant, 4 byte field) + * called offset_into_exception_tables, following the + * length_of_augmented field. This field contains an offset + * into the "_MIPS_eh_region", which describes + * the IRIX CC exception handling tables. + ---END SGI-ONLY COMMENT + + + * GNU .eh_frame has an augmentation string of z[RLP]* (gcc 3.4) + * The similarity to IRIX 'z' (and proposed but never + * implemented IRIX z1, z2 etc) was confusing things. + * If the section is .eh_frame then 'z' means GNU exception + * information 'Augmentation Data' not IRIX 'z'. + * See The Linux Standard Base Core Specification version 3.0 + */ + +#define DW_DEBUG_FRAME_VERSION 1 /* DWARF2 */ +#define DW_DEBUG_FRAME_VERSION3 3 /* DWARF3 */ +#define DW_DEBUG_FRAME_VERSION4 4 /* DWARF4 */ +/* The following is SGI/IRIX specific, and probably no longer + in use anywhere. */ +#define DW_DEBUG_FRAME_AUGMENTER_STRING "mti v1" + +/* The value of the offset field for Cie's. */ +#define DW_CIE_OFFSET ~(0x0) + +/* The augmentation string may be NULL. */ +#define DW_EMPTY_STRING "" + +#define DW_FRAME_INSTR_OPCODE_SHIFT 6 +#define DW_FRAME_INSTR_OFFSET_MASK 0x3f + +/* + This struct denotes the rule for a register in a row of + the frame table. In other words, it is one element of + the table. +*/ +struct Dwarf_Reg_Rule_s { + + /* + Is a flag indicating whether the rule includes the offset + field, ie whether the ru_offset field is valid or not. + Applies only if DW_EXPR_OFFSET or DW_EXPR_VAL_OFFSET. + It is important, since reg+offset (offset of 0) is different from + just 'register' since the former means 'read memory at address + given by the sum of register contents plus offset to get the + value'. whereas the latter means 'the value is in the register'. + + The 'register' numbers are either real registers (ie, table + columns defined as real registers) or defined entries that are + not really hardware registers, such as DW_FRAME_SAME_VAL or + DW_FRAME_CFA_COL. + + */ + Dwarf_Sbyte ru_is_off; + + /* DW_EXPR_OFFSET (0, DWARF2) + DW_EXPR_VAL_OFFSET 1 (dwarf2/3) + DW_EXPR_EXPRESSION 2 (dwarf2/3) + DW_EXPR_VAL_EXPRESSION 3 (dwarf2/3) + See dwarf_frame.h. */ + Dwarf_Sbyte ru_value_type; + + /* Register involved in this rule. */ + Dwarf_Half ru_register; + + /* Offset to add to register, if indicated by ru_is_offset + and if DW_EXPR_OFFSET or DW_EXPR_VAL_OFFSET. + If DW_EXPR_EXPRESSION or DW_EXPR_VAL_EXPRESSION + this is DW_FORM_block block-length, not offset. */ + Dwarf_Unsigned ru_offset_or_block_len; + + /* For DW_EXPR_EXPRESSION DW_EXPR_VAL_EXPRESSION these is set, + else 0. */ + Dwarf_Small *ru_block; +}; + +typedef struct Dwarf_Frame_s *Dwarf_Frame; + +/* + This structure represents a row of the frame table. + Fr_loc is the pc value for this row, and Fr_reg + contains the rule for each column. + + Entry DW_FRAME_CFA_COL of fr_reg was the tradional MIPS + way of setting CFA. cfa_rule is the new one. +*/ +struct Dwarf_Frame_s { + + /* Pc value corresponding to this row of the frame table. */ + Dwarf_Addr fr_loc; + + /* Rules for all the registers in this row. */ + struct Dwarf_Reg_Rule_s fr_cfa_rule; + + /* fr_reg_count is the the number of + entries of the fr_reg array. */ + unsigned long fr_reg_count; + struct Dwarf_Reg_Rule_s *fr_reg; + + Dwarf_Frame fr_next; +}; + +typedef struct Dwarf_Frame_Op_List_s *Dwarf_Frame_Op_List; + +/* This is used to chain together Dwarf_Frame_Op structures. */ +struct Dwarf_Frame_Op_List_s { + Dwarf_Frame_Op *fl_frame_instr; + Dwarf_Frame_Op_List fl_next; +}; + +/* See dwarf_frame.c for the heuristics used to set the + Dwarf_Cie ci_augmentation_type. + + This succinctly helps interpret the size and meaning of .debug_frame + and (for gcc) .eh_frame. + + In the case of gcc .eh_frame (gcc 3.3, 3.4) + z may be followed by one or more of + L R P. + +*/ +enum Dwarf_augmentation_type { + aug_empty_string, /* Default empty augmentation string. */ + aug_irix_exception_table, /* IRIX plain "z", + for exception handling, IRIX CC compiler. + Proposed z1 z2 ... never implemented. */ + aug_gcc_eh_z, /* gcc z augmentation, (including + L R P variations). gcc 3.3 3.4 exception + handling in eh_frame. */ + aug_irix_mti_v1, /* IRIX "mti v1" augmentation string. Probably + never in any released SGI-IRIX compiler. */ + aug_eh, /* For gcc .eh_frame, "eh" is the string., + gcc 1,2, egcs. Older values. */ + aug_armcc, /* "armcc+" meaning the cfa calculation + is corrected to be standard (output by + Arm C RVCT 3.0 SP1 and later). See + http://sourceware.org/ml/gdb-patches/2006-12/msg00249.html + for details. */ + aug_unknown, /* Unknown augmentation, we cannot do much. */ + aug_past_last +}; + + +/* + This structure contains all the pertinent info for a Cie. Most + of the fields are taken straight from the definition of a Cie. + Ci_cie_start points to the address (in .debug_frame) where this + Cie begins. Ci_cie_instr_start points to the first byte of the + frame instructions for this Cie. Ci_dbg points to the associated + Dwarf_Debug structure. Ci_initial_table is a pointer to the table + row generated by the instructions for this Cie. +*/ +struct Dwarf_Cie_s { + Dwarf_Unsigned ci_length; + char *ci_augmentation; + Dwarf_Small ci_code_alignment_factor; + Dwarf_Sbyte ci_data_alignment_factor; + Dwarf_Small ci_return_address_register; + Dwarf_Small *ci_cie_start; + Dwarf_Small *ci_cie_instr_start; + Dwarf_Debug ci_dbg; + Dwarf_Frame ci_initial_table; + Dwarf_Cie ci_next; + Dwarf_Small ci_length_size; + Dwarf_Small ci_extension_size; + Dwarf_Half ci_cie_version_number; + enum Dwarf_augmentation_type ci_augmentation_type; + + /* The following 2 for GNU .eh_frame exception handling + Augmentation Data. Set if ci_augmentation_type + is aug_gcc_eh_z. Zero if unused. */ + Dwarf_Unsigned ci_gnu_eh_augmentation_len; + Dwarf_Ptr ci_gnu_eh_augmentation_bytes; + + /* These are extracted from the gnu eh_frame + augmentation if the + augmentation begins with 'z'. See Linux LSB documents. + Otherwize these are zero. */ + unsigned char ci_gnu_personality_handler_encoding; + unsigned char ci_gnu_lsda_encoding; + unsigned char ci_gnu_fde_begin_encoding; + + /* If 'P' augmentation present, is handler addr. Else + is zero. */ + Dwarf_Addr ci_gnu_personality_handler_addr; + + + /* In creating list of cie's (which will become an array) + record the position so fde can get it on fde creation. */ + Dwarf_Unsigned ci_index; + Dwarf_Small * ci_section_ptr; + /* DWARF4 adds address size and segment size to the CIE: the .debug_info + section may not always be present to allow libdwarf to + find address_size from the compilation-unit. */ + Dwarf_Half ci_address_size; + Dwarf_Half ci_segment_size; + +}; + +/* + This structure contains all the pertinent info for a Fde. + Most of the fields are taken straight from the definition. + fd_cie_index is the index of the Cie associated with this + Fde in the list of Cie's for this debug_frame. Fd_cie + points to the corresponsing Dwarf_Cie structure. Fd_fde_start + points to the start address of the Fde. Fd_fde_instr_start + points to the start of the instructions for this Fde. Fd_dbg + points to the associated Dwarf_Debug structure. +*/ +struct Dwarf_Fde_s { + Dwarf_Unsigned fd_length; + Dwarf_Addr fd_cie_offset; + Dwarf_Unsigned fd_cie_index; + Dwarf_Cie fd_cie; + Dwarf_Addr fd_initial_location; + Dwarf_Small *fd_initial_loc_pos; + Dwarf_Addr fd_address_range; + Dwarf_Small *fd_fde_start; + Dwarf_Small *fd_fde_instr_start; + Dwarf_Debug fd_dbg; + + /* fd_offset_into_exception_tables is SGI/IRIX exception table + offset. Unused and zero if not IRIX .debug_frame. */ + Dwarf_Signed fd_offset_into_exception_tables; + + Dwarf_Fde fd_next; + Dwarf_Small fd_length_size; + Dwarf_Small fd_extension_size; + /* So we know from an fde which 'count' of fde-s in + Dwarf_Debug applies: eh or standard. */ + Dwarf_Small fd_is_eh; + /* The following 2 for GNU .eh_frame exception handling + Augmentation Data. Set if CIE ci_augmentation_type + is aug_gcc_eh_z. Zero if unused. */ + Dwarf_Unsigned fd_gnu_eh_augmentation_len; + Dwarf_Ptr fd_gnu_eh_augmentation_bytes; + Dwarf_Addr fd_gnu_eh_lsda; /* If 'L' augmentation letter + present: is address of the + Language Specific Data Area (LSDA). If not 'L" is zero. */ + + /* The following 3 are about the Elf section the FDEs come from. */ + Dwarf_Small * fd_section_ptr; + Dwarf_Unsigned fd_section_length; + Dwarf_Unsigned fd_section_index; + +}; + + +int + _dwarf_frame_address_offsets(Dwarf_Debug dbg, Dwarf_Addr ** addrlist, + Dwarf_Off ** offsetlist, + Dwarf_Signed * returncount, + Dwarf_Error * err); + +int +_dwarf_get_fde_list_internal(Dwarf_Debug dbg, + Dwarf_Cie ** cie_data, + Dwarf_Signed * cie_element_count, + Dwarf_Fde ** fde_data, + Dwarf_Signed * fde_element_count, + Dwarf_Small * section_ptr, + Dwarf_Unsigned section_index, + Dwarf_Unsigned section_length, + Dwarf_Unsigned cie_id_value, + int use_gnu_cie_calc, /* If non-zero, + this is gcc eh_frame. */ + Dwarf_Error * error); + +enum Dwarf_augmentation_type +_dwarf_get_augmentation_type(Dwarf_Debug dbg, + Dwarf_Small *augmentation_string, + int is_gcc_eh_frame); + +Dwarf_Unsigned _dwarf_get_return_address_reg(Dwarf_Small *frame_ptr, + int version, + unsigned long *size); + +/* Temporary recording of crucial cie/fde prefix data. + * Vastly simplifies some argument lists. + */ +struct cie_fde_prefix_s { + /* cf_start_addr is a pointer to the first byte of this fde/cie + we are reading now. */ + Dwarf_Small * cf_start_addr; + Dwarf_Small * cf_addr_after_prefix; + Dwarf_Unsigned cf_length; + int cf_local_length_size; + int cf_local_extension_size; + Dwarf_Unsigned cf_cie_id; + Dwarf_Small * cf_cie_id_addr; /* used for eh_frame calculations. */ + + /* Simplifies passing around these values to create fde having + these here. */ + /* cf_section_ptr is a pointer to the first byte + of the object section the prefix is read from. */ + Dwarf_Small * cf_section_ptr; + Dwarf_Unsigned cf_section_index; + Dwarf_Unsigned cf_section_length; +}; + +int +_dwarf_exec_frame_instr(Dwarf_Bool make_instr, + Dwarf_Frame_Op ** ret_frame_instr, + Dwarf_Bool search_pc, + Dwarf_Addr search_pc_val, + Dwarf_Addr initial_loc, + Dwarf_Small * start_instr_ptr, + Dwarf_Small * final_instr_ptr, + Dwarf_Frame table, + Dwarf_Cie cie, + Dwarf_Debug dbg, + Dwarf_Half reg_num_of_cfa, + Dwarf_Sword * returned_count, + int *returned_error); + + +int dwarf_read_cie_fde_prefix(Dwarf_Debug dbg, + Dwarf_Small *frame_ptr_in, + Dwarf_Small *section_ptr_in, + Dwarf_Unsigned section_index_in, + Dwarf_Unsigned section_length_in, + struct cie_fde_prefix_s *prefix_out, + Dwarf_Error *error); + +int dwarf_create_fde_from_after_start(Dwarf_Debug dbg, + struct cie_fde_prefix_s * prefix, + Dwarf_Small *section_pointer, + Dwarf_Small *frame_ptr, + int use_gnu_cie_calc, + Dwarf_Cie cie_ptr_in, + Dwarf_Fde *fde_ptr_out, + Dwarf_Error *error); + +int dwarf_create_cie_from_after_start(Dwarf_Debug dbg, + struct cie_fde_prefix_s *prefix, + Dwarf_Small* section_pointer, + Dwarf_Small* frame_ptr, + Dwarf_Unsigned cie_count, + int use_gnu_cie_calc, + Dwarf_Cie *cie_ptr_out, + Dwarf_Error *error); + + +int _dwarf_frame_constructor(Dwarf_Debug dbg,void * ); +void _dwarf_frame_destructor (void *); diff --git a/usr/src/lib/libdwarf/common/dwarf_frame2.c b/usr/src/lib/libdwarf/common/dwarf_frame2.c new file mode 100644 index 0000000000..01b9ec497b --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_frame2.c @@ -0,0 +1,1540 @@ +/* + + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + +/* + This implements _dwarf_get_fde_list_internal() + and related helper functions for reading cie/fde data. +*/ + + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include +#include +#include "dwarf_frame.h" +#include "dwarf_arange.h" /* using Arange as a way to build a + list */ + + +static int dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr, + Dwarf_Cie cur_cie_ptr, + Dwarf_Cie * cie_ptr_to_use_out, + Dwarf_Cie head_cie_ptr); +static void dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr, + Dwarf_Cie head_cie_ptr); +static int dwarf_create_cie_from_start(Dwarf_Debug dbg, + Dwarf_Small * cie_ptr_val, + Dwarf_Small * section_ptr, + Dwarf_Unsigned section_index, + Dwarf_Unsigned section_length, + Dwarf_Small * frame_ptr_end, + Dwarf_Unsigned cie_id_value, + Dwarf_Unsigned cie_count, + int use_gnu_cie_calc, + Dwarf_Cie * cie_ptr_to_use_out, + Dwarf_Error * error); + +static Dwarf_Small *get_cieptr_given_offset(Dwarf_Unsigned cie_id_value, + int use_gnu_cie_calc, + Dwarf_Small * section_ptr, + Dwarf_Small * cie_id_addr); +static int get_gcc_eh_augmentation(Dwarf_Debug dbg, + Dwarf_Small * frame_ptr, + unsigned long + *size_of_augmentation_data, + enum Dwarf_augmentation_type augtype, + Dwarf_Small * section_pointer, + Dwarf_Small * fde_eh_encoding_out, + char *augmentation); + +static int + gnu_aug_encodings(Dwarf_Debug dbg, char *augmentation, + Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len, + Dwarf_Half address_size, + unsigned char *pers_hand_enc_out, + unsigned char *lsda_enc_out, + unsigned char *fde_begin_enc_out, + Dwarf_Addr * gnu_pers_addr_out); + + +static int read_encoded_ptr(Dwarf_Debug dbg, + Dwarf_Small * section_pointer, + Dwarf_Small * input_field, + int gnu_encoding, + Dwarf_Half address_size, + Dwarf_Unsigned * addr, + Dwarf_Small ** input_field_out); + + + +static int qsort_compare(const void *elem1, const void *elem2); + + +/* Adds 'newone' to the end of the list starting at 'head' + and makes the new one 'cur'rent. */ +static void +chain_up_fde(Dwarf_Fde newone, Dwarf_Fde * head, Dwarf_Fde * cur) +{ + if (*head == NULL) + *head = newone; + else { + (*cur)->fd_next = newone; + } + *cur = newone; + +} + +/* Adds 'newone' to the end of the list starting at 'head' + and makes the new one 'cur'rent. */ +static void +chain_up_cie(Dwarf_Cie newone, Dwarf_Cie * head, Dwarf_Cie * cur) +{ + if (*head == NULL) { + *head = newone; + } else { + (*cur)->ci_next = newone; + } + *cur = newone; +} + +/* The size of the length field plus the + value of length must be an integral + multiple of the address size. Dwarf4 standard. + + A constant that gives the number of bytes of the CIE + structure, not including the length field itself + (where length mod == 0) + (see Section 7.2.2). Dwarf3 standard. + + A uword constant that gives the number of bytes of + the CIE structure, not including the + length field, itself (length mod == 0). + Dwarf2 standard.*/ +static void +validate_length(Dwarf_Debug dbg, + Dwarf_Cie cieptr, Dwarf_Unsigned length, + Dwarf_Unsigned length_size, + Dwarf_Unsigned extension_size, + Dwarf_Small * section_ptr, + Dwarf_Small * ciefde_start, + const char * cieorfde) +{ + Dwarf_Unsigned address_size = cieptr->ci_address_size; + Dwarf_Unsigned length_field_summed = length_size + extension_size; + Dwarf_Unsigned total_len = length + length_field_summed; + Dwarf_Unsigned mod = total_len % address_size; + + if (mod != 0) { + char msg[DW_HARMLESS_ERROR_MSG_STRING_SIZE]; + Dwarf_Unsigned sectionoffset = ciefde_start - section_ptr; + snprintf(msg,sizeof(msg), + "DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE" + " len=0x%" DW_PR_DUx + ", len size=0x%" DW_PR_DUx + ", extn size=0x%" DW_PR_DUx + ", totl length=0x%" DW_PR_DUx + ", addr size=0x%" DW_PR_DUx + ", mod=0x%" DW_PR_DUx " must be zero" + " in %s" + ", offset 0x%" DW_PR_DUx ".", + length, + length_size, + extension_size, + total_len,address_size, mod, + cieorfde, + sectionoffset); + dwarf_insert_harmless_error(dbg,msg); + } + return; +} + + +#if 0 +/* For debugging only. */ +static void +print_prefix(struct cie_fde_prefix_s *prefix, int line) +{ + printf("prefix-print, prefix at 0x%lx, line %d\n", + (long) prefix, line); + printf(" start addr 0x%lx after prefix 0x%lx\n", + (long) prefix->cf_start_addr, + (long) prefix->cf_addr_after_prefix); + printf(" length 0x%" DW_PR_DUx ", len size %d ext size %d\n", + (Dwarf_Unsigned) prefix->cf_length, + prefix->cf_local_length_size, + prefix->cf_local_extension_size); + printf(" cie_id 0x%" DW_PR_DUx " cie_id cie_id_addr 0x%lx\n", + (Dwarf_Unsigned) prefix->cf_cie_id, + (long) prefix->cf_cie_id_addr); + printf + (" sec ptr 0x%lx sec index %" DW_PR_DSd " sec len 0x%" DW_PR_DUx " sec past end 0x%lx\n", + (long) prefix->cf_section_ptr, + (Dwarf_Signed) prefix->cf_section_index, + (Dwarf_Unsigned) prefix->cf_section_length, + (long) prefix->cf_section_ptr + prefix->cf_section_length); +} +#endif + + + +/* Internal function called from various places to create + lists of CIEs and FDEs. Not directly called + by consumer code */ +int +_dwarf_get_fde_list_internal(Dwarf_Debug dbg, Dwarf_Cie ** cie_data, + Dwarf_Signed * cie_element_count, + Dwarf_Fde ** fde_data, + Dwarf_Signed * fde_element_count, + Dwarf_Small * section_ptr, + Dwarf_Unsigned section_index, + Dwarf_Unsigned section_length, + Dwarf_Unsigned cie_id_value, + int use_gnu_cie_calc, Dwarf_Error * error) +{ + /* Scans the debug_frame section. */ + Dwarf_Small *frame_ptr = section_ptr; + Dwarf_Small *frame_ptr_end = section_ptr + section_length; + + + + /* + New_cie points to the Cie being read, and head_cie_ptr and + cur_cie_ptr are used for chaining them up in sequence. + In case cie's are reused aggressively we need tail_cie_ptr + to add to the chain. If we re-use an early cie + later on, that does not mean we chain a new cie to the early one, + we always chain it to the tail. */ + Dwarf_Cie head_cie_ptr = NULL; + Dwarf_Cie cur_cie_ptr = NULL; + Dwarf_Cie tail_cie_ptr = NULL; + Dwarf_Word cie_count = 0; + + /* + Points to a list of contiguous pointers to Dwarf_Cie structures. + */ + Dwarf_Cie *cie_list_ptr = 0; + + + /* + New_fde points to the Fde being created, and head_fde_ptr and + cur_fde_ptr are used to chain them up. */ + Dwarf_Fde head_fde_ptr = NULL; + Dwarf_Fde cur_fde_ptr = NULL; + Dwarf_Word fde_count = 0; + + /* + Points to a list of contiguous pointers to Dwarf_Fde structures. + */ + Dwarf_Fde *fde_list_ptr = NULL; + + Dwarf_Word i = 0; + int res = DW_DLV_ERROR; + + if (frame_ptr == 0) { + return DW_DLV_NO_ENTRY; + } + + /* We create the fde and cie arrays. Processing each CIE as we come + to it or as an FDE refers to it. We cannot process 'late' CIEs + late as GNU .eh_frame complexities mean we need the whole CIE + before we can process the FDE correctly. */ + while (frame_ptr < frame_ptr_end) { + + struct cie_fde_prefix_s prefix; + + /* First read in the 'common prefix' to figure out what we are + to do with this entry. */ + memset(&prefix, 0, sizeof(prefix)); + res = dwarf_read_cie_fde_prefix(dbg, + frame_ptr, section_ptr, + section_index, + section_length, &prefix, error); + if (res == DW_DLV_ERROR) { + dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr); + return res; + } + if (res == DW_DLV_NO_ENTRY) + break; + frame_ptr = prefix.cf_addr_after_prefix; + if (frame_ptr >= frame_ptr_end) { + dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr); + _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD); + return DW_DLV_ERROR; + + } + + if (prefix.cf_cie_id == cie_id_value) { + /* This is a CIE. */ + Dwarf_Cie cie_ptr_to_use = 0; + + int res = dwarf_find_existing_cie_ptr(prefix.cf_start_addr, + cur_cie_ptr, + &cie_ptr_to_use, + head_cie_ptr); + + if (res == DW_DLV_OK) { + cur_cie_ptr = cie_ptr_to_use; + /* Ok. Seen already. */ + } else if (res == DW_DLV_NO_ENTRY) { + /* CIE before its FDE in this case. */ + res = dwarf_create_cie_from_after_start(dbg, + &prefix, + section_ptr, + frame_ptr, + cie_count, + use_gnu_cie_calc, + &cie_ptr_to_use, + error); + /* ASSERT: res==DW_DLV_NO_ENTRY impossible. */ + if (res == DW_DLV_ERROR) { + dealloc_fde_cie_list_internal(head_fde_ptr, + head_cie_ptr); + return res; + } + /* ASSERT res != DW_DLV_NO_ENTRY */ + cie_count++; + chain_up_cie(cie_ptr_to_use, &head_cie_ptr, + &tail_cie_ptr); + cur_cie_ptr = tail_cie_ptr; + } else { /* res == DW_DLV_ERROR */ + + dealloc_fde_cie_list_internal(head_fde_ptr, + head_cie_ptr); + return res; + } + frame_ptr = cie_ptr_to_use->ci_cie_start + + cie_ptr_to_use->ci_length + + cie_ptr_to_use->ci_length_size + + cie_ptr_to_use->ci_extension_size; + continue; + } else { + /* this is an FDE, Frame Description Entry, see the Dwarf + Spec, section 6.4.1 */ + int res = DW_DLV_ERROR; + Dwarf_Cie cie_ptr_to_use = 0; + Dwarf_Fde fde_ptr_to_use = 0; + + /* Do not call this twice on one prefix, as + prefix.cf_cie_id_addr is altered as a side effect. */ + Dwarf_Small *cieptr_val = + get_cieptr_given_offset(prefix.cf_cie_id, + use_gnu_cie_calc, + section_ptr, + prefix.cf_cie_id_addr); + + res = dwarf_find_existing_cie_ptr(cieptr_val, + cur_cie_ptr, + &cie_ptr_to_use, + head_cie_ptr); + if (res == DW_DLV_OK) { + cur_cie_ptr = cie_ptr_to_use; + /* Ok. Seen CIE already. */ + } else if (res == DW_DLV_NO_ENTRY) { + res = dwarf_create_cie_from_start(dbg, + cieptr_val, + section_ptr, + section_index, + section_length, + frame_ptr_end, + cie_id_value, + cie_count, + use_gnu_cie_calc, + &cie_ptr_to_use, + error); + if (res == DW_DLV_ERROR) { + dealloc_fde_cie_list_internal(head_fde_ptr, + head_cie_ptr); + return res; + } else if (res == DW_DLV_NO_ENTRY) { + return res; + } + ++cie_count; + chain_up_cie(cie_ptr_to_use, &head_cie_ptr, + &tail_cie_ptr); + cur_cie_ptr = tail_cie_ptr; + + } else { + /* DW_DLV_ERROR */ + return res; + } + + res = dwarf_create_fde_from_after_start(dbg, + &prefix, + section_ptr, + frame_ptr, + use_gnu_cie_calc, + cie_ptr_to_use, + &fde_ptr_to_use, + error); + if (res == DW_DLV_ERROR) { + return res; + } + chain_up_fde(fde_ptr_to_use, &head_fde_ptr, &cur_fde_ptr); + fde_count++; + /* ASSERT: DW_DLV_OK. */ + frame_ptr = fde_ptr_to_use->fd_fde_start + + fde_ptr_to_use->fd_length + + fde_ptr_to_use->fd_length_size + + fde_ptr_to_use->fd_extension_size; + continue; + + } + + } + + /* Now build list of CIEs from the list. If there are no CIEs + there should be no FDEs. */ + if (cie_count > 0) { + cie_list_ptr = (Dwarf_Cie *) + _dwarf_get_alloc(dbg, DW_DLA_LIST, cie_count); + } else { + if(fde_count > 0) { + dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr); + _dwarf_error(dbg, error, DW_DLE_ORPHAN_FDE); + return DW_DLV_ERROR; + } + dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr); + return DW_DLV_NO_ENTRY; + } + if (cie_list_ptr == NULL) { + dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr); + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return DW_DLV_ERROR; + } + cur_cie_ptr = head_cie_ptr; + for (i = 0; i < cie_count; i++) { + *(cie_list_ptr + i) = cur_cie_ptr; + cur_cie_ptr = cur_cie_ptr->ci_next; + } + + + + /* Now build array of FDEs from the list. + With orphan CIEs (meaning no FDEs) lets not return DW_DLV_NO_ENTRY */ + if (fde_count > 0) { + fde_list_ptr = (Dwarf_Fde *) + _dwarf_get_alloc(dbg, DW_DLA_LIST, fde_count); + } + + /* It is ok if fde_list_ptr is NULL, we just have no fdes. */ + cur_fde_ptr = head_fde_ptr; + for (i = 0; i < fde_count; i++) { + *(fde_list_ptr + i) = cur_fde_ptr; + cur_fde_ptr = cur_fde_ptr->fd_next; + } + + + /* Return arguments. */ + *cie_data = cie_list_ptr; + *cie_element_count = cie_count; + + *fde_data = fde_list_ptr; + *fde_element_count = fde_count; + if(use_gnu_cie_calc) { + dbg->de_fde_data_eh = fde_list_ptr; + dbg->de_fde_count_eh = fde_count; + dbg->de_cie_data_eh = cie_list_ptr; + dbg->de_cie_count_eh = cie_count; + } else { + dbg->de_fde_data = fde_list_ptr; + dbg->de_fde_count = fde_count; + dbg->de_cie_data = cie_list_ptr; + dbg->de_cie_count = cie_count; + } + + /* Sort the list by the address so that dwarf_get_fde_at_pc() can + binary search this list. */ + if(fde_count > 0) { + qsort((void *) fde_list_ptr, fde_count, sizeof(Dwarf_Ptr), + qsort_compare); + } + + return (DW_DLV_OK); +} + +/* Internal function, not called by consumer code. + 'prefix' has accumulated the info up thru the cie-id + and now we consume the rest and build a Dwarf_Cie_s structure. +*/ +int +dwarf_create_cie_from_after_start(Dwarf_Debug dbg, + struct cie_fde_prefix_s *prefix, + Dwarf_Small * section_pointer, + Dwarf_Small * frame_ptr, + Dwarf_Unsigned cie_count, + int use_gnu_cie_calc, + Dwarf_Cie * cie_ptr_out, + Dwarf_Error * error) +{ + Dwarf_Cie new_cie = 0; + + /* egcs-1.1.2 .eh_frame uses 0 as the distinguishing id. sgi uses + -1 (in .debug_frame). .eh_frame not quite identical to + .debug_frame */ + /* We here default the address size as it is not present + in DWARF2 or DWARF3 cie data, below we set it right if + it is present. */ + Dwarf_Half address_size = dbg->de_pointer_size; + Dwarf_Small eh_fde_encoding = 0; + Dwarf_Small *augmentation = 0; + Dwarf_Half segment_size = 0; + Dwarf_Sword data_alignment_factor = -1; + Dwarf_Word code_alignment_factor = 4; + Dwarf_Unsigned return_address_register = 31; + int local_length_size = 0; + Dwarf_Word leb128_length = 0; + Dwarf_Unsigned cie_aug_data_len = 0; + Dwarf_Small *cie_aug_data = 0; + Dwarf_Addr gnu_personality_handler_addr = 0; + unsigned char gnu_personality_handler_encoding = 0; + unsigned char gnu_lsda_encoding = 0; + unsigned char gnu_fde_begin_encoding = 0; + + + enum Dwarf_augmentation_type augt = aug_unknown; + + + /* this is a CIE, Common Information Entry: See the dwarf spec, + section 6.4.1 */ + Dwarf_Small version = *(Dwarf_Small *) frame_ptr; + + frame_ptr++; + if (version != DW_CIE_VERSION && version != DW_CIE_VERSION3 && + version != DW_CIE_VERSION4) { + _dwarf_error(dbg, error, DW_DLE_FRAME_VERSION_BAD); + return (DW_DLV_ERROR); + } + + augmentation = frame_ptr; + frame_ptr = frame_ptr + strlen((char *) frame_ptr) + 1; + augt = _dwarf_get_augmentation_type(dbg, + augmentation, use_gnu_cie_calc); + if (augt == aug_eh) { + /* REFERENCED *//* Not used in this instance */ + Dwarf_Unsigned exception_table_addr; + + /* this is per egcs-1.1.2 as on RH 6.0 */ + READ_UNALIGNED(dbg, exception_table_addr, + Dwarf_Unsigned, frame_ptr, local_length_size); + frame_ptr += local_length_size; + } + { + Dwarf_Unsigned lreg = 0; + unsigned long size = 0; + + if( version == DW_CIE_VERSION4) { + address_size = *((unsigned char *)frame_ptr); + ++frame_ptr; + segment_size = *((unsigned char *)frame_ptr); + ++frame_ptr; + } + + DECODE_LEB128_UWORD(frame_ptr, lreg); + code_alignment_factor = (Dwarf_Word) lreg; + + data_alignment_factor = + (Dwarf_Sword) _dwarf_decode_s_leb128(frame_ptr, + &leb128_length); + + frame_ptr = frame_ptr + leb128_length; + + return_address_register = + _dwarf_get_return_address_reg(frame_ptr, version, &size); + if (return_address_register > dbg->de_frame_reg_rules_entry_count) { + _dwarf_error(dbg, error, DW_DLE_CIE_RET_ADDR_REG_ERROR); + return (DW_DLV_ERROR); + } + frame_ptr += size; + } + switch (augt) { + case aug_empty_string: + break; + case aug_irix_mti_v1: + break; + case aug_irix_exception_table:{ + Dwarf_Unsigned lreg = 0; + Dwarf_Word length_of_augmented_fields; + + /* Decode the length of augmented fields. */ + DECODE_LEB128_UWORD(frame_ptr, lreg); + length_of_augmented_fields = (Dwarf_Word) lreg; + + + /* set the frame_ptr to point at the instruction start. */ + frame_ptr += length_of_augmented_fields; + } + break; + + case aug_eh:{ + + int err = 0; + unsigned long increment = 0; + + if (!use_gnu_cie_calc) { + /* This should be impossible. */ + _dwarf_error(dbg, error, + DW_DLE_FRAME_AUGMENTATION_UNKNOWN); + return DW_DLV_ERROR; + } + + err = get_gcc_eh_augmentation(dbg, frame_ptr, &increment, + augt, + prefix->cf_section_ptr, + &eh_fde_encoding, + (char *) augmentation); + if (err == DW_DLV_ERROR) { + _dwarf_error(dbg, error, + DW_DLE_FRAME_AUGMENTATION_UNKNOWN); + return DW_DLV_ERROR; + } + frame_ptr += increment; + break; + } + case aug_gcc_eh_z:{ + /* Here we have Augmentation Data Length (uleb128) followed + by Augmentation Data bytes. */ + int res = DW_DLV_ERROR; + Dwarf_Unsigned adlen = 0; + + DECODE_LEB128_UWORD(frame_ptr, adlen); + cie_aug_data_len = adlen; + cie_aug_data = frame_ptr; + res = gnu_aug_encodings(dbg, + (char *) augmentation, + cie_aug_data, + cie_aug_data_len, + address_size, + &gnu_personality_handler_encoding, + &gnu_lsda_encoding, + &gnu_fde_begin_encoding, + &gnu_personality_handler_addr); + if (res != DW_DLV_OK) { + _dwarf_error(dbg, error, + DW_DLE_FRAME_AUGMENTATION_UNKNOWN); + return res; + } + + + frame_ptr += adlen; + break; + } + case aug_armcc: + break; + default:{ + /* We do not understand the augmentation string. No + assumption can be made about any fields other than what + we have already read. */ + frame_ptr = prefix->cf_start_addr + + prefix->cf_length + prefix->cf_local_length_size + + prefix->cf_local_extension_size; + /* FIX -- What are the values of data_alignment_factor, + code_alignement_factor, return_address_register and + instruction start? They were clearly uninitalized in the + previous version and I am leaving them the same way. */ + break; + } + } /* End switch on augmentation type. */ + + new_cie = (Dwarf_Cie) _dwarf_get_alloc(dbg, DW_DLA_CIE, 1); + if (new_cie == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + new_cie->ci_cie_version_number = version; + new_cie->ci_initial_table = NULL; + new_cie->ci_length = (Dwarf_Word) prefix->cf_length; + new_cie->ci_length_size = prefix->cf_local_length_size; + new_cie->ci_extension_size = prefix->cf_local_extension_size; + new_cie->ci_augmentation = (char *) augmentation; + + new_cie->ci_data_alignment_factor = + (Dwarf_Sbyte) data_alignment_factor; + new_cie->ci_code_alignment_factor = + (Dwarf_Small) code_alignment_factor; + new_cie->ci_return_address_register = return_address_register; + new_cie->ci_cie_start = prefix->cf_start_addr; + new_cie->ci_cie_instr_start = frame_ptr; + new_cie->ci_dbg = dbg; + new_cie->ci_augmentation_type = augt; + new_cie->ci_gnu_eh_augmentation_len = cie_aug_data_len; + new_cie->ci_gnu_eh_augmentation_bytes = cie_aug_data; + new_cie->ci_gnu_personality_handler_encoding = + gnu_personality_handler_encoding; + new_cie->ci_gnu_personality_handler_addr = + gnu_personality_handler_addr; + new_cie->ci_gnu_lsda_encoding = gnu_lsda_encoding; + new_cie->ci_gnu_fde_begin_encoding = gnu_fde_begin_encoding; + + new_cie->ci_index = cie_count; + new_cie->ci_section_ptr = prefix->cf_section_ptr; + /* The Following new in DWARF4 */ + new_cie->ci_address_size = address_size; + new_cie->ci_segment_size = segment_size; + validate_length(dbg,new_cie,new_cie->ci_length, + new_cie->ci_length_size, new_cie->ci_extension_size, + new_cie->ci_section_ptr, + new_cie->ci_cie_start,"cie"); + + *cie_ptr_out = new_cie; + return DW_DLV_OK; + +} + + +/* Internal function, not called by consumer code. + 'prefix' has accumulated the info up thru the cie-id + and now we consume the rest and build a Dwarf_Fde_s structure. +*/ + +int +dwarf_create_fde_from_after_start(Dwarf_Debug dbg, + struct cie_fde_prefix_s *prefix, + Dwarf_Small * section_pointer, + Dwarf_Small * frame_ptr, + int use_gnu_cie_calc, + Dwarf_Cie cie_ptr_in, + Dwarf_Fde * fde_ptr_out, + Dwarf_Error * error) +{ + Dwarf_Fde new_fde = 0; + Dwarf_Cie cieptr = cie_ptr_in; + Dwarf_Small *saved_frame_ptr = 0; + + Dwarf_Small *initloc = frame_ptr; + Dwarf_Signed offset_into_exception_tables + /* must be min dwarf_sfixed in size */ + = (Dwarf_Signed) DW_DLX_NO_EH_OFFSET; + Dwarf_Small *fde_aug_data = 0; + Dwarf_Unsigned fde_aug_data_len = 0; + Dwarf_Addr cie_base_offset = prefix->cf_cie_id; + Dwarf_Addr initial_location = 0; /* must be min de_pointer_size + bytes in size */ + Dwarf_Addr address_range = 0; /* must be min de_pointer_size + bytes in size */ + Dwarf_Half address_size = cie_ptr_in->ci_address_size; + + enum Dwarf_augmentation_type augt = cieptr->ci_augmentation_type; + + if (augt == aug_gcc_eh_z) { + /* If z augmentation this is eh_frame, and initial_location and + address_range in the FDE are read according to the CIE + augmentation string instructions. */ + + { + Dwarf_Small *fp_updated = 0; + int res = read_encoded_ptr(dbg, + section_pointer, + frame_ptr, + cieptr-> ci_gnu_fde_begin_encoding, + address_size, + &initial_location, + &fp_updated); + if (res != DW_DLV_OK) { + _dwarf_error(dbg, error, + DW_DLE_FRAME_AUGMENTATION_UNKNOWN); + return DW_DLV_ERROR; + } + frame_ptr = fp_updated; + /* For the address-range it makes no sense to be + pc-relative, so we turn it off with a section_pointer of + NULL. Masking off DW_EH_PE_pcrel from the + ci_gnu_fde_begin_encoding in this call would also work + to turn off DW_EH_PE_pcrel. */ + res = read_encoded_ptr(dbg, (Dwarf_Small *) NULL, + frame_ptr, + cieptr->ci_gnu_fde_begin_encoding, + address_size, + &address_range, &fp_updated); + if (res != DW_DLV_OK) { + _dwarf_error(dbg, error, + DW_DLE_FRAME_AUGMENTATION_UNKNOWN); + return DW_DLV_ERROR; + } + frame_ptr = fp_updated; + } + { + Dwarf_Unsigned adlen = 0; + + DECODE_LEB128_UWORD(frame_ptr, adlen); + fde_aug_data_len = adlen; + fde_aug_data = frame_ptr; + frame_ptr += adlen; + } + + } else { + READ_UNALIGNED(dbg, initial_location, Dwarf_Addr, + frame_ptr, address_size); + frame_ptr += address_size; + + READ_UNALIGNED(dbg, address_range, Dwarf_Addr, + frame_ptr, address_size); + frame_ptr += address_size; + } + + + + + + switch (augt) { + case aug_irix_mti_v1: + case aug_empty_string: + break; + case aug_irix_exception_table:{ + Dwarf_Unsigned lreg = 0; + Dwarf_Word length_of_augmented_fields = 0; + + DECODE_LEB128_UWORD(frame_ptr, lreg); + length_of_augmented_fields = (Dwarf_Word) lreg; + + saved_frame_ptr = frame_ptr; + /* The first word is an offset into exception tables. + Defined as a 32bit offset even for CC -64. */ + READ_UNALIGNED(dbg, offset_into_exception_tables, + Dwarf_Addr, frame_ptr, sizeof(Dwarf_sfixed)); + SIGN_EXTEND(offset_into_exception_tables, + sizeof(Dwarf_sfixed)); + frame_ptr = saved_frame_ptr + length_of_augmented_fields; + } + break; + case aug_eh:{ + Dwarf_Unsigned eh_table_value = 0; + + if (!use_gnu_cie_calc) { + /* This should be impossible. */ + _dwarf_error(dbg, error, + DW_DLE_FRAME_AUGMENTATION_UNKNOWN); + return DW_DLV_ERROR; + } + + /* gnu eh fde case. we do not need to do anything */ + /*REFERENCED*/ /* Not used in this instance of the + macro */ + READ_UNALIGNED(dbg, eh_table_value, + Dwarf_Unsigned, frame_ptr, + address_size); + frame_ptr += address_size; + } + break; + + case aug_gcc_eh_z:{ + /* The Augmentation Data Length is here, followed by the + Augmentation Data bytes themselves. */ + } + break; + case aug_armcc: + break; + case aug_past_last: + break; + case aug_unknown: + _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN); + return DW_DLV_ERROR; + } /* End switch on augmentation type */ + new_fde = (Dwarf_Fde) _dwarf_get_alloc(dbg, DW_DLA_FDE, 1); + if (new_fde == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + new_fde->fd_length = prefix->cf_length; + new_fde->fd_length_size = prefix->cf_local_length_size; + new_fde->fd_extension_size = prefix->cf_local_extension_size; + new_fde->fd_is_eh = use_gnu_cie_calc; + new_fde->fd_cie_offset = cie_base_offset; + new_fde->fd_cie_index = cieptr->ci_index; + new_fde->fd_cie = cieptr; + new_fde->fd_initial_location = initial_location; + new_fde->fd_initial_loc_pos = initloc; + new_fde->fd_address_range = address_range; + new_fde->fd_fde_start = prefix->cf_start_addr; + new_fde->fd_fde_instr_start = frame_ptr; + new_fde->fd_dbg = dbg; + new_fde->fd_offset_into_exception_tables = + offset_into_exception_tables; + + new_fde->fd_section_ptr = prefix->cf_section_ptr; + new_fde->fd_section_index = prefix->cf_section_index; + new_fde->fd_section_length = prefix->cf_section_length; + + new_fde->fd_gnu_eh_augmentation_bytes = fde_aug_data; + new_fde->fd_gnu_eh_augmentation_len = fde_aug_data_len; + validate_length(dbg,cieptr,new_fde->fd_length, + new_fde->fd_length_size, new_fde->fd_extension_size, + new_fde->fd_section_ptr,new_fde->fd_fde_start,"fde"); + + + *fde_ptr_out = new_fde; + return DW_DLV_OK; +} + +/* called by qsort to compare FDE entries. + Consumer code expects the array of FDE pointers to be in address order. +*/ +static int +qsort_compare(const void *elem1, const void *elem2) +{ + Dwarf_Fde fde1 = *(Dwarf_Fde *) elem1; + Dwarf_Fde fde2 = *(Dwarf_Fde *) elem2; + Dwarf_Addr addr1 = fde1->fd_initial_location; + Dwarf_Addr addr2 = fde2->fd_initial_location; + + if (addr1 < addr2) { + return -1; + } else if (addr1 > addr2) { + return 1; + } + return 0; +} + + +/* Read in the common cie/fde prefix, including reading + * the cie-value which shows which this is: cie or fde. + * */ +int +dwarf_read_cie_fde_prefix(Dwarf_Debug dbg, + Dwarf_Small * frame_ptr_in, + Dwarf_Small * section_ptr_in, + Dwarf_Unsigned section_index_in, + Dwarf_Unsigned section_length_in, + struct cie_fde_prefix_s *data_out, + Dwarf_Error * error) +{ + Dwarf_Unsigned length = 0; + int local_length_size = 0; + int local_extension_size = 0; + Dwarf_Small *frame_ptr = frame_ptr_in; + Dwarf_Small *cie_ptr_addr = 0; + Dwarf_Unsigned cie_id = 0; + + /* READ_AREA_LENGTH updates frame_ptr for consumed bytes */ + READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned, + frame_ptr, local_length_size, + local_extension_size); + + if (length == 0) { + /* nul bytes at end of section, seen at end of egcs eh_frame + sections (in a.out). Take this as meaning no more CIE/FDE + data. We should be very close to end of section. */ + return DW_DLV_NO_ENTRY; + } + + cie_ptr_addr = frame_ptr; + READ_UNALIGNED(dbg, cie_id, Dwarf_Unsigned, + frame_ptr, local_length_size); + SIGN_EXTEND(cie_id, local_length_size); + frame_ptr += local_length_size; + + data_out->cf_start_addr = frame_ptr_in; + data_out->cf_addr_after_prefix = frame_ptr; + + data_out->cf_length = length; + data_out->cf_local_length_size = local_length_size; + data_out->cf_local_extension_size = local_extension_size; + data_out->cf_cie_id = cie_id; + data_out->cf_cie_id_addr = cie_ptr_addr; + data_out->cf_section_ptr = section_ptr_in; + data_out->cf_section_index = section_index_in; + data_out->cf_section_length = section_length_in; + return DW_DLV_OK; +} + +/* On various errors previously-allocated CIEs and FDEs + must be cleaned up. + This helps avoid leaks in case of errors. +*/ +static void +dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr, + Dwarf_Cie head_cie_ptr) +{ + Dwarf_Fde curfde = 0; + Dwarf_Cie curcie = 0; + Dwarf_Fde nextfde = 0; + Dwarf_Cie nextcie = 0; + + for (curfde = head_fde_ptr; curfde; curfde = nextfde) { + nextfde = curfde->fd_next; + dwarf_dealloc(curfde->fd_dbg, curfde, DW_DLA_FDE); + } + for (curcie = head_cie_ptr; curcie; curcie = nextcie) { + Dwarf_Frame frame = curcie->ci_initial_table; + + nextcie = curcie->ci_next; + if (frame) + dwarf_dealloc(curcie->ci_dbg, frame, DW_DLA_FRAME); + dwarf_dealloc(curcie->ci_dbg, curcie, DW_DLA_CIE); + } +} + +/* Find the cie whose id value is given: the id + * value is, per DWARF2/3, an offset in the section. + * For .debug_frame, zero is a legal offset. For + * GNU .eh_frame it is not a legal offset. + * 'cie_ptr' is a pointer into our section, not an offset. */ +static int +dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr, + Dwarf_Cie cur_cie_ptr, + Dwarf_Cie * cie_ptr_to_use_out, + Dwarf_Cie head_cie_ptr) +{ + Dwarf_Cie next = 0; + + if (cur_cie_ptr && cie_ptr == cur_cie_ptr->ci_cie_start) { + /* Usually, we use the same cie again and again. */ + *cie_ptr_to_use_out = cur_cie_ptr; + return DW_DLV_OK; + } + for (next = head_cie_ptr; next; next = next->ci_next) { + if (cie_ptr == next->ci_cie_start) { + *cie_ptr_to_use_out = next; + return DW_DLV_OK; + } + } + return DW_DLV_NO_ENTRY; +} + + +/* We have a valid cie_ptr_val that has not been + * turned into an internal Cie yet. Do so now. + * Returns DW_DLV_OK or DW_DLV_ERROR, never + * DW_DLV_NO_ENTRY. + + 'section_ptr' - Points to first byte of section data. + 'section_length' - Length of the section, in bytes. + 'frame_ptr_end' - Points 1-past last byte of section data. + * */ +static int +dwarf_create_cie_from_start(Dwarf_Debug dbg, + Dwarf_Small * cie_ptr_val, + Dwarf_Small * section_ptr, + Dwarf_Unsigned section_index, + Dwarf_Unsigned section_length, + Dwarf_Small * frame_ptr_end, + Dwarf_Unsigned cie_id_value, + Dwarf_Unsigned cie_count, + int use_gnu_cie_calc, + Dwarf_Cie * cie_ptr_to_use_out, + Dwarf_Error * error) +{ + struct cie_fde_prefix_s prefix; + int res = DW_DLV_ERROR; + Dwarf_Small *frame_ptr = cie_ptr_val; + + if (frame_ptr < section_ptr || frame_ptr > frame_ptr_end) { + _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD); + return DW_DLV_ERROR; + } + /* First read in the 'common prefix' to figure out what * we are to + do with this entry. If it is not a cie * we are in big trouble. */ + memset(&prefix, 0, sizeof(prefix)); + res = dwarf_read_cie_fde_prefix(dbg, frame_ptr, section_ptr, + section_index, section_length, + &prefix, error); + if (res == DW_DLV_ERROR) { + return res; + } + if (res == DW_DLV_NO_ENTRY) { + /* error. */ + _dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR); + return DW_DLV_ERROR; + + } + + if (prefix.cf_cie_id != cie_id_value) { + _dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR); + return DW_DLV_ERROR; + } + frame_ptr = prefix.cf_addr_after_prefix; + res = dwarf_create_cie_from_after_start(dbg, + &prefix, + section_ptr, + frame_ptr, + cie_count, + use_gnu_cie_calc, + cie_ptr_to_use_out, error); + return res; + +} + + +/* This is for gnu eh frames, the 'z' case. + We find the letter involved + Return the augmentation character and, if applicable, + the personality routine address. + + personality_routine_out - + if 'P' is augchar, is personality handler addr. + Otherwise is not set. + aug_data - if 'P' points to data space of the + aug_data_len - length of areas aug_data points to. + +*/ +#if 0 +/* For debugging only. */ +void +dump_bytes(Dwarf_Small * start, long len) +{ + Dwarf_Small *end = start + len; + Dwarf_Small *cur = start; + + for (; cur < end; cur++) { + printf(" byte %d, data %02x\n", (int) (cur - start), *cur); + } + +} +#endif +static int +gnu_aug_encodings(Dwarf_Debug dbg, char *augmentation, + Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len, + Dwarf_Half address_size, + unsigned char *pers_hand_enc_out, + unsigned char *lsda_enc_out, + unsigned char *fde_begin_enc_out, + Dwarf_Addr * gnu_pers_addr_out) +{ + char *nc = 0; + Dwarf_Small *cur_aug_p = aug_data; + Dwarf_Small *end_aug_p = aug_data + aug_data_len; + + for (nc = augmentation; *nc; ++nc) { + char c = *nc; + + switch (c) { + case 'z': + /* Means that the augmentation data is present. */ + continue; + + case 'S': + /* Indicates this is a signal stack frame. Debuggers have to do + special handling. We don't need to do more than print this flag at + the right time, though (see dwarfdump where it prints the augmentation + string). + A signal stack frame (in some OS's) can only be + unwound (backtraced) by knowing it is a signal stack frame + (perhaps by noticing the name of the function for the stack frame + if the name can be found somehow) and figuring + out (or knowing) how the kernel and libc pushed a structure + onto the stack and loading registers from that structure. + Totally different from normal stack unwinding. + This flag gives an unwinder a big leg up by decoupling the + 'hint: this is a stack frame' from knowledge like + the function name (the name might be unavailable at unwind time). + */ + break; + + case 'L': + if (cur_aug_p > end_aug_p) { + return DW_DLV_ERROR; + } + *lsda_enc_out = *(unsigned char *) cur_aug_p; + ++cur_aug_p; + break; + case 'R': + /* Followed by a one byte argument giving the + pointer encoding for the address pointers in the fde. */ + if (cur_aug_p >= end_aug_p) { + return DW_DLV_ERROR; + } + *fde_begin_enc_out = *(unsigned char *) cur_aug_p; + ++cur_aug_p; + break; + case 'P':{ + int res = DW_DLV_ERROR; + Dwarf_Small *updated_aug_p = 0; + unsigned char encoding = 0; + + if (cur_aug_p >= end_aug_p) { + return DW_DLV_ERROR; + } + encoding = *(unsigned char *) cur_aug_p; + *pers_hand_enc_out = encoding; + ++cur_aug_p; + if (cur_aug_p > end_aug_p) { + return DW_DLV_ERROR; + } + /* DW_EH_PE_pcrel makes no sense here, so we turn it + off via a section pointer of NULL. */ + res = read_encoded_ptr(dbg, + (Dwarf_Small *) NULL, + cur_aug_p, + encoding, + address_size, + gnu_pers_addr_out, + &updated_aug_p); + if (res != DW_DLV_OK) { + return res; + } + cur_aug_p = updated_aug_p; + if (cur_aug_p > end_aug_p) { + return DW_DLV_ERROR; + } + } + break; + default: + return DW_DLV_ERROR; + + } + } + + return DW_DLV_OK; +} + +/* Given augmentation character (the encoding) giving the +address format, read the address from input_field +and return an incremented value 1 past the input bytes of the +address. +Push the address read back thru the *addr pointer. +See LSB (Linux Standar Base) exception handling documents. +*/ +static int +read_encoded_ptr(Dwarf_Debug dbg, + Dwarf_Small * section_pointer, + Dwarf_Small * input_field, + int gnu_encoding, + Dwarf_Half address_size, + Dwarf_Unsigned * addr, + Dwarf_Small ** input_field_updated) +{ + Dwarf_Word length = 0; + int value_type = gnu_encoding & 0xf; + Dwarf_Small *input_field_original = input_field; + + if (gnu_encoding == 0xff) { + /* There is no data here. */ + + *addr = 0; + *input_field_updated = input_field; + /* Should we return DW_DLV_NO_ENTRY? */ + return DW_DLV_OK; + } + switch (value_type) { + case DW_EH_PE_absptr:{ + /* value_type is zero. Treat as pointer size of the object. + */ + Dwarf_Unsigned ret_value = 0; + + READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, + input_field, address_size); + *addr = ret_value; + *input_field_updated = input_field + address_size; + } + break; + case DW_EH_PE_uleb128:{ + Dwarf_Unsigned val = _dwarf_decode_u_leb128(input_field, + &length); + + *addr = val; + *input_field_updated = input_field + length; + } + break; + case DW_EH_PE_udata2:{ + Dwarf_Unsigned ret_value = 0; + + READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, + input_field, 2); + *addr = ret_value; + *input_field_updated = input_field + 2; + } + break; + + case DW_EH_PE_udata4:{ + + Dwarf_Unsigned ret_value = 0; + + /* ASSERT: sizeof(Dwarf_ufixed) == 4 */ + READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, + input_field, sizeof(Dwarf_ufixed)); + *addr = ret_value; + *input_field_updated = input_field + sizeof(Dwarf_ufixed); + } + break; + + case DW_EH_PE_udata8:{ + Dwarf_Unsigned ret_value = 0; + + /* ASSERT: sizeof(Dwarf_Unsigned) == 8 */ + READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, + input_field, sizeof(Dwarf_Unsigned)); + *addr = ret_value; + *input_field_updated = input_field + sizeof(Dwarf_Unsigned); + } + break; + + case DW_EH_PE_sleb128:{ + Dwarf_Signed val = _dwarf_decode_s_leb128(input_field, + &length); + + *addr = (Dwarf_Unsigned) val; + *input_field_updated = input_field + length; + } + break; + case DW_EH_PE_sdata2:{ + Dwarf_Unsigned val = 0; + + READ_UNALIGNED(dbg, val, Dwarf_Unsigned, input_field, 2); + SIGN_EXTEND(val, 2); + *addr = (Dwarf_Unsigned) val; + *input_field_updated = input_field + 2; + } + break; + + case DW_EH_PE_sdata4:{ + Dwarf_Unsigned val = 0; + + /* ASSERT: sizeof(Dwarf_ufixed) == 4 */ + READ_UNALIGNED(dbg, val, + Dwarf_Unsigned, input_field, + sizeof(Dwarf_ufixed)); + SIGN_EXTEND(val, sizeof(Dwarf_ufixed)); + *addr = (Dwarf_Unsigned) val; + *input_field_updated = input_field + sizeof(Dwarf_ufixed); + } + break; + case DW_EH_PE_sdata8:{ + Dwarf_Unsigned val = 0; + + /* ASSERT: sizeof(Dwarf_Unsigned) == 8 */ + READ_UNALIGNED(dbg, val, + Dwarf_Unsigned, input_field, + sizeof(Dwarf_Unsigned)); + *addr = (Dwarf_Unsigned) val; + *input_field_updated = input_field + sizeof(Dwarf_Unsigned); + } + break; + default: + return DW_DLV_ERROR; + + }; + /* The ELF ABI for gnu does not document the meaning of + DW_EH_PE_pcrel, which is awkward. It apparently means the value + we got above is pc-relative (meaning section-relative), so we + adjust the value. Section_pointer may be null if it is known + DW_EH_PE_pcrel cannot apply, such as for .debug_frame or for an + address-range value. */ + if (section_pointer && ((gnu_encoding & 0x70) == DW_EH_PE_pcrel)) { + /* Address (*addr) above is pc relative with respect to a + section. Add to the offset the base address (from elf) of + section and the distance of the field we are reading from + the section-beginning to get the actual address. */ + /* ASSERT: input_field_original >= section_pointer */ + Dwarf_Unsigned distance = + input_field_original - section_pointer; + *addr += dbg->de_debug_frame_eh_gnu.dss_addr + distance; + } + + return DW_DLV_OK; +} + + + + +/* + All augmentation string checking done here now. + + For .eh_frame, gcc from 3.3 uses the z style, earlier used + only "eh" as augmentation. We don't yet handle + decoding .eh_frame with the z style extensions like L P. + + These are nasty heuristics, but then that's life + as augmentations are implementation specific. +*/ +/* ARGSUSED */ +enum Dwarf_augmentation_type +_dwarf_get_augmentation_type(Dwarf_Debug dbg, + Dwarf_Small * augmentation_string, + int is_gcc_eh_frame) +{ + enum Dwarf_augmentation_type t = aug_unknown; + char *ag_string = (char *) augmentation_string; + + if (ag_string[0] == 0) { + /* Empty string. We'll just guess that we know what this means: + standard dwarf2/3 with no implementation-defined fields. */ + t = aug_empty_string; + } else if (strcmp(ag_string, DW_DEBUG_FRAME_AUGMENTER_STRING) == 0) { + /* The string is "mti v1". Used internally at SGI, probably + never shipped. Replaced by "z". Treat like 'nothing + special'. */ + t = aug_irix_mti_v1; + } else if (ag_string[0] == 'z') { + /* If it's IRIX cc, z means aug_irix_exception_table. z1 z2 + were designed as for IRIX CC, but never implemented */ + /* If it's gcc, z may be any of several things. "z" or z + followed optionally followed by one or more of L R P, each + of which means a value may be present. Should be in eh_frame + only, I think. */ + if (is_gcc_eh_frame) { + t = aug_gcc_eh_z; + } else if (ag_string[1] == 0) { + /* This is the normal IRIX C++ case, where there is an + offset into a table in each fde. The table being for + IRIX CC exception handling. */ + /* DW_CIE_AUGMENTER_STRING_V0 "z" */ + t = aug_irix_exception_table; + } /* Else unknown. */ + } else if (strncmp(ag_string, "eh", 2) == 0) { + /* gcc .eh_frame augmentation for egcs and gcc 2.x, at least + for x86. */ + t = aug_eh; + } else if (strcmp(ag_string, "armcc+") == 0) { + /* Arm uses this string to mean a bug in + in Arm compilers was fixed, changing to the standard + calculation of the CFA. See + http://sourceware.org/ml/gdb-patches/2006-12/msg00249.html + for details. */ + t = aug_armcc; + } else { + + } + return t; +} + +/* Using augmentation, and version + read in the augmentation data for GNU eh. + + Return DW_DLV_OK if we succeeded, + DW_DLV_ERR if we fail. + + On success, update 'size_of_augmentation_data' with + the length of the fields that are part of augmentation (so the + caller can increment frame_ptr appropriately). + + 'frame_ptr' points within section. + 'section_pointer' points to section base address in memory. +*/ +/* ARGSUSED */ +static int +get_gcc_eh_augmentation(Dwarf_Debug dbg, Dwarf_Small * frame_ptr, + unsigned long *size_of_augmentation_data, + enum Dwarf_augmentation_type augtype, + Dwarf_Small * section_pointer, + Dwarf_Small * fde_eh_encoding_out, + char *augmentation) +{ + char *suffix = 0; + unsigned long augdata_size = 0; + + if (augtype == aug_gcc_eh_z) { + /* Has leading 'z'. */ + Dwarf_Word leb128_length = 0; + + /* Dwarf_Unsigned eh_value = */ + _dwarf_decode_u_leb128(frame_ptr, &leb128_length); + augdata_size += leb128_length; + frame_ptr += leb128_length; + suffix = augmentation + 1; + } else { + /* Prefix is 'eh'. As in gcc 3.2. No suffix present + apparently. */ + suffix = augmentation + 2; + } + for (; *suffix; ++suffix) { + /* We have no idea what this is as yet. Some extensions beyond + dwarf exist which we do not yet handle. */ + return DW_DLV_ERROR; + + } + + *size_of_augmentation_data = augdata_size; + return DW_DLV_OK; +} + + +/* Make the 'cie_id_addr' consistent across .debug_frame and .eh_frame. + Calculate a pointer into section bytes given a cie_id, which is + trivial for .debug_frame, but a bit more work for .eh_frame. +*/ +static Dwarf_Small * +get_cieptr_given_offset(Dwarf_Unsigned cie_id_value, + int use_gnu_cie_calc, + Dwarf_Small * section_ptr, + Dwarf_Small * cie_id_addr) +{ + Dwarf_Small *cieptr = 0; + + if (use_gnu_cie_calc) { + /* cie_id value is offset, in section, of the cie_id itself, to + use vm ptr of the value, less the value, to get to the cie + itself. In addition, munge *cie_id_addr to look *as if* it + was from real dwarf. */ + cieptr = (Dwarf_Small *)(uintptr_t) + ((Dwarf_Unsigned)(uintptr_t)cie_id_addr) - + ((Dwarf_Unsigned) cie_id_value); + } else { + /* Traditional dwarf section offset is in cie_id */ + cieptr = (section_ptr + cie_id_value); + } + return cieptr; +} + +/* To properly release all spaced used. + Earlier approaches (before July 15, 2005) + letting client do the dealloc directly left + some data allocated. + This is directly called by consumer code. +*/ +void +dwarf_fde_cie_list_dealloc(Dwarf_Debug dbg, + Dwarf_Cie * cie_data, + Dwarf_Signed cie_element_count, + Dwarf_Fde * fde_data, + Dwarf_Signed fde_element_count) +{ + Dwarf_Signed i = 0; + + for (i = 0; i < cie_element_count; ++i) { + Dwarf_Frame frame = cie_data[i]->ci_initial_table; + + if (frame) + dwarf_dealloc(dbg, frame, DW_DLA_FRAME); + dwarf_dealloc(dbg, cie_data[i], DW_DLA_CIE); + } + for (i = 0; i < fde_element_count; ++i) { + dwarf_dealloc(dbg, fde_data[i], DW_DLA_FDE); + } + if (cie_data) + dwarf_dealloc(dbg, cie_data, DW_DLA_LIST); + if (fde_data) + dwarf_dealloc(dbg, fde_data, DW_DLA_LIST); + +} diff --git a/usr/src/lib/libdwarf/common/dwarf_frame3.c b/usr/src/lib/libdwarf/common/dwarf_frame3.c new file mode 100644 index 0000000000..7bd8ec86d5 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_frame3.c @@ -0,0 +1,290 @@ +/* + + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include +#include "dwarf_frame.h" +#include "dwarf_arange.h" /* using Arange as a way to build a list */ + +/* + Used by rqs (an IRIX application). + Not needed except for that one application. + Should be moved to its own source file since + it is so rarely needed. + Returns DW_DLV_OK if returns the arrays. + Returns DW_DLV_NO_ENTRY if no section. ?? (How do I tell?) + Returns DW_DLV_ERROR if there is an error. + + Uses DW_FRAME_CFA_COL because IRIX is only DWARF2 + and that is what IRIX compilers and compatible + compilers support on IRIX. +*/ +int +_dwarf_frame_address_offsets(Dwarf_Debug dbg, Dwarf_Addr ** addrlist, + Dwarf_Off ** offsetlist, + Dwarf_Signed * returncount, + Dwarf_Error * err) +{ + int retval = DW_DLV_OK; + int res = DW_DLV_ERROR; + Dwarf_Cie *cie_data; + Dwarf_Signed cie_count; + Dwarf_Fde *fde_data; + Dwarf_Signed fde_count; + Dwarf_Signed i; + Dwarf_Frame_Op *frame_inst; + Dwarf_Fde fdep; + Dwarf_Cie ciep; + Dwarf_Chain curr_chain = 0; + Dwarf_Chain head_chain = 0; + Dwarf_Chain prev_chain = 0; + Dwarf_Arange arange; + Dwarf_Unsigned arange_count = 0; + Dwarf_Addr *arange_addrs = 0; + Dwarf_Off *arange_offsets = 0; + + res = dwarf_get_fde_list(dbg, &cie_data, &cie_count, + &fde_data, &fde_count, err); + if (res != DW_DLV_OK) { + return res; + } + + res = _dwarf_load_section(dbg, &dbg->de_debug_frame, err); + if (res != DW_DLV_OK) { + return res; + } + + for (i = 0; i < cie_count; i++) { + Dwarf_Off instoff = 0; + Dwarf_Signed initial_instructions_length = 0; + Dwarf_Small *instr_end = 0; + Dwarf_Sword icount = 0; + int j = 0; + int dw_err; + + ciep = cie_data[i]; + instoff = ciep->ci_cie_instr_start - dbg->de_debug_frame.dss_data; + initial_instructions_length = ciep->ci_length + + ciep->ci_length_size + ciep->ci_extension_size - + (ciep->ci_cie_instr_start - ciep->ci_cie_start); + instr_end = ciep->ci_cie_instr_start + + initial_instructions_length; + res = _dwarf_exec_frame_instr( /* make_instr */ true, + &frame_inst, + /* search_pc= */ false, + /* search_pc_val= */ 0, + /* location */ 0, + ciep->ci_cie_instr_start, + instr_end, + /* Dwarf_frame= */ 0, + /* cie= */ 0, + dbg, + DW_FRAME_CFA_COL, + &icount, &dw_err); + if (res == DW_DLV_ERROR) { + _dwarf_error(dbg, err, dw_err); + return (res); + } else if (res == DW_DLV_NO_ENTRY) { + continue; + } + + for (j = 0; j < icount; ++j) { + Dwarf_Frame_Op *finst = frame_inst + j; + + if (finst->fp_base_op == 0 && finst->fp_extended_op == 1) { + /* is DW_CFA_set_loc */ + Dwarf_Addr add = (Dwarf_Addr) finst->fp_offset; + Dwarf_Off off = finst->fp_instr_offset + instoff; + + arange = (Dwarf_Arange) + _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1); + if (arange == NULL) { + _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + arange->ar_address = add; + arange->ar_info_offset = off; + arange_count++; + curr_chain = (Dwarf_Chain) + _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); + if (curr_chain == NULL) { + _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + curr_chain->ch_item = arange; + if (head_chain == NULL) + head_chain = prev_chain = curr_chain; + else { + prev_chain->ch_next = curr_chain; + prev_chain = curr_chain; + } + } + } + dwarf_dealloc(dbg, frame_inst, DW_DLA_FRAME_BLOCK); + + } + for (i = 0; i < fde_count; i++) { + Dwarf_Small *instr_end = 0; + Dwarf_Sword icount = 0; + Dwarf_Signed instructions_length = 0; + Dwarf_Off instoff = 0; + Dwarf_Off off = 0; + Dwarf_Addr addr = 0; + int j = 0; + int dw_err; + + fdep = fde_data[i]; + off = fdep->fd_initial_loc_pos - dbg->de_debug_frame.dss_data; + addr = fdep->fd_initial_location; + arange = (Dwarf_Arange) + _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1); + if (arange == NULL) { + _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + arange->ar_address = addr; + arange->ar_info_offset = off; + arange_count++; + curr_chain = (Dwarf_Chain) + _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); + if (curr_chain == NULL) { + _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + curr_chain->ch_item = arange; + if (head_chain == NULL) + head_chain = prev_chain = curr_chain; + else { + prev_chain->ch_next = curr_chain; + prev_chain = curr_chain; + } + + + instoff = fdep->fd_fde_instr_start - dbg->de_debug_frame.dss_data; + instructions_length = fdep->fd_length + + fdep->fd_length_size + fdep->fd_extension_size - + (fdep->fd_fde_instr_start - fdep->fd_fde_start); + instr_end = fdep->fd_fde_instr_start + instructions_length; + res = _dwarf_exec_frame_instr( /* make_instr */ true, + &frame_inst, + /* search_pc= */ false, + /* search_pc_val= */ 0, + /* location */ 0, + fdep->fd_fde_instr_start, + instr_end, + /* Dwarf_frame= */ 0, + /* cie= */ 0, + dbg, + DW_FRAME_CFA_COL, + &icount, &dw_err); + if (res == DW_DLV_ERROR) { + _dwarf_error(dbg, err, dw_err); + return (res); + } else if (res == DW_DLV_NO_ENTRY) { + continue; + } + + for (j = 0; j < icount; ++j) { + Dwarf_Frame_Op *finst2 = frame_inst + j; + + if (finst2->fp_base_op == 0 && finst2->fp_extended_op == 1) { + /* is DW_CFA_set_loc */ + Dwarf_Addr add = (Dwarf_Addr) finst2->fp_offset; + Dwarf_Off off = finst2->fp_instr_offset + instoff; + + arange = (Dwarf_Arange) + _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1); + if (arange == NULL) { + _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + arange->ar_address = add; + arange->ar_info_offset = off; + arange_count++; + curr_chain = (Dwarf_Chain) + _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); + if (curr_chain == NULL) { + _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + curr_chain->ch_item = arange; + if (head_chain == NULL) + head_chain = prev_chain = curr_chain; + else { + prev_chain->ch_next = curr_chain; + prev_chain = curr_chain; + } + + } + } + dwarf_dealloc(dbg, frame_inst, DW_DLA_FRAME_BLOCK); + + } + dwarf_dealloc(dbg, fde_data, DW_DLA_LIST); + dwarf_dealloc(dbg, cie_data, DW_DLA_LIST); + arange_addrs = (Dwarf_Addr *) + _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count); + if (arange_addrs == NULL) { + _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + arange_offsets = (Dwarf_Off *) + _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count); + if (arange_offsets == NULL) { + _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + curr_chain = head_chain; + for (i = 0; i < arange_count; i++) { + Dwarf_Arange ar = curr_chain->ch_item; + + arange_addrs[i] = ar->ar_address; + arange_offsets[i] = ar->ar_info_offset; + prev_chain = curr_chain; + curr_chain = curr_chain->ch_next; + dwarf_dealloc(dbg, ar, DW_DLA_ARANGE); + dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN); + } + *returncount = arange_count; + *offsetlist = arange_offsets; + *addrlist = arange_addrs; + return retval; +} diff --git a/usr/src/lib/libdwarf/common/dwarf_funcs.c b/usr/src/lib/libdwarf/common/dwarf_funcs.c new file mode 100644 index 0000000000..8d725ae33f --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_funcs.c @@ -0,0 +1,130 @@ +/* + + Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include "dwarf_funcs.h" +#include "dwarf_global.h" + +int +dwarf_get_funcs(Dwarf_Debug dbg, + Dwarf_Func ** funcs, + Dwarf_Signed * ret_func_count, Dwarf_Error * error) +{ + int res = _dwarf_load_section(dbg, &dbg->de_debug_funcnames,error); + if (res != DW_DLV_OK) { + return res; + } + + return _dwarf_internal_get_pubnames_like_data(dbg, + dbg->de_debug_funcnames.dss_data, + dbg->de_debug_funcnames.dss_size, + (Dwarf_Global **) funcs, /* Type punning for sections with identical format. */ + ret_func_count, + error, + DW_DLA_FUNC_CONTEXT, + DW_DLA_FUNC, + DW_DLE_DEBUG_FUNCNAMES_LENGTH_BAD, + DW_DLE_DEBUG_FUNCNAMES_VERSION_ERROR); +} + +/* Deallocating fully requires deallocating the list + and all entries. But some internal data is + not exposed, so we need a function with internal knowledge. +*/ + +void +dwarf_funcs_dealloc(Dwarf_Debug dbg, Dwarf_Func * dwgl, + Dwarf_Signed count) +{ + _dwarf_internal_globals_dealloc(dbg, (Dwarf_Global *) dwgl, + count, + DW_DLA_FUNC_CONTEXT, + DW_DLA_FUNC, DW_DLA_LIST); + return; +} + + + +int +dwarf_funcname(Dwarf_Func func_in, char **ret_name, Dwarf_Error * error) +{ + Dwarf_Global func = (Dwarf_Global) func_in; + + if (func == NULL) { + _dwarf_error(NULL, error, DW_DLE_FUNC_NULL); + return (DW_DLV_ERROR); + } + + *ret_name = (char *) (func->gl_name); + return DW_DLV_OK; +} + +int +dwarf_func_die_offset(Dwarf_Func func_in, + Dwarf_Off * return_offset, Dwarf_Error * error) +{ + Dwarf_Global func = (Dwarf_Global) func_in; + + return dwarf_global_die_offset(func, return_offset, error); +} + + +int +dwarf_func_cu_offset(Dwarf_Func func_in, + Dwarf_Off * return_offset, Dwarf_Error * error) +{ + Dwarf_Global func = (Dwarf_Global) func_in; + + return dwarf_global_cu_offset(func, return_offset, error); +} + + +int +dwarf_func_name_offsets(Dwarf_Func func_in, + char **ret_func_name, + Dwarf_Off * die_offset, + Dwarf_Off * cu_die_offset, Dwarf_Error * error) +{ + Dwarf_Global func = (Dwarf_Global) func_in; + + return dwarf_global_name_offsets(func, + ret_func_name, + die_offset, cu_die_offset, error); +} diff --git a/usr/src/lib/libdwarf/common/dwarf_funcs.h b/usr/src/lib/libdwarf/common/dwarf_funcs.h new file mode 100644 index 0000000000..bf91c32157 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_funcs.h @@ -0,0 +1,42 @@ +/* + + Copyright (C) 2000, 2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + + +typedef struct Dwarf_Func_Context_s *Dwarf_Func_Context; + + +/* struct never completed: see dwarf_global.h */ diff --git a/usr/src/lib/libdwarf/common/dwarf_global.c b/usr/src/lib/libdwarf/common/dwarf_global.c new file mode 100644 index 0000000000..d1c090fa43 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_global.c @@ -0,0 +1,607 @@ +/* + + Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include "dwarf_global.h" + + +#ifdef __sgi /* __sgi should only be defined for IRIX/MIPS. */ +/* The 'fixup' here intended for IRIX targets only. + With a 2+GB Elf64 IRIX executable (under 4GB in size), + some DIE offsets wrongly + got the 32bit upper bit sign extended. For the cu-header + offset in the .debug_pubnames section and in the + .debug_aranges section. + the 'varp' here is a pointer to an offset into .debug_info. + We fix up the offset here if it seems advisable.. + + As of June 2005 we have identified a series of mistakes + in ldx64 that can cause this (64 bit values getting passed + thru 32-bit signed knothole). +*/ +void +_dwarf_fix_up_offset_irix(Dwarf_Debug dbg, + Dwarf_Unsigned * varp, char *caller_site_name) +{ + + Dwarf_Unsigned var = *varp; + +#define UPPER33 0xffffffff80000000LL +#define LOWER32 0xffffffffLL + /* Restrict the hack to the known case. Upper 32 bits erroneously + sign extended from lower 32 upper bit. */ + if ((var & UPPER33) == UPPER33) { + var &= LOWER32; + /* Apply the fix. Dreadful hack. */ + *varp = var; + } +#undef UPPER33 +#undef LOWER32 + return; +} +#endif + + +int +dwarf_get_globals(Dwarf_Debug dbg, + Dwarf_Global ** globals, + Dwarf_Signed * return_count, Dwarf_Error * error) +{ + int res = _dwarf_load_section(dbg, &dbg->de_debug_pubnames,error); + if (res != DW_DLV_OK) { + return res; + } + + return _dwarf_internal_get_pubnames_like_data(dbg, + dbg->de_debug_pubnames.dss_data, + dbg->de_debug_pubnames.dss_size, + globals, + return_count, + error, + DW_DLA_GLOBAL_CONTEXT, + DW_DLA_GLOBAL, + DW_DLE_PUBNAMES_LENGTH_BAD, + DW_DLE_PUBNAMES_VERSION_ERROR); + +} + +/* Deallocating fully requires deallocating the list + and all entries. But some internal data is + not exposed, so we need a function with internal knowledge. +*/ + +void +dwarf_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl, + Dwarf_Signed count) +{ + _dwarf_internal_globals_dealloc(dbg, dwgl, + count, + DW_DLA_GLOBAL_CONTEXT, + DW_DLA_GLOBAL, DW_DLA_LIST); + return; +} + +void +_dwarf_internal_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl, + Dwarf_Signed count, + int context_code, + int global_code, int list_code) +{ + Dwarf_Signed i; + struct Dwarf_Global_Context_s *gcp = 0; + struct Dwarf_Global_Context_s *lastgcp = 0; + + for (i = 0; i < count; i++) { + Dwarf_Global dgb = dwgl[i]; + + gcp = dgb->gl_context; + + if (lastgcp != gcp) { + lastgcp = gcp; + dwarf_dealloc(dbg, gcp, context_code); + } + dwarf_dealloc(dbg, dgb, global_code); + } + dwarf_dealloc(dbg, dwgl, list_code); + return; +} + + +/* Sweeps the complete section. +*/ +int +_dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg, + Dwarf_Small * section_data_ptr, + Dwarf_Unsigned section_length, + Dwarf_Global ** globals, + Dwarf_Signed * return_count, + Dwarf_Error * error, + int context_code, + int global_code, + int length_err_num, + int version_err_num) +{ + + + Dwarf_Small *pubnames_like_ptr = 0; + + + + /* Points to the context for the current set of global names, and + contains information to identify the compilation-unit that the + set refers to. */ + Dwarf_Global_Context pubnames_context = 0; + + Dwarf_Half version = 0; + + /* + Offset from the start of compilation-unit for the current + global. */ + Dwarf_Off die_offset_in_cu = 0; + + Dwarf_Unsigned global_count = 0; + + /* Points to the current global read. */ + Dwarf_Global global = 0; + + /* Used to chain the Dwarf_Global_s structs for creating contiguous + list of pointers to the structs. */ + Dwarf_Chain curr_chain = 0; + Dwarf_Chain prev_chain = 0; + Dwarf_Chain head_chain = 0; + + /* Points to contiguous block of Dwarf_Global's to be returned. */ + Dwarf_Global *ret_globals = 0; + + /* Temporary counter. */ + Dwarf_Unsigned i = 0; + + + + + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + /* We will eventually need the .debug_info data. Load it now. */ + if (!dbg->de_debug_info.dss_data) { + int res = _dwarf_load_debug_info(dbg, error); + + if (res != DW_DLV_OK) { + return res; + } + } + + if (section_data_ptr == NULL) { + return (DW_DLV_NO_ENTRY); + } + + pubnames_like_ptr = section_data_ptr; + do { + Dwarf_Unsigned length = 0; + int local_extension_size = 0; + int local_length_size = 0; + + /* Some compilers emit padding at the end of each cu's area. + pubnames_ptr_past_end_cu records the true area end for this + cu's data. Essentially the length in the header and the 0 + terminator of the data are redundant information. The + dwarf2/3 spec does not mention what to do if the length is + past the 0 terminator. So we take any bytes left after the 0 + as padding and ignore them. */ + Dwarf_Small *pubnames_ptr_past_end_cu = 0; + + + pubnames_context = (Dwarf_Global_Context) + _dwarf_get_alloc(dbg, context_code, 1); + if (pubnames_context == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + /* READ_AREA_LENGTH updates pubnames_like_ptr for consumed + bytes. */ + READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned, + pubnames_like_ptr, local_length_size, + local_extension_size); + pubnames_context->pu_length_size = local_length_size; + pubnames_context->pu_extension_size = local_extension_size; + pubnames_context->pu_dbg = dbg; + + pubnames_ptr_past_end_cu = pubnames_like_ptr + length; + + READ_UNALIGNED(dbg, version, Dwarf_Half, + pubnames_like_ptr, sizeof(Dwarf_Half)); + pubnames_like_ptr += sizeof(Dwarf_Half); + if (version != CURRENT_VERSION_STAMP) { + _dwarf_error(dbg, error, version_err_num); + return (DW_DLV_ERROR); + } + + /* Offset of CU header in debug section. */ + READ_UNALIGNED(dbg, pubnames_context->pu_offset_of_cu_header, + Dwarf_Off, pubnames_like_ptr, + pubnames_context->pu_length_size); + pubnames_like_ptr += pubnames_context->pu_length_size; + + FIX_UP_OFFSET_IRIX_BUG(dbg, + pubnames_context->pu_offset_of_cu_header, + "pubnames cu header offset"); + + + READ_UNALIGNED(dbg, pubnames_context->pu_info_length, + Dwarf_Unsigned, pubnames_like_ptr, + pubnames_context->pu_length_size); + pubnames_like_ptr += pubnames_context->pu_length_size; + + if (pubnames_like_ptr > (section_data_ptr + section_length)) { + _dwarf_error(dbg, error, length_err_num); + return (DW_DLV_ERROR); + } + + /* Read initial offset (of DIE within CU) of a pubname, final + entry is not a pair, just a zero offset. */ + READ_UNALIGNED(dbg, die_offset_in_cu, Dwarf_Off, + pubnames_like_ptr, + pubnames_context->pu_length_size); + pubnames_like_ptr += pubnames_context->pu_length_size; + FIX_UP_OFFSET_IRIX_BUG(dbg, + die_offset_in_cu, "offset of die in cu"); + + /* Loop thru pairs. DIE off with CU followed by string. */ + while (die_offset_in_cu != 0) { + + /* Already read offset, pubnames_like_ptr now points to the + string. */ + global = + (Dwarf_Global) _dwarf_get_alloc(dbg, global_code, 1); + if (global == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + global_count++; + + global->gl_context = pubnames_context; + + global->gl_named_die_offset_within_cu = die_offset_in_cu; + + global->gl_name = pubnames_like_ptr; + + pubnames_like_ptr = pubnames_like_ptr + + strlen((char *) pubnames_like_ptr) + 1; + + + /* finish off current entry chain */ + curr_chain = + (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); + if (curr_chain == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + /* Put current global on singly_linked list. */ + curr_chain->ch_item = (Dwarf_Global) global; + + if (head_chain == NULL) + head_chain = prev_chain = curr_chain; + else { + prev_chain->ch_next = curr_chain; + prev_chain = curr_chain; + } + + /* read offset for the *next* entry */ + READ_UNALIGNED(dbg, die_offset_in_cu, Dwarf_Off, + pubnames_like_ptr, + pubnames_context->pu_length_size); + + pubnames_like_ptr += pubnames_context->pu_length_size; + FIX_UP_OFFSET_IRIX_BUG(dbg, + die_offset_in_cu, + "offset of next die in cu"); + + if (pubnames_like_ptr > (section_data_ptr + section_length)) { + _dwarf_error(dbg, error, length_err_num); + return (DW_DLV_ERROR); + } + } + /* ASSERT: die_offset_in_cu == 0 */ + if (pubnames_like_ptr > pubnames_ptr_past_end_cu) { + /* This is some kind of error. This simply cannot happen. + The encoding is wrong or the length in the header for + this cu's contribution is wrong. */ + _dwarf_error(dbg, error, length_err_num); + return (DW_DLV_ERROR); + } + /* If there is some kind of padding at the end of the section, + as emitted by some compilers, skip over that padding and + simply ignore the bytes thus passed-over. With most + compilers, pubnames_like_ptr == pubnames_ptr_past_end_cu at + this point */ + pubnames_like_ptr = pubnames_ptr_past_end_cu; + + } while (pubnames_like_ptr < (section_data_ptr + section_length)); + + /* Points to contiguous block of Dwarf_Global's. */ + ret_globals = (Dwarf_Global *) + _dwarf_get_alloc(dbg, DW_DLA_LIST, global_count); + if (ret_globals == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + /* + Store pointers to Dwarf_Global_s structs in contiguous block, + and deallocate the chain. */ + curr_chain = head_chain; + for (i = 0; i < global_count; i++) { + *(ret_globals + i) = curr_chain->ch_item; + prev_chain = curr_chain; + curr_chain = curr_chain->ch_next; + dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN); + } + + *globals = ret_globals; + *return_count = (Dwarf_Signed) global_count; + return DW_DLV_OK; +} + + +/* + Given a pubnames entry (or other like section entry) + return thru the ret_name pointer + a pointer to the string which is the entry name. + +*/ +int +dwarf_globname(Dwarf_Global glob, char **ret_name, Dwarf_Error * error) +{ + if (glob == NULL) { + _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL); + return (DW_DLV_ERROR); + } + + *ret_name = (char *) (glob->gl_name); + return DW_DLV_OK; +} + + +/* + Given a pubnames entry (or other like section entry) + return thru the ret_off pointer the + global offset of the DIE for this entry. + The global offset is the offset within the .debug_info + section as a whole. +*/ +int +dwarf_global_die_offset(Dwarf_Global global, + Dwarf_Off * ret_off, Dwarf_Error * error) +{ + if (global == NULL) { + _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL); + return (DW_DLV_ERROR); + } + + if (global->gl_context == NULL) { + _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL); + return (DW_DLV_ERROR); + } + + *ret_off = (global->gl_named_die_offset_within_cu + + global->gl_context->pu_offset_of_cu_header); + return DW_DLV_OK; +} + +/* + Given a pubnames entry (or other like section entry) + return thru the ret_off pointer the + offset of the compilation unit header of the + compilation unit the global is part of. + + In early versions of this, the value returned was + the offset of the compilation unit die, and + other cu-local die offsets were faked so adding this to + such a cu-local offset got a true section offset. + Now things do as they say (adding *cu_header_offset to + a cu-local offset gets the section offset). + +*/ +int +dwarf_global_cu_offset(Dwarf_Global global, + Dwarf_Off * cu_header_offset, + Dwarf_Error * error) +{ + Dwarf_Global_Context con = 0; + + if (global == NULL) { + _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL); + return (DW_DLV_ERROR); + } + + con = global->gl_context; + + if (con == NULL) { + _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL); + return (DW_DLV_ERROR); + } + + /* In early libdwarf, this incorrectly returned the offset of the + CU DIE. Now correctly returns the header offset. */ + *cu_header_offset = con->pu_offset_of_cu_header; + + return DW_DLV_OK; +} + +/* + Give back the pubnames entry (or any other like section) + name, symbol DIE offset, and the cu-DIE offset. + + Various errors are possible. + + The string pointer returned thru ret_name is not + dwarf_get_alloc()ed, so no dwarf_dealloc() + DW_DLA_STRING should be applied to it. + +*/ +int +dwarf_global_name_offsets(Dwarf_Global global, + char **ret_name, + Dwarf_Off * die_offset, + Dwarf_Off * cu_die_offset, + Dwarf_Error * error) +{ + Dwarf_Global_Context con = 0; + Dwarf_Debug dbg = 0; + Dwarf_Off off = 0; + + if (global == NULL) { + _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL); + return (DW_DLV_ERROR); + } + + con = global->gl_context; + + if (con == NULL) { + _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL); + return (DW_DLV_ERROR); + } + + off = con->pu_offset_of_cu_header; + /* The offset had better not be too close to the end. If it is, + _dwarf_length_of_cu_header() will step off the end and therefore + must not be used. 10 is a meaningless heuristic, but no CU + header is that small so it is safe. An erroneous offset is due + to a bug in the tool chain. A bug like this has been seen on + IRIX with MIPSpro 7.3.1.3 and an executable > 2GB in size and + with 2 million pubnames entries. */ +#define MIN_CU_HDR_SIZE 10 + dbg = con->pu_dbg; + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + if (dbg->de_debug_info.dss_size && + ((off + MIN_CU_HDR_SIZE) >= dbg->de_debug_info.dss_size)) { + _dwarf_error(NULL, error, DW_DLE_OFFSET_BAD); + return (DW_DLV_ERROR); + } +#undef MIN_CU_HDR_SIZE + if (die_offset != NULL) { + *die_offset = global->gl_named_die_offset_within_cu + off; + } + + *ret_name = (char *) global->gl_name; + + if (cu_die_offset != NULL) { + int res = _dwarf_load_debug_info(dbg, error); + + if (res != DW_DLV_OK) { + return res; + } + /* The offset had better not be too close to the end. If it is, + _dwarf_length_of_cu_header() will step off the end and + therefore must not be used. 10 is a meaningless heuristic, + but no CU header is that small so it is safe. */ + if ((off + 10) >= dbg->de_debug_info.dss_size) { + _dwarf_error(NULL, error, DW_DLE_OFFSET_BAD); + return (DW_DLV_ERROR); + } + *cu_die_offset = off + _dwarf_length_of_cu_header(dbg, off); + } + + + return DW_DLV_OK; +} + +/* + We have the offset to a CU header. + Return thru outFileOffset the offset of the CU DIE. + + New June, 2001. + Used by SGI debuggers. + No error is possible. + + See also dwarf_CU_dieoffset_given_die(). +*/ + +/* ARGSUSED */ +int +dwarf_get_cu_die_offset_given_cu_header_offset(Dwarf_Debug dbg, + Dwarf_Off in_cu_header_offset, + Dwarf_Off * out_cu_die_offset, + Dwarf_Error * err) +{ + Dwarf_Off len = + _dwarf_length_of_cu_header(dbg, in_cu_header_offset); + + Dwarf_Off newoff = in_cu_header_offset + len; + + *out_cu_die_offset = newoff; + return DW_DLV_OK; +} +/* dwarf_CU_dieoffset_given_die returns + the global debug_info section offset of the CU die + that is the CU containing the given (passed-in) die. + This information makes it possible for a consumer to + find and print context information for any die. + + Use dwarf_offdie() passing in the offset this returns + to get a die pointer to the CU die. + */ +int +dwarf_CU_dieoffset_given_die(Dwarf_Die die, + Dwarf_Off* return_offset, + Dwarf_Error* error) +{ + Dwarf_Off dieoff = 0; + Dwarf_CU_Context cucontext = 0; + + CHECK_DIE(die, DW_DLV_ERROR); + cucontext = die->di_cu_context; + dieoff = cucontext->cc_debug_info_offset; + /* The following call cannot fail, so no error check. */ + dwarf_get_cu_die_offset_given_cu_header_offset( + cucontext->cc_dbg, dieoff, return_offset,error); + return DW_DLV_OK; +} diff --git a/usr/src/lib/libdwarf/common/dwarf_global.h b/usr/src/lib/libdwarf/common/dwarf_global.h new file mode 100644 index 0000000000..c2bc2cdcc3 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_global.h @@ -0,0 +1,124 @@ +/* + + Copyright (C) 2000,2004,2005 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + + +typedef struct Dwarf_Global_Context_s *Dwarf_Global_Context; + +/* + This struct contains header information for a set of pubnames. + Essentially, they contain the context for a set of pubnames + belonging to a compilation-unit. + + This is also used for the sgi-specific + weaknames, typenames, varnames, funcnames data: + the structs for those are incomplete and + instances of this are used instead. + + Also used for DWARF3 .debug_pubtypes. + +*/ +struct Dwarf_Global_Context_s { + + /* Length in .debug_pubnames (etc) of a set of names for a + compilation-unit. Dwarf_Word pu_length; The value is not made + available outside libdwarf and not used inside, so no need to + record it. */ + + /* For this context, size of a length. 4 or 8 */ + unsigned char pu_length_size; + + /* For this CU, size of the extension 0 except for dwarf2 extension + 64bit, in which case is 4. */ + unsigned char pu_extension_size; + + /* + Offset into .debug_info of the compilation-unit header (not DIE) + for this set of pubnames. */ + Dwarf_Off pu_offset_of_cu_header; + + /* Size of compilation-unit that these pubnames are in. */ + Dwarf_Unsigned pu_info_length; + + Dwarf_Debug pu_dbg; +}; + + +/* This struct contains information for a single pubname. */ +struct Dwarf_Global_s { + + /* + Offset from the start of the corresponding compilation-unit of + the DIE for the given pubname CU. */ + Dwarf_Off gl_named_die_offset_within_cu; + + /* Points to the given pubname. */ + Dwarf_Small *gl_name; + + /* Context for this pubname. */ + Dwarf_Global_Context gl_context; +}; + +int _dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg, + Dwarf_Small * + section_data_ptr, + Dwarf_Unsigned + section_length, + Dwarf_Global ** globals, + Dwarf_Signed * return_count, + Dwarf_Error * error, + int context_code, + int global_code, + int length_err_num, + int version_err_num); + +void +_dwarf_internal_globals_dealloc( Dwarf_Debug dbg, Dwarf_Global *dwgl, + Dwarf_Signed count, + int context_code, + int global_code, + int list_code); + + +#ifdef __sgi /* __sgi should only be defined for IRIX/MIPS. */ +void _dwarf_fix_up_offset_irix(Dwarf_Debug dbg, + Dwarf_Unsigned *varp, + char *caller_site_name); +#define FIX_UP_OFFSET_IRIX_BUG(ldbg,var,name) _dwarf_fix_up_offset_irix(ldbg,&var,name) +#else +#define FIX_UP_OFFSET_IRIX_BUG(ldbg,var,name) +#endif + diff --git a/usr/src/lib/libdwarf/common/dwarf_harmless.c b/usr/src/lib/libdwarf/common/dwarf_harmless.c new file mode 100644 index 0000000000..16dbe4bc97 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_harmless.c @@ -0,0 +1,226 @@ +/* + + Copyright (C) 2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + +*/ + +/* + This implements _dwarf_insert_harmless_error + and related helper functions for recording + compiler errors that need not make the input + unusable. + + Applications can use dwarf_get_harmless_error_list to + find (and possibly print) a warning about such errors. + + The initial error reported here is + DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE which was a + bug in a specific compiler. + + It is a fixed length circular list to constrain + the space used for errors. + + The assumption is that these errors are exceedingly + rare, and indicate a broken compiler (the one that + produced the object getting the error(s)). + + dh_maxcount is recorded internally as 1 greater than + requested. Hiding the fact we always leave one + slot unused (at least). So a user request for + N slots really gives the user N usable slots. +*/ + + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include +#include "dwarf_frame.h" +#include "dwarf_harmless.h" + + +/* The pointers returned here through errmsg_ptrs_array + become invalidated by any call to libdwarf. Any call. +*/ +int dwarf_get_harmless_error_list(Dwarf_Debug dbg, + unsigned count, + const char ** errmsg_ptrs_array, + unsigned * errs_count) +{ + struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors; + if(!dhp->dh_errors) { + dhp->dh_errs_count = 0; + return DW_DLV_NO_ENTRY; + } + if(dhp->dh_errs_count == 0) { + return DW_DLV_NO_ENTRY; + } + if(errs_count) { + *errs_count = dhp->dh_errs_count; + } + if(count) { + /* NULL terminate the array of pointers */ + --count; + errmsg_ptrs_array[count] = 0; + + if(dhp->dh_next_to_use != dhp->dh_first) { + unsigned i = 0; + unsigned cur = dhp->dh_first; + for(i = 0; cur != dhp->dh_next_to_use; ++i) { + if(i >= count ) { + /* All output spaces are used. */ + break; + } + errmsg_ptrs_array[i] = dhp->dh_errors[cur]; + cur = (cur +1) % dhp->dh_maxcount; + } + errmsg_ptrs_array[i] = 0; + } + } + dhp->dh_next_to_use = 0; + dhp->dh_first = 0; + dhp->dh_errs_count = 0; + return DW_DLV_OK; +} + +/* strncpy does not null-terminate, this does it. */ +static void +safe_strncpy(char *targ, char *src, unsigned spaceavail) +{ + unsigned goodcount = spaceavail-1; + if(spaceavail < 1) { + return; /* impossible */ + } + strncpy(targ,src,goodcount); + targ[goodcount] = 0; +} + +/* Insertion made public is only for testing the harmless error code, + it is not necessarily useful for libdwarf client code aside + from code testing libdwarf. */ +void dwarf_insert_harmless_error(Dwarf_Debug dbg, + char *newerror) +{ + struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors; + unsigned next = 0; + unsigned cur = dhp->dh_next_to_use; + char *msgspace; + if(!dhp->dh_errors) { + dhp->dh_errs_count++; + return; + } + msgspace = dhp->dh_errors[cur]; + safe_strncpy(msgspace, newerror,DW_HARMLESS_ERROR_MSG_STRING_SIZE); + next = (cur+1) % dhp->dh_maxcount; + dhp->dh_errs_count++; + dhp->dh_next_to_use = next; + if (dhp->dh_next_to_use == dhp->dh_first) { + /* Array is full set full invariant. */ + dhp->dh_first = (dhp->dh_first+1) % dhp->dh_maxcount; + } +} + +/* The size of the circular list of strings may be set + and reset as desired. Returns the previous size of + the list. If the list is shortened excess error entries + are simply dropped. + If the reallocation fails the list size is left unchanged. + Do not make this a long list! + + Remember the maxcount we record is 1 > the user count, + so we adjust it so it looks like the user count. +*/ +unsigned dwarf_set_harmless_error_list_size(Dwarf_Debug dbg, + unsigned maxcount ) +{ + struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors; + unsigned prevcount = dhp->dh_maxcount; + if(maxcount != 0) { + ++maxcount; + if(maxcount != dhp->dh_maxcount) { + /* Assign transfers 'ownership' of the malloc areas + to oldarray. */ + struct Dwarf_Harmless_s oldarray = *dhp; + /* Do not double increment the max, the init() func + increments it too. */ + dwarf_harmless_init(dhp,maxcount-1); + if(oldarray.dh_next_to_use != oldarray.dh_first) { + unsigned i = 0; + for(i = oldarray.dh_first; i != oldarray.dh_next_to_use; + i = (i+1)%oldarray.dh_maxcount) { + dwarf_insert_harmless_error(dbg,oldarray.dh_errors[i]); + } + if( oldarray.dh_errs_count > dhp->dh_errs_count) { + dhp->dh_errs_count = oldarray.dh_errs_count; + } + } + dwarf_harmless_cleanout(&oldarray); + } + } + return prevcount-1; +} + +void +dwarf_harmless_init(struct Dwarf_Harmless_s *dhp,unsigned size) +{ + unsigned i = 0; + memset(dhp,0,sizeof(*dhp)); + dhp->dh_maxcount = size +1; + dhp->dh_errors = (char **)malloc(sizeof( char *) *dhp->dh_maxcount); + if (!dhp->dh_errors) { + dhp->dh_maxcount = 0; + return; + } + + for(i = 0; i < dhp->dh_maxcount; ++i) { + char *newstr = + (char *)malloc(DW_HARMLESS_ERROR_MSG_STRING_SIZE); + dhp->dh_errors[i] = newstr; + if(!newstr) { + dhp->dh_maxcount = 0; + /* Let it leak, the leak is a constrained amount. */ + dhp->dh_errors = 0; + return; + } + /* We make the string content well-defined by an initial + NUL byte, but this is not really necessary. */ + newstr[0] = 0; + } +} + +void +dwarf_harmless_cleanout(struct Dwarf_Harmless_s *dhp) +{ + unsigned i = 0; + if(!dhp->dh_errors) { + return; + } + for(i = 0; i < dhp->dh_maxcount; ++i) { + free(dhp->dh_errors[i]); + } + free(dhp->dh_errors); + dhp->dh_errors = 0; + dhp->dh_maxcount = 0; +} + diff --git a/usr/src/lib/libdwarf/common/dwarf_harmless.h b/usr/src/lib/libdwarf/common/dwarf_harmless.h new file mode 100644 index 0000000000..3d4d910ce9 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_harmless.h @@ -0,0 +1,31 @@ +/* + + Copyright (C) 2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + +*/ + + + +void dwarf_harmless_init(struct Dwarf_Harmless_s *dhp,unsigned size); +void dwarf_harmless_cleanout(struct Dwarf_Harmless_s *dhp); + diff --git a/usr/src/lib/libdwarf/common/dwarf_incl.h b/usr/src/lib/libdwarf/common/dwarf_incl.h new file mode 100644 index 0000000000..df2fbf334c --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_incl.h @@ -0,0 +1,66 @@ +/* + + Copyright (C) 2000, 2002, 2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2008-2010 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#ifndef DWARF_INCL_H +#define DWARF_INCL_H +#if (!defined(HAVE_RAW_LIBELF_OK) && defined(HAVE_LIBELF_OFF64_OK) ) +/* At a certain point libelf.h requires _GNU_SOURCE. + here we assume the criteria in configure determine that + usefully. +*/ +#define _GNU_SOURCE 1 +#endif + + +#include "libdwarfdefs.h" +#include + +#ifdef HAVE_ELF_H +#include +#endif + +#include +#include +#include + +#include "dwarf_base_types.h" +#include "dwarf_alloc.h" +#include "dwarf_opaque.h" +#include "dwarf_error.h" +#include "dwarf_util.h" +#endif /* DWARF_INCL_H */ diff --git a/usr/src/lib/libdwarf/common/dwarf_init_finish.c b/usr/src/lib/libdwarf/common/dwarf_init_finish.c new file mode 100644 index 0000000000..1ab9d5fd38 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_init_finish.c @@ -0,0 +1,577 @@ +/* + + Copyright (C) 2000,2002,2003,2004,2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2008-2010 Arxan Technologies, Inc. All Rights Reserved. + Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + +#include "config.h" +#include "dwarf_incl.h" + +#include +#include +#include +#include +#include + +#include "dwarf_incl.h" +#include "malloc_check.h" + +#define DWARF_DBG_ERROR(dbg,errval,retval) \ + _dwarf_error(dbg, error, errval); return(retval); + +#define FALSE 0 +#define TRUE 1 + + + +/* This static is copied to the dbg on dbg init + so that the static need not be referenced at + run time, preserving better locality of + reference. + Value is 0 means do the string check. + Value non-zero means do not do the check. +*/ +static Dwarf_Small _dwarf_assume_string_bad; +static Dwarf_Small _dwarf_apply_relocs = 1; + +/* Call this after calling dwarf_init but before doing anything else. + * It applies to all objects, not just the current object. + */ +int +dwarf_set_reloc_application(int apply) +{ + int oldval = _dwarf_apply_relocs; + _dwarf_apply_relocs = apply; + return oldval; +} + +int +dwarf_set_stringcheck(int newval) +{ + int oldval = _dwarf_assume_string_bad; + + _dwarf_assume_string_bad = newval; + return oldval; +} + +/* Unifies the basic duplicate/empty testing and section + * data setting to one place. */ +static int +get_basic_section_data(Dwarf_Debug dbg, + struct Dwarf_Section_s *secdata, + struct Dwarf_Obj_Access_Section_s *doas, + Dwarf_Half section_index, + Dwarf_Error* error, + int duperr, int emptyerr ) +{ + if (secdata->dss_index != 0) { + DWARF_DBG_ERROR(dbg, duperr, DW_DLV_ERROR); + } + if (doas->size == 0) { + if (emptyerr == 0 ) { + /* Allow empty section. */ + return DW_DLV_OK; + } + /* Know no reason to allow section */ + DWARF_DBG_ERROR(dbg, emptyerr, DW_DLV_ERROR); + } + secdata->dss_index = section_index; + secdata->dss_size = doas->size; + secdata->dss_addr = doas->addr; + secdata->dss_link = doas->link; + return DW_DLV_OK; +} + + +static void +add_rela_data( struct Dwarf_Section_s *secdata, + struct Dwarf_Obj_Access_Section_s *doas, + Dwarf_Half section_index) +{ + secdata->dss_reloc_index = section_index; + secdata->dss_reloc_size = doas->size; + secdata->dss_reloc_addr = doas->addr; + secdata->dss_reloc_symtab = doas->link; + secdata->dss_reloc_link = doas->link; +} + +/* + Given an Elf ptr, set up dbg with pointers + to all the Dwarf data sections. + Return NULL on error. + + This function is also responsible for determining + whether the given object contains Dwarf information + or not. The test currently used is that it contains + either a .debug_info or a .debug_frame section. If + not, it returns DW_DLV_NO_ENTRY causing dwarf_init() also to + return DW_DLV_NO_ENTRY. Earlier, we had thought of using only + the presence/absence of .debug_info to test, but we + added .debug_frame since there could be stripped objects + that have only a .debug_frame section for exception + processing. + DW_DLV_NO_ENTRY or DW_DLV_OK or DW_DLV_ERROR +*/ +static int +_dwarf_setup(Dwarf_Debug dbg, Dwarf_Error * error) +{ + const char *scn_name = 0; + int foundDwarf = 0; + struct Dwarf_Obj_Access_Interface_s * obj = 0; + + Dwarf_Endianness endianness; + + Dwarf_Unsigned section_size = 0; + Dwarf_Unsigned section_count = 0; + Dwarf_Half section_index = 0; + Dwarf_Addr section_addr = 0; + + foundDwarf = FALSE; + + dbg->de_assume_string_in_bounds = _dwarf_assume_string_bad; + + dbg->de_same_endian = 1; + dbg->de_copy_word = memcpy; + obj = dbg->de_obj_file; + endianness = obj->methods->get_byte_order(obj->object); +#ifdef WORDS_BIGENDIAN + dbg->de_big_endian_object = 1; + if (endianness == DW_OBJECT_LSB ) { + dbg->de_same_endian = 0; + dbg->de_big_endian_object = 0; + dbg->de_copy_word = _dwarf_memcpy_swap_bytes; + } +#else /* little endian */ + dbg->de_big_endian_object = 0; + if (endianness == DW_OBJECT_MSB ) { + dbg->de_same_endian = 0; + dbg->de_big_endian_object = 1; + dbg->de_copy_word = _dwarf_memcpy_swap_bytes; + } +#endif /* !WORDS_BIGENDIAN */ + + + /* The following de_length_size is Not Too Significant. Only used + one calculation, and an approximate one at that. */ + dbg->de_length_size = obj->methods->get_length_size(obj->object); + dbg->de_pointer_size = obj->methods->get_pointer_size(obj->object); + + section_count = obj->methods->get_section_count(obj->object); + + /* We can skip index 0 when considering ELF files, but not other + object types. */ + for (section_index = 0; section_index < section_count; + ++section_index) { + + struct Dwarf_Obj_Access_Section_s doas; + int res = DW_DLV_ERROR; + int err; + + res = obj->methods->get_section_info(obj->object, + section_index, + &doas, &err); + if(res == DW_DLV_ERROR){ + DWARF_DBG_ERROR(dbg, err, DW_DLV_ERROR); + } + + section_addr = doas.addr; + section_size = doas.size; + scn_name = doas.name; + + if (strncmp(scn_name, ".debug_", 7) + && strcmp(scn_name, ".eh_frame") + && strcmp(scn_name, ".symtab") + && strcmp(scn_name, ".strtab") + && strncmp(scn_name, ".rela.",6)) { + continue; + } + else if (strcmp(scn_name, ".debug_info") == 0) { + res = get_basic_section_data(dbg,&dbg->de_debug_info, &doas, + section_index,error, + DW_DLE_DEBUG_INFO_DUPLICATE,DW_DLE_DEBUG_INFO_NULL); + if(res != DW_DLV_OK) { + return res; + } + foundDwarf = TRUE; + } + else if (strcmp(scn_name, ".debug_abbrev") == 0) { + res = get_basic_section_data(dbg,&dbg->de_debug_abbrev, &doas, + section_index,error, + DW_DLE_DEBUG_ABBREV_DUPLICATE,DW_DLE_DEBUG_ABBREV_NULL); + if(res != DW_DLV_OK) { + return res; + } + } + else if (strcmp(scn_name, ".debug_aranges") == 0) { + res = get_basic_section_data(dbg,&dbg->de_debug_aranges, &doas, + section_index,error, + DW_DLE_DEBUG_ARANGES_DUPLICATE,0); + if(res != DW_DLV_OK) { + return res; + } + } + + else if (strcmp(scn_name, ".debug_line") == 0) { + res = get_basic_section_data(dbg,&dbg->de_debug_line, &doas, + section_index,error, + DW_DLE_DEBUG_LINE_DUPLICATE,0); + if(res != DW_DLV_OK) { + return res; + } + } + else if (strcmp(scn_name, ".debug_frame") == 0) { + res = get_basic_section_data(dbg,&dbg->de_debug_frame, &doas, + section_index,error, + DW_DLE_DEBUG_FRAME_DUPLICATE,0); + if(res != DW_DLV_OK) { + return res; + } + foundDwarf = TRUE; + } else if (strcmp(scn_name, ".eh_frame") == 0) { + /* gnu egcs-1.1.2 data */ + res = get_basic_section_data(dbg,&dbg->de_debug_frame_eh_gnu, &doas, + section_index,error, + DW_DLE_DEBUG_FRAME_DUPLICATE,0); + if(res != DW_DLV_OK) { + return res; + } + foundDwarf = TRUE; + } + else if (strcmp(scn_name, ".debug_loc") == 0) { + res = get_basic_section_data(dbg,&dbg->de_debug_loc, &doas, + section_index,error, + DW_DLE_DEBUG_LOC_DUPLICATE,0); + if(res != DW_DLV_OK) { + return res; + } + } + else if (strcmp(scn_name, ".debug_pubnames") == 0) { + res = get_basic_section_data(dbg,&dbg->de_debug_pubnames, &doas, + section_index,error, + DW_DLE_DEBUG_PUBNAMES_DUPLICATE,0); + if(res != DW_DLV_OK) { + return res; + } + } + + else if (strcmp(scn_name, ".debug_str") == 0) { + res = get_basic_section_data(dbg,&dbg->de_debug_str, &doas, + section_index,error, + DW_DLE_DEBUG_STR_DUPLICATE,0); + if(res != DW_DLV_OK) { + return res; + } + } + else if (strcmp(scn_name, ".debug_funcnames") == 0) { + /* SGI IRIX-only. */ + res = get_basic_section_data(dbg,&dbg->de_debug_funcnames, &doas, + section_index,error, + DW_DLE_DEBUG_FUNCNAMES_DUPLICATE,0); + if(res != DW_DLV_OK) { + return res; + } + } + else if (strcmp(scn_name, ".debug_typenames") == 0) { + /* SGI IRIX-only, created years before DWARF3. Content + essentially identical to .debug_pubtypes. */ + res = get_basic_section_data(dbg,&dbg->de_debug_typenames, &doas, + section_index,error, + DW_DLE_DEBUG_TYPENAMES_DUPLICATE,0); + if(res != DW_DLV_OK) { + return res; + } + } else if (strcmp(scn_name, ".debug_pubtypes") == 0) { + /* Section new in DWARF3. */ + res = get_basic_section_data(dbg,&dbg->de_debug_pubtypes, &doas, + section_index,error, + DW_DLE_DEBUG_PUBTYPES_DUPLICATE,0); + if(res != DW_DLV_OK) { + return res; + } + } + else if (strcmp(scn_name, ".debug_varnames") == 0) { + /* SGI IRIX-only. */ + res = get_basic_section_data(dbg,&dbg->de_debug_varnames, &doas, + section_index,error, + DW_DLE_DEBUG_VARNAMES_DUPLICATE,0); + if(res != DW_DLV_OK) { + return res; + } + } + else if (strcmp(scn_name, ".debug_weaknames") == 0) { + /* SGI IRIX-only. */ + res = get_basic_section_data(dbg,&dbg->de_debug_weaknames, &doas, + section_index,error, + DW_DLE_DEBUG_WEAKNAMES_DUPLICATE,0); + if(res != DW_DLV_OK) { + return res; + } + } else if (strcmp(scn_name, ".debug_macinfo") == 0) { + res = get_basic_section_data(dbg,&dbg->de_debug_macinfo, &doas, + section_index,error, + DW_DLE_DEBUG_MACINFO_DUPLICATE,0); + if(res != DW_DLV_OK) { + return res; + } + } + else if (strcmp(scn_name, ".debug_ranges") == 0) { + res = get_basic_section_data(dbg,&dbg->de_debug_ranges, &doas, + section_index,error, + DW_DLE_DEBUG_RANGES_DUPLICATE,0); + if(res != DW_DLV_OK) { + return res; + } + foundDwarf = TRUE; + } + else if (strcmp(scn_name, ".symtab") == 0) { + res = get_basic_section_data(dbg,&dbg->de_elf_symtab, &doas, + section_index,error, + DW_DLE_DEBUG_SYMTAB_ERR,0); + if(res != DW_DLV_OK) { + return res; + } + } + else if (strcmp(scn_name, ".strtab") == 0) { + res = get_basic_section_data(dbg,&dbg->de_elf_strtab, &doas, + section_index,error, + DW_DLE_DEBUG_STRTAB_ERR,0); + if(res != DW_DLV_OK) { + return res; + } + } + else if (strncmp(scn_name, ".rela.debug_",12) == 0) { + const char *rcn_name = scn_name + 5; + if (strcmp(rcn_name, ".debug_info") == 0) { + add_rela_data(&dbg->de_debug_info,&doas,section_index); + } else if (strcmp(rcn_name, ".debug_abbrev") == 0) { + add_rela_data(&dbg->de_debug_abbrev,&doas,section_index); + } else if (strcmp(rcn_name, ".debug_aranges") == 0) { + add_rela_data(&dbg->de_debug_aranges,&doas,section_index); + } else if (strcmp(rcn_name, ".debug_line") == 0) { + add_rela_data(&dbg->de_debug_line,&doas,section_index); + } else if (strcmp(rcn_name, ".debug_frame") == 0) { + add_rela_data(&dbg->de_debug_frame,&doas,section_index); + } else if (strcmp(rcn_name, ".eh_frame") == 0) { + add_rela_data(&dbg->de_debug_frame_eh_gnu,&doas,section_index); + } else if (strcmp(rcn_name, ".debug_loc") == 0) { + add_rela_data(&dbg->de_debug_loc,&doas,section_index); + } else if (strcmp(rcn_name, ".debug_pubnames") == 0) { + add_rela_data(&dbg->de_debug_pubnames,&doas,section_index); + } else if (strcmp(rcn_name, ".debug_str") == 0) { + add_rela_data(&dbg->de_debug_str,&doas,section_index); + } else if (strcmp(rcn_name, ".debug_funcnames") == 0) { + add_rela_data(&dbg->de_debug_funcnames,&doas,section_index); + } else if (strcmp(rcn_name, ".debug_typenames") == 0) { + add_rela_data(&dbg->de_debug_typenames,&doas,section_index); + } else if (strcmp(rcn_name, ".debug_pubtypes") == 0) { + add_rela_data(&dbg->de_debug_pubtypes,&doas,section_index); + } else if (strcmp(rcn_name, ".debug_varnames") == 0) { + add_rela_data(&dbg->de_debug_varnames,&doas,section_index); + } else if (strcmp(rcn_name, ".debug_weaknames") == 0) { + add_rela_data(&dbg->de_debug_weaknames,&doas,section_index); + } else if (strcmp(rcn_name, ".debug_macinfo") == 0) { + add_rela_data(&dbg->de_debug_macinfo,&doas,section_index); + } + } + } + if (foundDwarf) { + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} + + +/* + Use a Dwarf_Obj_Access_Interface to kick things off. All other + init routines eventually use this one. + The returned Dwarf_Debug contains a copy of *obj + the callers copy of *obj may be freed whenever the caller + wishes. +*/ +int +dwarf_object_init(Dwarf_Obj_Access_Interface* obj, Dwarf_Handler errhand, + Dwarf_Ptr errarg, Dwarf_Debug* ret_dbg, + Dwarf_Error* error) +{ + Dwarf_Debug dbg = 0; + int setup_result = DW_DLV_OK; + + dbg = _dwarf_get_debug(); + if (dbg == NULL) { + DWARF_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, DW_DLV_ERROR); + } + dbg->de_errhand = errhand; + dbg->de_errarg = errarg; + dbg->de_frame_rule_initial_value = DW_FRAME_REG_INITIAL_VALUE; + dbg->de_frame_reg_rules_entry_count = DW_FRAME_LAST_REG_NUM; +#ifdef HAVE_OLD_FRAME_CFA_COL + /* DW_FRAME_CFA_COL is really only suitable for old libdwarf frame + interfaces and its value of 0 there is only usable where + (as in MIPS) register 0 has no value other than 0 so + we can use the frame table column 0 for the CFA value + (and rely on client software to know when 'register 0' + is the cfa and when to just use a value 0 for register 0). + */ + dbg->de_frame_cfa_col_number = DW_FRAME_CFA_COL; +#else + dbg->de_frame_cfa_col_number = DW_FRAME_CFA_COL3; +#endif + dbg->de_frame_same_value_number = DW_FRAME_SAME_VAL; + dbg->de_frame_undefined_value_number = DW_FRAME_UNDEFINED_VAL; + + dbg->de_obj_file = obj; + + setup_result = _dwarf_setup(dbg, error); + if (setup_result != DW_DLV_OK) { + /* The status we want to return here is of _dwarf_setup, + not of the _dwarf_free_all_of_one_debug(dbg) call. + So use a local status variable for the free. */ + int freeresult = _dwarf_free_all_of_one_debug(dbg); + if (freeresult == DW_DLV_ERROR) { + DWARF_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, DW_DLV_ERROR); + } + dwarf_malloc_check_complete("After Final free"); + return setup_result; + } + + dwarf_harmless_init(&dbg->de_harmless_errors, + DW_HARMLESS_ERROR_CIRCULAR_LIST_DEFAULT_SIZE); + + /* This call cannot fail: allocates nothing, releases nothing */ + _dwarf_setup_debug(dbg); + + + *ret_dbg = dbg; + return DW_DLV_OK; +} + + +/* + A finish routine that is completely unaware of ELF. + + Frees all memory that was not previously freed by + dwarf_dealloc. + Aside frmo certain categories. + */ +int +dwarf_object_finish(Dwarf_Debug dbg, Dwarf_Error * error) +{ + int res = DW_DLV_OK; + + res = _dwarf_free_all_of_one_debug(dbg); + if (res == DW_DLV_ERROR) { + DWARF_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, DW_DLV_ERROR); + } + dwarf_malloc_check_complete("After Final free"); + + return res; +} + + +/* + Load the ELF section with the specified index and set the + pointer pointed to by section_data to the memory where it + was loaded. + */ +int +_dwarf_load_section(Dwarf_Debug dbg, + struct Dwarf_Section_s *section, + Dwarf_Error * error) +{ + int res = DW_DLV_ERROR; + int err = 0; + struct Dwarf_Obj_Access_Interface_s *o = 0; + + /* check to see if the section is already loaded */ + if (section->dss_data != NULL) { + return DW_DLV_OK; + } + o = dbg->de_obj_file; + res = o->methods->load_section( + o->object, section->dss_index, + §ion->dss_data, &err); + if(res == DW_DLV_ERROR){ + DWARF_DBG_ERROR(dbg, err, DW_DLV_ERROR); + } + if(_dwarf_apply_relocs == 0) { + return res; + } + if(section->dss_reloc_size == 0) { + return res; + } + if(!o->methods->relocate_a_section) { + return res; + } + /*apply relocations */ + res = o->methods->relocate_a_section( o->object, section->dss_index, + dbg, &err); + if(res == DW_DLV_ERROR) { + DWARF_DBG_ERROR(dbg, err, DW_DLV_ERROR); + } + return res; +} + +/* This is a hack so clients can verify offsets. + Added April 2005 so that debugger can detect broken offsets + (which happened in an IRIX -64 executable larger than 2GB + using MIPSpro 7.3.1.3 compilers. A couple .debug_pubnames + offsets were wrong.). +*/ +int +dwarf_get_section_max_offsets(Dwarf_Debug dbg, + Dwarf_Unsigned * debug_info_size, + Dwarf_Unsigned * debug_abbrev_size, + Dwarf_Unsigned * debug_line_size, + Dwarf_Unsigned * debug_loc_size, + Dwarf_Unsigned * debug_aranges_size, + Dwarf_Unsigned * debug_macinfo_size, + Dwarf_Unsigned * debug_pubnames_size, + Dwarf_Unsigned * debug_str_size, + Dwarf_Unsigned * debug_frame_size, + Dwarf_Unsigned * debug_ranges_size, + Dwarf_Unsigned * debug_typenames_size) +{ + *debug_info_size = dbg->de_debug_info.dss_size; + *debug_abbrev_size = dbg->de_debug_abbrev.dss_size; + *debug_line_size = dbg->de_debug_line.dss_size; + *debug_loc_size = dbg->de_debug_loc.dss_size; + *debug_aranges_size = dbg->de_debug_aranges.dss_size; + *debug_macinfo_size = dbg->de_debug_macinfo.dss_size; + *debug_pubnames_size = dbg->de_debug_pubnames.dss_size; + *debug_str_size = dbg->de_debug_str.dss_size; + *debug_frame_size = dbg->de_debug_frame.dss_size; + *debug_ranges_size = dbg->de_debug_ranges.dss_size; + *debug_typenames_size = dbg->de_debug_typenames.dss_size; + return DW_DLV_OK; +} diff --git a/usr/src/lib/libdwarf/common/dwarf_leb.c b/usr/src/lib/libdwarf/common/dwarf_leb.c new file mode 100644 index 0000000000..b3b5d262f5 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_leb.c @@ -0,0 +1,149 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "dwarf_incl.h" +#include + + +/* + decode ULEB +*/ +Dwarf_Unsigned +_dwarf_decode_u_leb128(Dwarf_Small * leb128, Dwarf_Word * leb128_length) +{ + unsigned char byte; + Dwarf_Word word_number; + Dwarf_Unsigned number; + Dwarf_Sword shift; + Dwarf_Sword byte_length; + + /* The following unrolls-the-loop for the first few bytes and + unpacks into 32 bits to make this as fast as possible. + word_number is assumed big enough that the shift has a defined + result. */ + if ((*leb128 & 0x80) == 0) { + if (leb128_length != NULL) + *leb128_length = 1; + return (*leb128); + } else if ((*(leb128 + 1) & 0x80) == 0) { + if (leb128_length != NULL) + *leb128_length = 2; + + word_number = *leb128 & 0x7f; + word_number |= (*(leb128 + 1) & 0x7f) << 7; + return (word_number); + } else if ((*(leb128 + 2) & 0x80) == 0) { + if (leb128_length != NULL) + *leb128_length = 3; + + word_number = *leb128 & 0x7f; + word_number |= (*(leb128 + 1) & 0x7f) << 7; + word_number |= (*(leb128 + 2) & 0x7f) << 14; + return (word_number); + } else if ((*(leb128 + 3) & 0x80) == 0) { + if (leb128_length != NULL) + *leb128_length = 4; + + word_number = *leb128 & 0x7f; + word_number |= (*(leb128 + 1) & 0x7f) << 7; + word_number |= (*(leb128 + 2) & 0x7f) << 14; + word_number |= (*(leb128 + 3) & 0x7f) << 21; + return (word_number); + } + + /* The rest handles long numbers Because the 'number' may be larger + than the default int/unsigned, we must cast the 'byte' before + the shift for the shift to have a defined result. */ + number = 0; + shift = 0; + byte_length = 1; + byte = *(leb128); + for (;;) { + number |= ((Dwarf_Unsigned) (byte & 0x7f)) << shift; + + if ((byte & 0x80) == 0) { + if (leb128_length != NULL) + *leb128_length = byte_length; + return (number); + } + shift += 7; + + byte_length++; + ++leb128; + byte = *leb128; + } +} + +#define BITSINBYTE 8 + +/* + decode SLEB +*/ +Dwarf_Signed +_dwarf_decode_s_leb128(Dwarf_Small * leb128, Dwarf_Word * leb128_length) +{ + Dwarf_Signed number = 0; + Dwarf_Bool sign = 0; + Dwarf_Sword shift = 0; + unsigned char byte = *leb128; + Dwarf_Sword byte_length = 1; + + /* byte_length being the number of bytes of data absorbed so far in + turning the leb into a Dwarf_Signed. */ + + for (;;) { + sign = byte & 0x40; + number |= ((Dwarf_Signed) ((byte & 0x7f))) << shift; + shift += 7; + + if ((byte & 0x80) == 0) { + break; + } + ++leb128; + byte = *leb128; + byte_length++; + } + + if ((shift < sizeof(Dwarf_Signed) * BITSINBYTE) && sign) { + number |= -((Dwarf_Signed) 1 << shift); + } + + if (leb128_length != NULL) + *leb128_length = byte_length; + return (number); +} diff --git a/usr/src/lib/libdwarf/common/dwarf_line.c b/usr/src/lib/libdwarf/common/dwarf_line.c new file mode 100644 index 0000000000..e7e15e7c1a --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_line.c @@ -0,0 +1,1951 @@ +/* + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include +#include "dwarf_line.h" + +static int +is_path_separator(Dwarf_Small s) +{ + if(s == '/') { + return 1; + } +#ifdef HAVE_WINDOWS_PATH + if(s == '\\') { + return 1; + } +#endif + return 0; +} + +/* Return 0 if false, 1 if true. + If HAVE_WINDOWS_PATH is defined we + attempt to handle windows full paths: + \\something or C:cwdpath.c +*/ +static int +file_name_is_full_path(Dwarf_Small *fname) +{ + Dwarf_Small firstc = *fname; + if(is_path_separator(firstc)) { + /* Full path. */ + return 1; + } + if(!firstc) { + return 0; + } +#ifdef HAVE_WINDOWS_PATH + if((firstc >= 'A' && firstc <= 'Z') || + (firstc >= 'a' && firstc <= 'z')) { + Dwarf_Small secondc = fname[1]; + if (secondc == ':') { + return 1; + } + } +#endif + return 0; +} + +/* + Although source files is supposed to return the + source files in the compilation-unit, it does + not look for any in the statement program. In + other words, it ignores those defined using the + extended opcode DW_LNE_define_file. +*/ +int +dwarf_srcfiles(Dwarf_Die die, + char ***srcfiles, + Dwarf_Signed * srcfilecount, Dwarf_Error * error) +{ + /* This pointer is used to scan the portion of the .debug_line + section for the current cu. */ + Dwarf_Small *line_ptr; + + /* Pointer to a DW_AT_stmt_list attribute in case it exists in the + die. */ + Dwarf_Attribute stmt_list_attr; + + /* Pointer to DW_AT_comp_dir attribute in die. */ + Dwarf_Attribute comp_dir_attr; + + /* Pointer to name of compilation directory. */ + Dwarf_Small *comp_dir = 0; + + /* Offset into .debug_line specified by a DW_AT_stmt_list + attribute. */ + Dwarf_Unsigned line_offset = 0; + + /* This points to a block of char *'s, each of which points to a + file name. */ + char **ret_files = 0; + + /* The Dwarf_Debug this die belongs to. */ + Dwarf_Debug dbg = 0; + + /* Used to chain the file names. */ + Dwarf_Chain curr_chain = NULL; + Dwarf_Chain prev_chain = NULL; + Dwarf_Chain head_chain = NULL; + Dwarf_Half attrform = 0; + int resattr = DW_DLV_ERROR; + int lres = DW_DLV_ERROR; + struct Line_Table_Prefix_s line_prefix; + int i = 0; + int res = DW_DLV_ERROR; + + /* ***** BEGIN CODE ***** */ + /* Reset error. */ + if (error != NULL) + *error = NULL; + + CHECK_DIE(die, DW_DLV_ERROR); + dbg = die->di_cu_context->cc_dbg; + + resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error); + if (resattr != DW_DLV_OK) { + return resattr; + } + + if (dbg->de_debug_line.dss_index == 0) { + _dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_NULL); + return (DW_DLV_ERROR); + } + + res = _dwarf_load_section(dbg, &dbg->de_debug_line,error); + if (res != DW_DLV_OK) { + return res; + } + + lres = dwarf_whatform(stmt_list_attr,&attrform,error); + if (lres != DW_DLV_OK) { + return lres; + } + if (attrform != DW_FORM_data4 && attrform != DW_FORM_data8 && + attrform != DW_FORM_sec_offset ) { + _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); + return (DW_DLV_ERROR); + } + lres = dwarf_global_formref(stmt_list_attr, &line_offset, error); + if (lres != DW_DLV_OK) { + return lres; + } + if (line_offset >= dbg->de_debug_line.dss_size) { + _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); + return (DW_DLV_ERROR); + } + line_ptr = dbg->de_debug_line.dss_data + line_offset; + dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR); + + /* + If die has DW_AT_comp_dir attribute, get the string that names + the compilation directory. */ + resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error); + if (resattr == DW_DLV_ERROR) { + return resattr; + } + if (resattr == DW_DLV_OK) { + int cres = DW_DLV_ERROR; + char *cdir = 0; + + cres = dwarf_formstring(comp_dir_attr, &cdir, error); + if (cres == DW_DLV_ERROR) { + return cres; + } else if (cres == DW_DLV_OK) { + comp_dir = (Dwarf_Small *) cdir; + } + } + if (resattr == DW_DLV_OK) { + dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR); + } + dwarf_init_line_table_prefix(&line_prefix); + { + Dwarf_Small *line_ptr_out = 0; + int dres = dwarf_read_line_table_prefix(dbg, + line_ptr, + dbg->de_debug_line.dss_size, + &line_ptr_out, + &line_prefix, + NULL, NULL,error, + 0); + + if (dres == DW_DLV_ERROR) { + dwarf_free_line_table_prefix(&line_prefix); + return dres; + } + if (dres == DW_DLV_NO_ENTRY) { + dwarf_free_line_table_prefix(&line_prefix); + return dres; + } + + line_ptr = line_ptr_out; + } + + for (i = 0; i < line_prefix.pf_files_count; ++i) { + struct Line_Table_File_Entry_s *fe = + line_prefix.pf_line_table_file_entries + i; + char *file_name = (char *) fe->lte_filename; + char *dir_name = 0; + char *full_name = 0; + Dwarf_Unsigned dir_index = fe->lte_directory_index; + + if (dir_index == 0) { + dir_name = (char *) comp_dir; + } else { + dir_name = + (char *) line_prefix.pf_include_directories[ + fe->lte_directory_index - 1]; + } + + /* dir_name can be NULL if there is no DW_AT_comp_dir */ + if(dir_name == 0 || file_name_is_full_path((unsigned char *)file_name)) { + /* This is safe because dwarf_dealloc is careful to not + dealloc strings which are part of the raw .debug_* data. + */ + full_name = file_name; + } else { + full_name = (char *) _dwarf_get_alloc(dbg, DW_DLA_STRING, + strlen(dir_name) + 1 + + strlen(file_name) + + 1); + if (full_name == NULL) { + dwarf_free_line_table_prefix(&line_prefix); + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + /* This is not careful to avoid // in the output, Nothing + forces a 'canonical' name format here. Unclear if this + needs to be fixed. */ + strcpy(full_name, dir_name); + strcat(full_name, "/"); + strcat(full_name, file_name); + } + curr_chain = + (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); + if (curr_chain == NULL) { + dwarf_free_line_table_prefix(&line_prefix); + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + curr_chain->ch_item = full_name; + if (head_chain == NULL) + head_chain = prev_chain = curr_chain; + else { + prev_chain->ch_next = curr_chain; + prev_chain = curr_chain; + } + } + + curr_chain = (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); + if (curr_chain == NULL) { + dwarf_free_line_table_prefix(&line_prefix); + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + + + + if (line_prefix.pf_files_count == 0) { + *srcfiles = NULL; + *srcfilecount = 0; + dwarf_free_line_table_prefix(&line_prefix); + return (DW_DLV_NO_ENTRY); + } + + ret_files = (char **) + _dwarf_get_alloc(dbg, DW_DLA_LIST, line_prefix.pf_files_count); + if (ret_files == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + dwarf_free_line_table_prefix(&line_prefix); + return (DW_DLV_ERROR); + } + + curr_chain = head_chain; + for (i = 0; i < line_prefix.pf_files_count; i++) { + *(ret_files + i) = curr_chain->ch_item; + prev_chain = curr_chain; + curr_chain = curr_chain->ch_next; + dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN); + } + + *srcfiles = ret_files; + *srcfilecount = line_prefix.pf_files_count; + dwarf_free_line_table_prefix(&line_prefix); + return (DW_DLV_OK); +} + + +/* + return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR +*/ +int +_dwarf_internal_srclines(Dwarf_Die die, + Dwarf_Line ** linebuf, + Dwarf_Signed * count, + Dwarf_Bool doaddrs, + Dwarf_Bool dolines, Dwarf_Error * error) +{ + /* This pointer is used to scan the portion of the .debug_line + section for the current cu. */ + Dwarf_Small *line_ptr = 0; + + /* This points to the last byte of the .debug_line portion for the + current cu. */ + Dwarf_Small *line_ptr_end = 0; + + /* Pointer to a DW_AT_stmt_list attribute in case it exists in the + die. */ + Dwarf_Attribute stmt_list_attr = 0; + + /* Pointer to DW_AT_comp_dir attribute in die. */ + Dwarf_Attribute comp_dir_attr = 0; + + /* Pointer to name of compilation directory. */ + Dwarf_Small *comp_dir = NULL; + + /* Offset into .debug_line specified by a DW_AT_stmt_list + attribute. */ + Dwarf_Unsigned line_offset = 0; + + Dwarf_File_Entry file_entries = 0; + + /* These are the state machine state variables. */ + Dwarf_Addr address = 0; + Dwarf_Word file = 1; + Dwarf_Word line = 1; + Dwarf_Word column = 0; + + /* Phony init. See below for true initialization. */ + Dwarf_Bool is_stmt = false; + + Dwarf_Bool basic_block = false; + Dwarf_Bool prologue_end = false; + Dwarf_Bool epilogue_begin = false; + Dwarf_Small isa = 0; + Dwarf_Bool end_sequence = false; + + /* These pointers are used to build the list of files names by this + cu. cur_file_entry points to the file name being added, and + prev_file_entry to the previous one. */ + Dwarf_File_Entry cur_file_entry, prev_file_entry; + + Dwarf_Sword i = 0; + Dwarf_Sword file_entry_count = 0; + + /* This is the current opcode read from the statement program. */ + Dwarf_Small opcode = 0; + + /* Pointer to a Dwarf_Line_Context_s structure that contains the + context such as file names and include directories for the set + of lines being generated. */ + Dwarf_Line_Context line_context = 0; + + /* This is a pointer to the current line being added to the line + matrix. */ + Dwarf_Line curr_line = 0; + + /* These variables are used to decode leb128 numbers. Leb128_num + holds the decoded number, and leb128_length is its length in + bytes. */ + Dwarf_Word leb128_num = 0; + Dwarf_Word leb128_length = 0; + Dwarf_Sword advance_line = 0; + + /* This is the operand of the latest fixed_advance_pc extended + opcode. */ + Dwarf_Half fixed_advance_pc = 0; + + /* Counts the number of lines in the line matrix. */ + Dwarf_Sword line_count = 0; + + /* This is the length of an extended opcode instr. */ + Dwarf_Word instr_length = 0; + Dwarf_Small ext_opcode = 0; + struct Line_Table_Prefix_s prefix; + + /* Used to chain together pointers to line table entries that are + later used to create a block of Dwarf_Line entries. */ + Dwarf_Chain chain_line = NULL; + Dwarf_Chain head_chain = NULL; + Dwarf_Chain curr_chain = NULL; + + /* This points to a block of Dwarf_Lines, a pointer to which is + returned in linebuf. */ + Dwarf_Line *block_line = 0; + + /* The Dwarf_Debug this die belongs to. */ + Dwarf_Debug dbg = 0; + int resattr = DW_DLV_ERROR; + int lres = DW_DLV_ERROR; + Dwarf_Half address_size = 0; + + int res = DW_DLV_ERROR; + + /* ***** BEGIN CODE ***** */ + if (error != NULL) + *error = NULL; + + CHECK_DIE(die, DW_DLV_ERROR); + dbg = die->di_cu_context->cc_dbg; + + res = _dwarf_load_section(dbg, &dbg->de_debug_line,error); + if (res != DW_DLV_OK) { + return res; + } + address_size = _dwarf_get_address_size(dbg, die); + resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error); + if (resattr != DW_DLV_OK) { + return resattr; + } + + lres = dwarf_formudata(stmt_list_attr, &line_offset, error); + if (lres != DW_DLV_OK) { + return lres; + } + + if (line_offset >= dbg->de_debug_line.dss_size) { + _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); + return (DW_DLV_ERROR); + } + line_ptr = dbg->de_debug_line.dss_data + line_offset; + dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR); + + /* If die has DW_AT_comp_dir attribute, get the string that names + the compilation directory. */ + resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error); + if (resattr == DW_DLV_ERROR) { + return resattr; + } + if (resattr == DW_DLV_OK) { + int cres = DW_DLV_ERROR; + char *cdir = 0; + + cres = dwarf_formstring(comp_dir_attr, &cdir, error); + if (cres == DW_DLV_ERROR) { + return cres; + } else if (cres == DW_DLV_OK) { + comp_dir = (Dwarf_Small *) cdir; + } + } + if (resattr == DW_DLV_OK) { + dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR); + } + dwarf_init_line_table_prefix(&prefix); + + { + Dwarf_Small *newlinep = 0; + int res = dwarf_read_line_table_prefix(dbg, + line_ptr, + dbg->de_debug_line.dss_size, + &newlinep, + &prefix, + NULL,NULL, + error, + 0); + + if (res == DW_DLV_ERROR) { + dwarf_free_line_table_prefix(&prefix); + return res; + } + if (res == DW_DLV_NO_ENTRY) { + dwarf_free_line_table_prefix(&prefix); + return res; + } + line_ptr_end = prefix.pf_line_ptr_end; + line_ptr = newlinep; + } + + + /* Set up context structure for this set of lines. */ + line_context = (Dwarf_Line_Context) + _dwarf_get_alloc(dbg, DW_DLA_LINE_CONTEXT, 1); + if (line_context == NULL) { + dwarf_free_line_table_prefix(&prefix); + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + /* Fill out a Dwarf_File_Entry list as we use that to implement the + define_file operation. */ + file_entries = prev_file_entry = NULL; + for (i = 0; i < prefix.pf_files_count; ++i) { + struct Line_Table_File_Entry_s *pfxfile = + prefix.pf_line_table_file_entries + i; + + cur_file_entry = (Dwarf_File_Entry) + _dwarf_get_alloc(dbg, DW_DLA_FILE_ENTRY, 1); + if (cur_file_entry == NULL) { + dwarf_free_line_table_prefix(&prefix); + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + cur_file_entry->fi_file_name = pfxfile->lte_filename; + cur_file_entry->fi_dir_index = pfxfile->lte_directory_index; + cur_file_entry->fi_time_last_mod = + pfxfile->lte_last_modification_time; + + cur_file_entry->fi_file_length = pfxfile->lte_length_of_file; + + if (file_entries == NULL) + file_entries = cur_file_entry; + else + prev_file_entry->fi_next = cur_file_entry; + prev_file_entry = cur_file_entry; + + file_entry_count++; + } + + + /* Initialize the one state machine variable that depends on the + prefix. */ + is_stmt = prefix.pf_default_is_stmt; + + + /* Start of statement program. */ + while (line_ptr < line_ptr_end) { + int type; + + opcode = *(Dwarf_Small *) line_ptr; + line_ptr++; + + + /* 'type' is the output */ + WHAT_IS_OPCODE(type, opcode, prefix.pf_opcode_base, + prefix.pf_opcode_length_table, line_ptr, + prefix.pf_std_op_count); + + if (type == LOP_DISCARD) { + int oc; + int opcnt = prefix.pf_opcode_length_table[opcode]; + + for (oc = 0; oc < opcnt; oc++) { + /* + ** Read and discard operands we don't + ** understand. + ** arbitrary choice of unsigned read. + ** signed read would work as well. + */ + Dwarf_Unsigned utmp2; + + DECODE_LEB128_UWORD(line_ptr, utmp2); + } + } else if (type == LOP_SPECIAL) { + /* This op code is a special op in the object, no matter + that it might fall into the standard op range in this + compile. That is, these are special opcodes between + opcode_base and MAX_LINE_OP_CODE. (including + opcode_base and MAX_LINE_OP_CODE) */ + + opcode = opcode - prefix.pf_opcode_base; + address = address + prefix.pf_minimum_instruction_length * + (opcode / prefix.pf_line_range); + line = + line + prefix.pf_line_base + + opcode % prefix.pf_line_range; + + if (dolines) { + curr_line = + (Dwarf_Line) _dwarf_get_alloc(dbg, DW_DLA_LINE, 1); + if (curr_line == NULL) { + dwarf_free_line_table_prefix(&prefix); + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + curr_line->li_address = address; + curr_line->li_addr_line.li_l_data.li_file = + (Dwarf_Sword) file; + curr_line->li_addr_line.li_l_data.li_line = + (Dwarf_Sword) line; + curr_line->li_addr_line.li_l_data.li_column = + (Dwarf_Half) column; + curr_line->li_addr_line.li_l_data.li_is_stmt = is_stmt; + curr_line->li_addr_line.li_l_data.li_basic_block = + basic_block; + curr_line->li_addr_line.li_l_data.li_end_sequence = + curr_line->li_addr_line.li_l_data. + li_epilogue_begin = epilogue_begin; + curr_line->li_addr_line.li_l_data.li_prologue_end = + prologue_end; + curr_line->li_addr_line.li_l_data.li_isa = isa; + curr_line->li_context = line_context; + line_count++; + + chain_line = (Dwarf_Chain) + _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); + if (chain_line == NULL) { + dwarf_free_line_table_prefix(&prefix); + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + chain_line->ch_item = curr_line; + + if (head_chain == NULL) + head_chain = curr_chain = chain_line; + else { + curr_chain->ch_next = chain_line; + curr_chain = chain_line; + } + } + + basic_block = false; + } else if (type == LOP_STANDARD) { + switch (opcode) { + + case DW_LNS_copy:{ + if (dolines) { + + curr_line = + (Dwarf_Line) _dwarf_get_alloc(dbg, + DW_DLA_LINE, + 1); + if (curr_line == NULL) { + dwarf_free_line_table_prefix(&prefix); + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + curr_line->li_address = address; + curr_line->li_addr_line.li_l_data.li_file = + (Dwarf_Sword) file; + curr_line->li_addr_line.li_l_data.li_line = + (Dwarf_Sword) line; + curr_line->li_addr_line.li_l_data.li_column = + (Dwarf_Half) column; + curr_line->li_addr_line.li_l_data.li_is_stmt = + is_stmt; + curr_line->li_addr_line.li_l_data. + li_basic_block = basic_block; + curr_line->li_addr_line.li_l_data. + li_end_sequence = end_sequence; + curr_line->li_context = line_context; + curr_line->li_addr_line.li_l_data. + li_epilogue_begin = epilogue_begin; + curr_line->li_addr_line.li_l_data. + li_prologue_end = prologue_end; + curr_line->li_addr_line.li_l_data.li_isa = isa; + line_count++; + + chain_line = (Dwarf_Chain) + _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); + if (chain_line == NULL) { + dwarf_free_line_table_prefix(&prefix); + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + chain_line->ch_item = curr_line; + if (head_chain == NULL) + head_chain = curr_chain = chain_line; + else { + curr_chain->ch_next = chain_line; + curr_chain = chain_line; + } + } + + basic_block = false; + prologue_end = false; + epilogue_begin = false; + break; + } + + case DW_LNS_advance_pc:{ + Dwarf_Unsigned utmp2; + + DECODE_LEB128_UWORD(line_ptr, utmp2); + leb128_num = (Dwarf_Word) utmp2; + address = + address + + prefix.pf_minimum_instruction_length * + leb128_num; + break; + } + + case DW_LNS_advance_line:{ + Dwarf_Signed stmp; + + DECODE_LEB128_SWORD(line_ptr, stmp); + advance_line = (Dwarf_Sword) stmp; + line = line + advance_line; + break; + } + + case DW_LNS_set_file:{ + Dwarf_Unsigned utmp2; + + DECODE_LEB128_UWORD(line_ptr, utmp2); + file = (Dwarf_Word) utmp2; + break; + } + + case DW_LNS_set_column:{ + Dwarf_Unsigned utmp2; + + DECODE_LEB128_UWORD(line_ptr, utmp2); + column = (Dwarf_Word) utmp2; + break; + } + + case DW_LNS_negate_stmt:{ + + is_stmt = !is_stmt; + break; + } + + case DW_LNS_set_basic_block:{ + + basic_block = true; + break; + } + + case DW_LNS_const_add_pc:{ + opcode = MAX_LINE_OP_CODE - prefix.pf_opcode_base; + address = address + + prefix.pf_minimum_instruction_length * (opcode / + prefix. + pf_line_range); + break; + } + + case DW_LNS_fixed_advance_pc:{ + + READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half, + line_ptr, sizeof(Dwarf_Half)); + line_ptr += sizeof(Dwarf_Half); + address = address + fixed_advance_pc; + break; + } + + /* New in DWARF3 */ + case DW_LNS_set_prologue_end:{ + + prologue_end = true; + break; + + + } + /* New in DWARF3 */ + case DW_LNS_set_epilogue_begin:{ + epilogue_begin = true; + break; + } + + /* New in DWARF3 */ + case DW_LNS_set_isa:{ + Dwarf_Unsigned utmp2; + + DECODE_LEB128_UWORD(line_ptr, utmp2); + isa = utmp2; + if (isa != utmp2) { + /* The value of the isa did not fit in our + local so we record it wrong. declare an + error. */ + dwarf_free_line_table_prefix(&prefix); + + _dwarf_error(dbg, error, + DW_DLE_LINE_NUM_OPERANDS_BAD); + return (DW_DLV_ERROR); + } + break; + } + } + + } else if (type == LOP_EXTENDED) { + Dwarf_Unsigned utmp3; + + DECODE_LEB128_UWORD(line_ptr, utmp3); + instr_length = (Dwarf_Word) utmp3; + /* Dwarf_Small is a ubyte and the extended opcode is a + ubyte, though not stated as clearly in the 2.0.0 spec as + one might hope. */ + ext_opcode = *(Dwarf_Small *) line_ptr; + line_ptr++; + switch (ext_opcode) { + + case DW_LNE_end_sequence:{ + end_sequence = true; + + if (dolines) { + curr_line = (Dwarf_Line) + _dwarf_get_alloc(dbg, DW_DLA_LINE, 1); + if (curr_line == NULL) { + dwarf_free_line_table_prefix(&prefix); + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + curr_line->li_address = address; + curr_line->li_addr_line.li_l_data.li_file = + (Dwarf_Sword) file; + curr_line->li_addr_line.li_l_data.li_line = + (Dwarf_Sword) line; + curr_line->li_addr_line.li_l_data.li_column = + (Dwarf_Half) column; + curr_line->li_addr_line.li_l_data.li_is_stmt = + prefix.pf_default_is_stmt; + curr_line->li_addr_line.li_l_data. + li_basic_block = basic_block; + curr_line->li_addr_line.li_l_data. + li_end_sequence = end_sequence; + curr_line->li_context = line_context; + curr_line->li_addr_line.li_l_data. + li_epilogue_begin = epilogue_begin; + curr_line->li_addr_line.li_l_data. + li_prologue_end = prologue_end; + curr_line->li_addr_line.li_l_data.li_isa = isa; + line_count++; + + chain_line = (Dwarf_Chain) + _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); + if (chain_line == NULL) { + dwarf_free_line_table_prefix(&prefix); + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + chain_line->ch_item = curr_line; + + if (head_chain == NULL) + head_chain = curr_chain = chain_line; + else { + curr_chain->ch_next = chain_line; + curr_chain = chain_line; + } + } + + address = 0; + file = 1; + line = 1; + column = 0; + is_stmt = prefix.pf_default_is_stmt; + basic_block = false; + end_sequence = false; + prologue_end = false; + epilogue_begin = false; + + + break; + } + + case DW_LNE_set_address:{ + { + READ_UNALIGNED(dbg, address, Dwarf_Addr, + line_ptr, address_size); + if (doaddrs) { + curr_line = + (Dwarf_Line) _dwarf_get_alloc(dbg, + DW_DLA_LINE, + 1); + if (curr_line == NULL) { + dwarf_free_line_table_prefix(&prefix); + _dwarf_error(dbg, error, + DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + curr_line->li_address = address; + curr_line->li_addr_line.li_offset = + line_ptr - dbg->de_debug_line.dss_data; + + line_count++; + + chain_line = (Dwarf_Chain) + _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); + if (chain_line == NULL) { + dwarf_free_line_table_prefix(&prefix); + _dwarf_error(dbg, error, + DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + chain_line->ch_item = curr_line; + + if (head_chain == NULL) + head_chain = curr_chain = chain_line; + else { + curr_chain->ch_next = chain_line; + curr_chain = chain_line; + } + } + + line_ptr += address_size; + } + + break; + } + + case DW_LNE_define_file:{ + + if (dolines) { + cur_file_entry = (Dwarf_File_Entry) + _dwarf_get_alloc(dbg, DW_DLA_FILE_ENTRY, 1); + if (cur_file_entry == NULL) { + dwarf_free_line_table_prefix(&prefix); + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + cur_file_entry->fi_file_name = + (Dwarf_Small *) line_ptr; + line_ptr = + line_ptr + strlen((char *) line_ptr) + 1; + + cur_file_entry->fi_dir_index = (Dwarf_Sword) + _dwarf_decode_u_leb128(line_ptr, + &leb128_length); + line_ptr = line_ptr + leb128_length; + + cur_file_entry->fi_time_last_mod = + _dwarf_decode_u_leb128(line_ptr, + &leb128_length); + line_ptr = line_ptr + leb128_length; + + cur_file_entry->fi_file_length = + _dwarf_decode_u_leb128(line_ptr, + &leb128_length); + line_ptr = line_ptr + leb128_length; + + if (file_entries == NULL) + file_entries = cur_file_entry; + else + prev_file_entry->fi_next = cur_file_entry; + prev_file_entry = cur_file_entry; + + file_entry_count++; + } + break; + } + + default:{ + /* This is an extended op code we do not know about, + other than we know now many bytes it is + and the op code and the bytes of operand. */ + Dwarf_Unsigned remaining_bytes = instr_length -1; + if(instr_length < 1 || remaining_bytes > DW_LNE_LEN_MAX) { + dwarf_free_line_table_prefix(&prefix); + _dwarf_error(dbg, error, + DW_DLE_LINE_EXT_OPCODE_BAD); + return (DW_DLV_ERROR); + } + line_ptr += remaining_bytes; + break; + } + } + + } + } + + block_line = (Dwarf_Line *) + _dwarf_get_alloc(dbg, DW_DLA_LIST, line_count); + if (block_line == NULL) { + dwarf_free_line_table_prefix(&prefix); + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + curr_chain = head_chain; + for (i = 0; i < line_count; i++) { + *(block_line + i) = curr_chain->ch_item; + head_chain = curr_chain; + curr_chain = curr_chain->ch_next; + dwarf_dealloc(dbg, head_chain, DW_DLA_CHAIN); + } + + line_context->lc_file_entries = file_entries; + line_context->lc_file_entry_count = file_entry_count; + line_context->lc_include_directories_count = + prefix.pf_include_directories_count; + if (prefix.pf_include_directories_count > 0) { + /* This gets a pointer to the *first* include dir. The others + follow directly with the standard DWARF2/3 NUL byte + following the last. */ + line_context->lc_include_directories = + prefix.pf_include_directories[0]; + } + + line_context->lc_line_count = line_count; + line_context->lc_compilation_directory = comp_dir; + line_context->lc_version_number = prefix.pf_version; + line_context->lc_dbg = dbg; + *count = line_count; + + *linebuf = block_line; + dwarf_free_line_table_prefix(&prefix); + return (DW_DLV_OK); +} + +int +dwarf_srclines(Dwarf_Die die, + Dwarf_Line ** linebuf, + Dwarf_Signed * linecount, Dwarf_Error * error) +{ + Dwarf_Signed count = 0; + int res = _dwarf_internal_srclines(die, linebuf, &count, + /* addrlist= */ false, + /* linelist= */ true, error); + if (res != DW_DLV_OK) { + return res; + } + *linecount = count; + return res; +} + + + +/* Every line table entry (except DW_DLE_end_sequence, + which is returned using dwarf_lineendsequence()) + potentially has the begin-statement + flag marked 'on'. This returns thru *return_bool, + the begin-statement flag. +*/ + +int +dwarf_linebeginstatement(Dwarf_Line line, + Dwarf_Bool * return_bool, Dwarf_Error * error) +{ + if (line == NULL || return_bool == 0) { + _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); + return (DW_DLV_ERROR); + } + + *return_bool = (line->li_addr_line.li_l_data.li_is_stmt); + return DW_DLV_OK; +} + +/* At the end of any contiguous line-table there may be + a DW_LNE_end_sequence operator. + This returns non-zero thru *return_bool + if and only if this 'line' entry was a DW_LNE_end_sequence. + + Within a compilation unit or function there may be multiple + line tables, each ending with a DW_LNE_end_sequence. + Each table describes a contiguous region. + Because compilers may split function code up in arbitrary ways + compilers may need to emit multiple contigous regions (ie + line tables) for a single function. + See the DWARF3 spec section 6.2. +*/ +int +dwarf_lineendsequence(Dwarf_Line line, + Dwarf_Bool * return_bool, Dwarf_Error * error) +{ + if (line == NULL) { + _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); + return (DW_DLV_ERROR); + } + + *return_bool = (line->li_addr_line.li_l_data.li_end_sequence); + return DW_DLV_OK; +} + + +/* Each 'line' entry has a line-number. + If the entry is a DW_LNE_end_sequence the line-number is + meaningless (see dwarf_lineendsequence(), just above). +*/ +int +dwarf_lineno(Dwarf_Line line, + Dwarf_Unsigned * ret_lineno, Dwarf_Error * error) +{ + if (line == NULL || ret_lineno == 0) { + _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); + return (DW_DLV_ERROR); + } + + *ret_lineno = (line->li_addr_line.li_l_data.li_line); + return DW_DLV_OK; +} + +/* Each 'line' entry has a file-number, and index into the file table. + If the entry is a DW_LNE_end_sequence the index is + meaningless (see dwarf_lineendsequence(), just above). + The file number returned is an index into the file table + produced by dwarf_srcfiles(), but care is required: the + li_file begins with 1 for real files, so that the li_file returned here + is 1 greater than its index into the dwarf_srcfiles() output array. + And entries from DW_LNE_define_file don't appear in + the dwarf_srcfiles() output so file indexes from here may exceed + the size of the dwarf_srcfiles() output array size. +*/ +int +dwarf_line_srcfileno(Dwarf_Line line, + Dwarf_Unsigned * ret_fileno, Dwarf_Error * error) +{ + if (line == NULL || ret_fileno == 0) { + _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); + return (DW_DLV_ERROR); + } + /* li_file must be <= line->li_context->lc_file_entry_count else it + is trash. li_file 0 means not attributable to any source file + per dwarf2/3 spec. */ + + *ret_fileno = (line->li_addr_line.li_l_data.li_file); + return DW_DLV_OK; +} + + +/* Each 'line' entry has a line-address. + If the entry is a DW_LNE_end_sequence the adddress + is one-beyond the last address this contigous region + covers, so the address is not inside the region, + but is just outside it. +*/ +int +dwarf_lineaddr(Dwarf_Line line, + Dwarf_Addr * ret_lineaddr, Dwarf_Error * error) +{ + if (line == NULL || ret_lineaddr == 0) { + _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); + return (DW_DLV_ERROR); + } + + *ret_lineaddr = (line->li_address); + return DW_DLV_OK; +} + + +/* Each 'line' entry has a column-within-line (offset + within the line) where the + source text begins. + If the entry is a DW_LNE_end_sequence the line-number is + meaningless (see dwarf_lineendsequence(), just above). + Lines of text begin at column 1. The value 0 + means the line begins at the left edge of the line. + (See the DWARF3 spec, section 6.2.2). +*/ +int +dwarf_lineoff(Dwarf_Line line, + Dwarf_Signed * ret_lineoff, Dwarf_Error * error) +{ + if (line == NULL || ret_lineoff == 0) { + _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); + return (DW_DLV_ERROR); + } + + *ret_lineoff = + (line->li_addr_line.li_l_data.li_column == + 0 ? -1 : line->li_addr_line.li_l_data.li_column); + return DW_DLV_OK; +} + + +int +dwarf_linesrc(Dwarf_Line line, char **ret_linesrc, Dwarf_Error * error) +{ + Dwarf_Signed i = 0; + Dwarf_File_Entry file_entry; + Dwarf_Small *name_buffer = 0; + Dwarf_Small *include_directories = 0; + Dwarf_Small include_direc_full_path = 0; + Dwarf_Small file_name_full_path = 0; + Dwarf_Debug dbg = 0; + unsigned int comp_dir_len = 0; + + if (line == NULL) { + _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); + return (DW_DLV_ERROR); + } + + if (line->li_context == NULL) { + _dwarf_error(NULL, error, DW_DLE_LINE_CONTEXT_NULL); + return (DW_DLV_ERROR); + } + dbg = line->li_context->lc_dbg; + + if (line->li_addr_line.li_l_data.li_file > + line->li_context->lc_file_entry_count) { + _dwarf_error(dbg, error, DW_DLE_LINE_FILE_NUM_BAD); + return (DW_DLV_ERROR); + } + + if (line->li_addr_line.li_l_data.li_file == 0) { + /* No file name known: see dwarf2/3 spec. */ + _dwarf_error(dbg, error, DW_DLE_NO_FILE_NAME); + return (DW_DLV_ERROR); + } + file_entry = line->li_context->lc_file_entries; + /* ASSERT: li_file > 0, dwarf correctness issue, see line table + definition of dwarf2/3 spec. */ + /* Example: if li_file is 2 and lc_file_entry_count is 3, + file_entry is file 3 (1 based), aka 2( 0 based) file_entry->next + is file 2 (1 based), aka 1( 0 based) file_entry->next->next is + file 1 (1 based), aka 0( 0 based) file_entry->next->next->next + is NULL. + + and this loop finds the file_entry we need (2 (1 based) in this + case). Because lc_file_entries are in reverse order and + effectively zero based as a count whereas li_file is 1 based. */ + for (i = line->li_addr_line.li_l_data.li_file - 1; i > 0; i--) + file_entry = file_entry->fi_next; + + if (file_entry->fi_file_name == NULL) { + _dwarf_error(dbg, error, DW_DLE_NO_FILE_NAME); + return (DW_DLV_ERROR); + } + + file_name_full_path = file_name_is_full_path(file_entry->fi_file_name); + if (file_name_full_path) { + *ret_linesrc = ((char *) file_entry->fi_file_name); + return DW_DLV_OK; + } + + if (file_entry->fi_dir_index == 0) { + + /* dir_index of 0 means that the compilation was in the + 'current directory of compilation' */ + if (line->li_context->lc_compilation_directory == NULL) { + /* we don't actually *have* a current directory of + compilation: DW_AT_comp_dir was not present Rather than + emitting DW_DLE_NO_COMP_DIR lets just make an empty name + here. In other words, do the best we can with what we do + have instead of reporting an error. _dwarf_error(dbg, + error, DW_DLE_NO_COMP_DIR); return(DW_DLV_ERROR); */ + comp_dir_len = 0; + } else { + comp_dir_len = strlen((char *) + (line->li_context-> + lc_compilation_directory)); + } + + name_buffer = + _dwarf_get_alloc(line->li_context->lc_dbg, DW_DLA_STRING, + comp_dir_len + 1 + + strlen((char *) file_entry->fi_file_name) + + 1); + if (name_buffer == NULL) { + _dwarf_error(line->li_context->lc_dbg, error, + DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + if (comp_dir_len > 0) { + /* if comp_dir_len is 0 we do not want to put a / in front + of the fi_file_name as we just don't know anything. */ + strcpy((char *) name_buffer, + (char *) (line->li_context-> + lc_compilation_directory)); + strcat((char *) name_buffer, "/"); + } + strcat((char *) name_buffer, (char *) file_entry->fi_file_name); + *ret_linesrc = ((char *) name_buffer); + return DW_DLV_OK; + } + + if (file_entry->fi_dir_index > + line->li_context->lc_include_directories_count) { + _dwarf_error(dbg, error, DW_DLE_INCL_DIR_NUM_BAD); + return (DW_DLV_ERROR); + } + + include_directories = line->li_context->lc_include_directories; + for (i = file_entry->fi_dir_index - 1; i > 0; i--) + include_directories += strlen((char *) include_directories) + 1; + + if (line->li_context->lc_compilation_directory) { + comp_dir_len = strlen((char *) + (line->li_context->lc_compilation_directory)); + } else { + /* No DW_AT_comp_dir present. Do the best we can without it. */ + comp_dir_len = 0; + } + + include_direc_full_path = file_name_is_full_path(include_directories); + name_buffer = _dwarf_get_alloc(dbg, DW_DLA_STRING, + (include_direc_full_path ? 0 : comp_dir_len + 1) + + strlen((char *)include_directories) + 1 + + strlen((char *)file_entry->fi_file_name) + 1); + if (name_buffer == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + if (!include_direc_full_path) { + if (comp_dir_len > 0) { + strcpy((char *)name_buffer, + (char *)line->li_context->lc_compilation_directory); + /* Who provides the / needed after the compilation + directory? */ + if (!is_path_separator(name_buffer[comp_dir_len - 1])) { + /* Here we provide the / separator. It + should work ok for Windows */ + /* Overwrite previous nul terminator with needed / */ + name_buffer[comp_dir_len] = '/'; + name_buffer[comp_dir_len + 1] = 0; + } + } + } else { + strcpy((char *) name_buffer, ""); + } + strcat((char *) name_buffer, (char *) include_directories); + strcat((char *) name_buffer, "/"); + strcat((char *) name_buffer, (char *) file_entry->fi_file_name); + *ret_linesrc = ((char *) name_buffer); + return DW_DLV_OK; +} + +/* Every line table entry potentially has the basic-block-start + flag marked 'on'. This returns thru *return_bool, + the basic-block-start flag. +*/ +int +dwarf_lineblock(Dwarf_Line line, + Dwarf_Bool * return_bool, Dwarf_Error * error) +{ + if (line == NULL) { + _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); + return (DW_DLV_ERROR); + } + *return_bool = (line->li_addr_line.li_l_data.li_basic_block); + return DW_DLV_OK; +} + + +#if 0 /* Ignore this. This needs major + re-work. */ +/* + This routine works by looking for exact matches between + the current line address and pc, and crossovers from + from less than pc value to greater than. At each line + that satisfies the above, it records a pointer to the + line, and the difference between the address and pc. + It then scans these pointers and picks out those with + the smallest difference between pc and address. +*/ +int +dwarf_pclines(Dwarf_Debug dbg, + Dwarf_Addr pc, + Dwarf_Line ** linebuf, + Dwarf_Signed slide, + Dwarf_Signed * linecount, Dwarf_Error * error) +{ + /* + Scans the line matrix for the current cu to which a pointer + exists in dbg. */ + Dwarf_Line line; + Dwarf_Line prev_line; + + /* + These flags are for efficiency reasons. Check_line is true + initially, but set false when the address of the current line is + greater than pc. It is set true only when the address of the + current line falls below pc. This assumes that addresses within + the same segment increase, and we are only interested in the + switch from a less than pc address to a greater than. First_line + is set true initially, but set false after the first line is + scanned. This is to prevent looking at the address of previous + line when slide is DW_DLS_BACKWARD, and the first line is being + scanned. */ + Dwarf_Bool check_line, first_line; + + /* + Diff tracks the smallest difference a line address and the input + pc value. */ + Dwarf_Signed diff, i; + + /* + For the slide = DW_DLS_BACKWARD case, pc_less is the value of + the address of the line immediately preceding the first line + that has value greater than pc. For the slide = DW_DLS_FORWARD + case, pc_more is the values of address for the first line that + is greater than pc. Diff is the difference between either of the + these values and pc. */ + Dwarf_Addr pc_less, pc_more; + + /* + Pc_line_buf points to a chain of pointers to lines of which + those with a diff equal to the smallest difference will be + returned. */ + Dwarf_Line *pc_line_buf, *pc_line; + + /* + Chain_count counts the number of lines in the above chain for + which the diff is equal to the smallest difference This is the + number returned by this routine. */ + Dwarf_Signed chain_count; + + chain_head = NULL; + + check_line = true; + first_line = true; + diff = MAX_LINE_DIFF; + + for (i = 0; i < dbg->de_cu_line_count; i++) { + + line = *(dbg->de_cu_line_ptr + i); + prev_line = first_line ? NULL : *(dbg->de_cu_line_ptr + i - 1); + + if (line->li_address == pc) { + chain_ptr = (struct chain *) + _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); + if (chain_ptr == NULL) { + _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + chain_ptr->line = line; + chain_ptr->diff = diff = 0; + chain_ptr->next = chain_head; + chain_head = chain_ptr; + } else + /* + Look for crossover from less than pc address to greater + than. */ + if (check_line && line->li_address > pc && + (first_line ? 0 : prev_line->li_address) < pc) + + if (slide == DW_DLS_BACKWARD && !first_line) { + pc_less = prev_line->li_address; + if (pc - pc_less <= diff) { + chain_ptr = (struct chain *) + _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); + if (chain_ptr == NULL) { + _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + chain_ptr->line = prev_line; + chain_ptr->diff = diff = pc - pc_less; + chain_ptr->next = chain_head; + chain_head = chain_ptr; + } + check_line = false; + } else if (slide == DW_DLS_FORWARD) { + pc_more = line->li_address; + if (pc_more - pc <= diff) { + chain_ptr = (struct chain *) + _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); + if (chain_ptr == NULL) { + _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + chain_ptr->line = line; + chain_ptr->diff = diff = pc_more - pc; + chain_ptr->next = chain_head; + chain_head = chain_ptr; + } + check_line = false; + } else + /* Check addresses only when they go */ + /* below pc. */ + if (line->li_address < pc) + check_line = true; + + first_line = false; + } + + chain_count = 0; + for (chain_ptr = chain_head; chain_ptr != NULL; + chain_ptr = chain_ptr->next) + if (chain_ptr->diff == diff) + chain_count++; + + pc_line_buf = pc_line = (Dwarf_Line) + _dwarf_get_alloc(dbg, DW_DLA_LIST, chain_count); + for (chain_ptr = chain_head; chain_ptr != NULL; + chain_ptr = chain_ptr->next) + if (chain_ptr->diff == diff) { + *pc_line = chain_ptr->line; + pc_line++; + } + + for (chain_ptr = chain_head; chain_ptr != NULL;) { + chain_head = chain_ptr; + chain_ptr = chain_ptr->next; + dwarf_dealloc(dbg, chain_head, DW_DLA_CHAIN); + } + + *linebuf = pc_line_buf; + return (chain_count); +} +#endif + + + +/* + It's impossible for callers of dwarf_srclines() to get to and + free all the resources (in particular, the li_context and its + lc_file_entries). + So this function, new July 2005, does it. +*/ + +void +dwarf_srclines_dealloc(Dwarf_Debug dbg, Dwarf_Line * linebuf, + Dwarf_Signed count) +{ + + Dwarf_Signed i = 0; + struct Dwarf_Line_Context_s *context = 0; + + if (count > 0) { + /* All these entries share a single context */ + context = linebuf[0]->li_context; + } + for (i = 0; i < count; ++i) { + dwarf_dealloc(dbg, linebuf[i], DW_DLA_LINE); + } + dwarf_dealloc(dbg, linebuf, DW_DLA_LIST); + + if (context) { + Dwarf_File_Entry fe = context->lc_file_entries; + + while (fe) { + Dwarf_File_Entry fenext = fe->fi_next; + + dwarf_dealloc(dbg, fe, DW_DLA_FILE_ENTRY); + fe = fenext; + } + dwarf_dealloc(dbg, context, DW_DLA_LINE_CONTEXT); + } + + return; +} + +/* Operand counts per standard operand. + The initial zero is for DW_LNS_copy. + This is an economical way to verify we understand the table + of standard-opcode-lengths in the line table prologue. */ +#define STANDARD_OPERAND_COUNT_DWARF2 9 +#define STANDARD_OPERAND_COUNT_DWARF3 12 +static unsigned char + dwarf_standard_opcode_operand_count[STANDARD_OPERAND_COUNT_DWARF3] = { + /* DWARF2 */ + 0, + 1, 1, 1, 1, + 0, 0, 0, + 1, + /* Following are new for DWARF3. */ + 0, 0, 1 +}; + +/* We have a normal standard opcode base, but + an arm compiler emitted a non-standard table! + This could lead to problems... + ARM C/C++ Compiler, RVCT4.0 [Build 4 + 00] seems to get the table wrong . */ +static unsigned char +dwarf_arm_standard_opcode_operand_count[STANDARD_OPERAND_COUNT_DWARF3] = { + /* DWARF2 */ + 0, + 1, 1, 1, 1, + 0, 0, 0, + 0, /* <<< --- this is wrong */ + /* Following are new for DWARF3. */ + 0, 0, 1 +}; + +static void +print_header_issue(Dwarf_Debug dbg, + char *specific_msg, + Dwarf_Small *data_start, + int *err_count_out) +{ + if(!err_count_out) + return; + printf("*** DWARF CHECK: " + "line table header: %s", + specific_msg); + if( data_start >= dbg->de_debug_line.dss_data && + (data_start < (dbg->de_debug_line.dss_data + + dbg->de_debug_line.dss_size))) { + Dwarf_Unsigned off = data_start - dbg->de_debug_line.dss_data; + printf(" at .debug_line section offset 0x%" DW_PR_DUx + " ( %" DW_PR_DUu " ) ", + off,off); + } else { + printf(" (unknown section location) "); + } + printf("***\n"); + *err_count_out += 1; +} + + + +/* Common line table prefix reading code. + Returns DW_DLV_OK, DW_DLV_ERROR. + DW_DLV_NO_ENTRY cannot be returned, but callers should + assume it is possible. + + The prefix_out area must be initialized properly before calling this. + + Has the side effect of allocating arrays which + must be freed (see the Line_Table_Prefix_s struct which + holds the pointers to space we allocate here). + + bogus_bytes_ptr and bogus_bytes are output values which + let a print-program notify the user of some surprising bytes + after a line table header and before the line table instructions. + These can be ignored unless one is printing. + And are ignored if NULL passed as the pointer. +*/ + +/* err_count_out may be NULL, in which case we + make no attempt to count checking-type errors. + Checking-type errors do not stop us, we just report them. +*/ +int +dwarf_read_line_table_prefix(Dwarf_Debug dbg, + Dwarf_Small * data_start, + Dwarf_Unsigned data_length, + Dwarf_Small ** updated_data_start_out, + struct Line_Table_Prefix_s *prefix_out, + Dwarf_Small ** bogus_bytes_ptr, + Dwarf_Unsigned *bogus_bytes, + Dwarf_Error * err, + int *err_count_out) +{ + Dwarf_Small *line_ptr = data_start; + Dwarf_Unsigned total_length = 0; + int local_length_size = 0; + int local_extension_size = 0; + Dwarf_Unsigned prologue_length = 0; + Dwarf_Half version = 0; + Dwarf_Unsigned directories_count = 0; + Dwarf_Unsigned directories_malloc = 0; + Dwarf_Unsigned files_count = 0; + Dwarf_Unsigned files_malloc = 0; + Dwarf_Small *line_ptr_end = 0; + Dwarf_Small *lp_begin = 0; + if(bogus_bytes_ptr) *bogus_bytes_ptr = 0; + if(bogus_bytes) *bogus_bytes= 0; + + prefix_out->pf_line_ptr_start = line_ptr; + /* READ_AREA_LENGTH updates line_ptr for consumed bytes */ + READ_AREA_LENGTH(dbg, total_length, Dwarf_Unsigned, + line_ptr, local_length_size, local_extension_size); + + + line_ptr_end = line_ptr + total_length; + prefix_out->pf_line_ptr_end = line_ptr_end; + prefix_out->pf_length_field_length = local_length_size + + local_extension_size; + /* ASSERT: prefix_out->pf_length_field_length == line_ptr + -prefix_out->pf_line_ptr_start; */ + if (line_ptr_end > dbg->de_debug_line.dss_data + + dbg->de_debug_line.dss_size) { + _dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD); + return (DW_DLV_ERROR); + } + if (line_ptr_end > data_start + data_length) { + _dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD); + return (DW_DLV_ERROR); + } + prefix_out->pf_total_length = total_length; + + READ_UNALIGNED(dbg, version, Dwarf_Half, + line_ptr, sizeof(Dwarf_Half)); + prefix_out->pf_version = version; + line_ptr += sizeof(Dwarf_Half); + if (version != CURRENT_VERSION_STAMP && + version != CURRENT_VERSION_STAMP3) { + _dwarf_error(dbg, err, DW_DLE_VERSION_STAMP_ERROR); + return (DW_DLV_ERROR); + } + + READ_UNALIGNED(dbg, prologue_length, Dwarf_Unsigned, + line_ptr, local_length_size); + prefix_out->pf_prologue_length = prologue_length; + line_ptr += local_length_size; + prefix_out->pf_line_prologue_start = line_ptr; + + prefix_out->pf_minimum_instruction_length = + *(unsigned char *) line_ptr; + line_ptr = line_ptr + sizeof(Dwarf_Small); + + prefix_out->pf_default_is_stmt = *(unsigned char *) line_ptr; + line_ptr = line_ptr + sizeof(Dwarf_Small); + + prefix_out->pf_line_base = *(signed char *) line_ptr; + line_ptr = line_ptr + sizeof(Dwarf_Sbyte); + + prefix_out->pf_line_range = *(unsigned char *) line_ptr; + line_ptr = line_ptr + sizeof(Dwarf_Small); + + prefix_out->pf_opcode_base = *(unsigned char *) line_ptr; + line_ptr = line_ptr + sizeof(Dwarf_Small); + + /* Set up the array of standard opcode lengths. */ + /* We think this works ok even for cross-endian processing of + objects. It might be wrong, we might need to specially process + the array of ubyte into host order. */ + prefix_out->pf_opcode_length_table = line_ptr; + + /* pf_opcode_base is one greater than the size of the array. */ + line_ptr += prefix_out->pf_opcode_base - 1; + + { + /* Determine (as best we can) whether the + pf_opcode_length_table holds 9 or 12 standard-conforming + entries. gcc4 upped to DWARF3's 12 without updating the + version number. */ + int operand_ck_fail = true; + + if (prefix_out->pf_opcode_base >= STANDARD_OPERAND_COUNT_DWARF3) { + int mismatch = memcmp(dwarf_standard_opcode_operand_count, + prefix_out->pf_opcode_length_table, + STANDARD_OPERAND_COUNT_DWARF3); + if(mismatch) { + if(err_count_out) { + print_header_issue(dbg,"standard-operands did not match", + data_start,err_count_out); + } + mismatch = memcmp(dwarf_arm_standard_opcode_operand_count, + prefix_out->pf_opcode_length_table, + STANDARD_OPERAND_COUNT_DWARF3); + if(!mismatch && err_count_out) { + print_header_issue(dbg,"arm (incorrect) operands in use", + data_start,err_count_out); + } + } + if (!mismatch) { + if (version == 2) { + if(err_count_out) { + print_header_issue(dbg, + "standard DWARF3 operands matched, but is DWARF2 linetable", + data_start,err_count_out); + } + } + operand_ck_fail = false; + prefix_out->pf_std_op_count = + STANDARD_OPERAND_COUNT_DWARF3; + } + } + if (operand_ck_fail) { + if (prefix_out->pf_opcode_base >= + STANDARD_OPERAND_COUNT_DWARF2) { + + int mismatch = + memcmp(dwarf_standard_opcode_operand_count, + prefix_out->pf_opcode_length_table, + STANDARD_OPERAND_COUNT_DWARF2); + if(mismatch) { + if(err_count_out) { + print_header_issue(dbg,"standard-operands-lengths did not match", + data_start,err_count_out); + } + mismatch = memcmp(dwarf_arm_standard_opcode_operand_count, + prefix_out->pf_opcode_length_table, + STANDARD_OPERAND_COUNT_DWARF2); + if(!mismatch && err_count_out) { + print_header_issue(dbg,"arm (incorrect) operand in use", + data_start,err_count_out); + } + } + + if (!mismatch) { + operand_ck_fail = false; + prefix_out->pf_std_op_count = + STANDARD_OPERAND_COUNT_DWARF2; + } + } + } + if (operand_ck_fail) { + /* Here we are not sure what the pf_std_op_count is. */ + _dwarf_error(dbg, err, DW_DLE_LINE_NUM_OPERANDS_BAD); + return (DW_DLV_ERROR); + } + } + /* At this point we no longer need to check operand counts. */ + + + directories_count = 0; + directories_malloc = 5; + prefix_out->pf_include_directories = malloc(sizeof(Dwarf_Small *) * + directories_malloc); + if (prefix_out->pf_include_directories == NULL) { + _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + memset(prefix_out->pf_include_directories, 0, + sizeof(Dwarf_Small *) * directories_malloc); + + while ((*(char *) line_ptr) != '\0') { + if (directories_count >= directories_malloc) { + Dwarf_Unsigned expand = 2 * directories_malloc; + Dwarf_Unsigned bytesalloc = sizeof(Dwarf_Small *) * expand; + Dwarf_Small **newdirs = + realloc(prefix_out->pf_include_directories, + bytesalloc); + + if (!newdirs) { + _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + /* Doubled size, zero out second half. */ + memset(newdirs + directories_malloc, 0, + sizeof(Dwarf_Small *) * directories_malloc); + directories_malloc = expand; + prefix_out->pf_include_directories = newdirs; + } + prefix_out->pf_include_directories[directories_count] = + line_ptr; + line_ptr = line_ptr + strlen((char *) line_ptr) + 1; + directories_count++; + } + prefix_out->pf_include_directories_count = directories_count; + line_ptr++; + + files_count = 0; + files_malloc = 5; + prefix_out->pf_line_table_file_entries = + malloc(sizeof(struct Line_Table_File_Entry_s) * files_malloc); + if (prefix_out->pf_line_table_file_entries == NULL) { + _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + memset(prefix_out->pf_line_table_file_entries, 0, + sizeof(struct Line_Table_File_Entry_s) * files_malloc); + + while (*(char *) line_ptr != '\0') { + Dwarf_Unsigned utmp; + Dwarf_Unsigned dir_index = 0; + Dwarf_Unsigned lastmod = 0; + Dwarf_Unsigned file_length = 0; + struct Line_Table_File_Entry_s *curline; + Dwarf_Word leb128_length = 0; + + + if (files_count >= files_malloc) { + Dwarf_Unsigned expand = 2 * files_malloc; + struct Line_Table_File_Entry_s *newfiles = + realloc(prefix_out->pf_line_table_file_entries, + sizeof(struct Line_Table_File_Entry_s) * + expand); + if (!newfiles) { + _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + memset(newfiles + files_malloc, 0, + sizeof(struct Line_Table_File_Entry_s) * + files_malloc); + files_malloc = expand; + prefix_out->pf_line_table_file_entries = newfiles; + } + curline = prefix_out->pf_line_table_file_entries + files_count; + + curline->lte_filename = line_ptr; + line_ptr = line_ptr + strlen((char *) line_ptr) + 1; + + DECODE_LEB128_UWORD(line_ptr, utmp); + dir_index = (Dwarf_Sword) utmp; + if (dir_index > directories_count) { + _dwarf_error(dbg, err, DW_DLE_DIR_INDEX_BAD); + return (DW_DLV_ERROR); + } + curline->lte_directory_index = dir_index; + + lastmod = _dwarf_decode_u_leb128(line_ptr, &leb128_length); + line_ptr = line_ptr + leb128_length; + curline->lte_last_modification_time = lastmod; + + /* Skip over file length. */ + file_length = _dwarf_decode_u_leb128(line_ptr, &leb128_length); + line_ptr = line_ptr + leb128_length; + curline->lte_length_of_file = file_length; + + ++files_count; + + } + prefix_out->pf_files_count = files_count; + /* Skip trailing nul byte */ + ++line_ptr; + + + lp_begin = prefix_out->pf_line_prologue_start + + prefix_out->pf_prologue_length; + if (line_ptr != lp_begin) { + if(line_ptr > lp_begin) { + _dwarf_error(dbg, err, DW_DLE_LINE_PROLOG_LENGTH_BAD); + return (DW_DLV_ERROR); + } else { + /* Bug in compiler. These + * bytes are really part of the instruction + * stream. The prefix_out->pf_prologue_length is + * wrong (12 too high). */ + if(bogus_bytes_ptr) { + *bogus_bytes_ptr = line_ptr; + } + if(bogus_bytes) { + /* How far off things are. We expect the + value 12 ! */ + *bogus_bytes = (lp_begin - line_ptr); + } + } + /* Ignore the lp_begin calc. Assume line_ptr right. + Making up for compiler bug. */ + lp_begin = line_ptr; + + } + + *updated_data_start_out = lp_begin; + return DW_DLV_OK; +} + + +/* Initialize the Line_Table_Prefix_s struct. + memset is not guaranteed a portable initializer, but works + fine for current architectures. AFAIK. +*/ +void +dwarf_init_line_table_prefix(struct Line_Table_Prefix_s *pf) +{ + memset(pf, 0, sizeof(*pf)); +} + +/* Free any malloc'd area. of the Line_Table_Prefix_s struct. */ +void +dwarf_free_line_table_prefix(struct Line_Table_Prefix_s *pf) +{ + if (pf->pf_include_directories) { + free(pf->pf_include_directories); + pf->pf_include_directories = 0; + } + if (pf->pf_line_table_file_entries) { + free(pf->pf_line_table_file_entries); + pf->pf_line_table_file_entries = 0; + } + return; +} diff --git a/usr/src/lib/libdwarf/common/dwarf_line.h b/usr/src/lib/libdwarf/common/dwarf_line.h new file mode 100644 index 0000000000..66d6062754 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_line.h @@ -0,0 +1,331 @@ +/* + + Copyright (C) 2000, 2004, 2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#define DW_EXTENDED_OPCODE 0 + +/* + This is used as the starting value for an algorithm + to get the minimum difference between 2 values. + UINT_MAX is used as our approximation to infinity. +*/ +#define MAX_LINE_DIFF UINT_MAX + +/* This is for a sanity check on line + table extended opcodes. + It is entirely arbitrary, and 100 is surely too small if + someone was inserting strings in the opcode. */ +#define DW_LNE_LEN_MAX 100 + + +/* + This structure is used to build a list of all the + files that are used in the current compilation unit. + All of the fields execpt fi_next have meanings that + are obvious from section 6.2.4 of the Libdwarf Doc. +*/ +struct Dwarf_File_Entry_s { + /* Points to string naming the file. */ + Dwarf_Small *fi_file_name; + + /* + Index into the list of directories of the directory in which + this file exits. */ + Dwarf_Sword fi_dir_index; + + /* Time of last modification of the file. */ + Dwarf_Unsigned fi_time_last_mod; + + /* Length in bytes of the file. */ + Dwarf_Unsigned fi_file_length; + + /* Pointer for chaining file entries. */ + Dwarf_File_Entry fi_next; +}; + + +typedef struct Dwarf_Line_Context_s *Dwarf_Line_Context; + +/* + This structure provides the context in which the fields of + a Dwarf_Line structure are interpreted. They come from the + statement program prologue. **Updated by dwarf_srclines in + dwarf_line.c. +*/ +struct Dwarf_Line_Context_s { + /* + Points to a chain of entries providing info about source files + for the current set of Dwarf_Line structures. File number + 'li_file 1' is last on the list, the first list entry is the + file numbered lc_file_entry_count. The numbering of the file + names matches the dwarf2/3 line table specification file table + and DW_LNE_define_file numbering rules. */ + Dwarf_File_Entry lc_file_entries; + /* + Count of number of source files for this set of Dwarf_Line + structures. */ + Dwarf_Sword lc_file_entry_count; + /* + Points to the portion of .debug_line section that contains a + list of strings naming the included directories. */ + Dwarf_Small *lc_include_directories; + + /* Count of the number of included directories. */ + Dwarf_Sword lc_include_directories_count; + + /* Count of the number of lines for this cu. */ + Dwarf_Sword lc_line_count; + + /* Points to name of compilation directory. */ + Dwarf_Small *lc_compilation_directory; + + Dwarf_Debug lc_dbg; + + Dwarf_Half lc_version_number; /* DWARF2/3 version number, 2 + for DWARF2, 3 for DWARF3. */ +}; + + +/* + This structure defines a row of the line table. + All of the fields except li_offset have the exact + same meaning that is defined in Section 6.2.2 + of the Libdwarf Document. + + li_offset is used by _dwarf_addr_finder() which is called + by rqs(1), an sgi utility for 'moving' shared libraries + as if the static linker (ld) had linked the shared library + at the newly-specified address. Most libdwarf-using + apps will ignore li_offset and _dwarf_addr_finder(). + +*/ +struct Dwarf_Line_s { + Dwarf_Addr li_address; /* pc value of machine instr */ + union addr_or_line_s { + struct li_inner_s { + Dwarf_Sword li_file; /* int identifying src file */ + /* li_file is a number 1-N, indexing into a conceptual + source file table as described in dwarf2/3 spec line + table doc. (see Dwarf_File_Entry lc_file_entries; and + Dwarf_Sword lc_file_entry_count;) */ + + Dwarf_Sword li_line; /* source file line number. */ + Dwarf_Half li_column; /* source file column number */ + Dwarf_Small li_isa; + + /* To save space, use bit flags. */ + /* indicate start of stmt */ + unsigned char li_is_stmt:1; + + /* indicate start basic block */ + unsigned char li_basic_block:1; + + /* first post sequence instr */ + unsigned char li_end_sequence:1; + + unsigned char li_prologue_end:1; + unsigned char li_epilogue_begin:1; + } li_l_data; + Dwarf_Off li_offset; /* for rqs */ + } li_addr_line; + Dwarf_Line_Context li_context; /* assoc Dwarf_Line_Context_s */ +}; + + +int _dwarf_line_address_offsets(Dwarf_Debug dbg, + Dwarf_Die die, + Dwarf_Addr ** addrs, + Dwarf_Off ** offs, + Dwarf_Unsigned * returncount, + Dwarf_Error * err); +int _dwarf_internal_srclines(Dwarf_Die die, + Dwarf_Line ** linebuf, + Dwarf_Signed * count, + Dwarf_Bool doaddrs, + Dwarf_Bool dolines, Dwarf_Error * error); + + + +/* The LOP, WHAT_IS_OPCODE stuff is here so it can + be reused in 3 places. Seemed hard to keep + the 3 places the same without an inline func or + a macro. + + Handling the line section where the header and the + file being processed do not match (unusual, but + planned for in the design of .debug_line) + is too tricky to recode this several times and keep + it right. + + As it is the code starting up line-reading is duplicated + and that is just wrong to do. FIXME! +*/ +#define LOP_EXTENDED 1 +#define LOP_DISCARD 2 +#define LOP_STANDARD 3 +#define LOP_SPECIAL 4 + +#define WHAT_IS_OPCODE(type,opcode,base,opcode_length,line_ptr,highest_std) \ + if( (opcode) < (base) ) { \ + /* we know we must treat as a standard op \ + or a special case. \ + */ \ + if((opcode) == DW_EXTENDED_OPCODE) { \ + type = LOP_EXTENDED; \ + } else if( ((highest_std)+1) >= (base)) { \ + /* == Standard case: compile of \ + dwarf_line.c and object \ + have same standard op codes set. \ + \ + > Special case: compile of dwarf_line.c\ + has things in standard op codes list \ + in dwarf.h header not \ + in the object: handle this as a standard\ + op code in switch below. \ + The header special ops overlap the \ + object standard ops. \ + The new standard op codes will not \ + appear in the object. \ + */ \ + type = LOP_STANDARD; \ + } else { \ + /* These are standard opcodes in the object\ + ** that were not defined in the header \ + ** at the time dwarf_line.c \ + ** was compiled. Provides the ability of \ + ** out-of-date dwarf reader to read newer \ + ** line table data transparently. \ + */ \ + type = LOP_DISCARD; \ + } \ + \ + } else { \ + /* Is a special op code. \ + */ \ + type = LOP_SPECIAL; \ + } + +/* The following is from the dwarf definition of 'ubyte' + and is specifically mentioned in section 6.2.5.1, page 54 + of the Rev 2.0.0 dwarf specification. +*/ + +#define MAX_LINE_OP_CODE 255 + + +/* The following structs (Line_Table_File_Entry_s,Line_Table_Prefix_s) + and functions allow refactoring common code into a single + reader routine. +*/ +/* There can be zero of more of these needed for 1 line prologue. */ +struct Line_Table_File_Entry_s { + Dwarf_Small *lte_filename; + Dwarf_Unsigned lte_directory_index; + Dwarf_Unsigned lte_last_modification_time; + Dwarf_Unsigned lte_length_of_file; +}; + +/* Data picked up from the line table prologue for a single +CU. */ +struct Line_Table_Prefix_s { + + /* pf_total_length is the value of the length field for the line + table of this CU. So it does not count the length of itself (the + length value) for consistency with the say lenghts recorded in + DWARF2/3. */ + Dwarf_Unsigned pf_total_length; + + /* Length of the initial length field itself. */ + Dwarf_Half pf_length_field_length; + + /* The version is 2 for DWARF2, 3 for DWARF3 */ + Dwarf_Half pf_version; + + Dwarf_Unsigned pf_prologue_length; + Dwarf_Small pf_minimum_instruction_length; + + /* Start and end of this CU line area. pf_line_ptr_start + + pf_total_length + pf_length_field_length == pf_line_ptr_end. + Meaning pf_line_ptr_start is before the length info. */ + Dwarf_Small *pf_line_ptr_start; + Dwarf_Small *pf_line_ptr_end; + + /* Used to check that decoding of the line prologue is done right. */ + Dwarf_Small *pf_line_prologue_start; + + Dwarf_Small pf_default_is_stmt; + Dwarf_Sbyte pf_line_base; + Dwarf_Small pf_line_range; + + /* Highest std opcode (+1). */ + Dwarf_Small pf_opcode_base; + + /* pf_opcode_base -1 entries (each a count, normally the value of + each entry is 0 or 1). */ + Dwarf_Small *pf_opcode_length_table; + + Dwarf_Unsigned pf_include_directories_count; + /* Array of pointers to dir strings. pf_include_directories_count + entriesin the array. */ + Dwarf_Small **pf_include_directories; + + /* Count of entries in line_table_file_entries array. */ + Dwarf_Unsigned pf_files_count; + struct Line_Table_File_Entry_s *pf_line_table_file_entries; + + /* The number to treat as standard ops. This is a special + accomodation of gcc using the new standard opcodes but not + updating the version number. It's legal dwarf2, but much better + for the user to understand as dwarf3 when 'it looks ok'. */ + Dwarf_Bool pf_std_op_count; + +}; + +void dwarf_init_line_table_prefix(struct Line_Table_Prefix_s *pf); +void dwarf_free_line_table_prefix(struct Line_Table_Prefix_s *pf); + +int dwarf_read_line_table_prefix(Dwarf_Debug dbg, + Dwarf_Small * data_start, + Dwarf_Unsigned data_length, + Dwarf_Small ** updated_data_start_out, + struct Line_Table_Prefix_s *prefix_out, + /* The following 2 arguments are solely for warning users + * when there is a surprising 'gap' in the .debug_line info. */ + Dwarf_Small ** bogus_bytes_ptr, + Dwarf_Unsigned * bogus_bytes_count, + Dwarf_Error * err, + int * err_count_out); diff --git a/usr/src/lib/libdwarf/common/dwarf_line2.c b/usr/src/lib/libdwarf/common/dwarf_line2.c new file mode 100644 index 0000000000..634b848167 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_line2.c @@ -0,0 +1,110 @@ +/* + + Copyright (C) 2000,2002,2004,2005,2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2008-2010 David Anderson, Inc. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + +/* This source file used for SGI-IRIX rqs processing. + Unused otherwise. +*/ + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include "dwarf_line.h" + +/* + Return DW_DLV_OK or, if error, + DW_DLV_ERROR. + + Thru pointers, return 2 arrays and a count + for rqs. +*/ +int +_dwarf_line_address_offsets(Dwarf_Debug dbg, + Dwarf_Die die, + Dwarf_Addr ** addrs, + Dwarf_Off ** offs, + Dwarf_Unsigned * returncount, + Dwarf_Error * err) +{ + Dwarf_Addr *laddrs; + Dwarf_Off *loffsets; + Dwarf_Signed lcount; + Dwarf_Signed i; + int res; + Dwarf_Line *linebuf; + + res = _dwarf_internal_srclines(die, &linebuf, &lcount, /* addrlist= + */ true, + /* linelist= */ false, err); + if (res != DW_DLV_OK) { + return res; + } + laddrs = (Dwarf_Addr *) + _dwarf_get_alloc(dbg, DW_DLA_ADDR, lcount); + if (laddrs == NULL) { + dwarf_srclines_dealloc(dbg, linebuf, lcount); + _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + loffsets = (Dwarf_Off *) + _dwarf_get_alloc(dbg, DW_DLA_ADDR, lcount); + if (loffsets == NULL) { + dwarf_srclines_dealloc(dbg, linebuf, lcount); + /* We already allocated what laddrs points at, so we'e better + deallocate that space since we are not going to return the + pointer to the caller. */ + dwarf_dealloc(dbg, laddrs, DW_DLA_ADDR); + _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + for (i = 0; i < lcount; i++) { + laddrs[i] = linebuf[i]->li_address; + loffsets[i] = linebuf[i]->li_addr_line.li_offset; + } + dwarf_srclines_dealloc(dbg, linebuf, lcount); + *returncount = lcount; + *offs = loffsets; + *addrs = laddrs; + return DW_DLV_OK; +} + +/* + It's impossible for callers of dwarf_srclines() to get to and + free all the resources (in particular, the li_context and its + lc_file_entries). + So this function, new July 2005, does it. +*/ diff --git a/usr/src/lib/libdwarf/common/dwarf_loc.c b/usr/src/lib/libdwarf/common/dwarf_loc.c new file mode 100644 index 0000000000..f28b27b630 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_loc.c @@ -0,0 +1,1073 @@ +/* + + Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + + + +#include "config.h" +#include "dwarf_incl.h" +#include "dwarf_loc.h" +#include /* for debugging only. */ +#include + +/* + Given a Dwarf_Block that represents a location expression, + this function returns a pointer to a Dwarf_Locdesc struct + that has its ld_cents field set to the number of location + operators in the block, and its ld_s field pointing to a + contiguous block of Dwarf_Loc structs. However, the + ld_lopc and ld_hipc values are uninitialized. Returns + NULL on error. This function assumes that the length of + the block is greater than 0. Zero length location expressions + to represent variables that have been optimized away are + handled in the calling function. +*/ +static Dwarf_Locdesc * +_dwarf_get_locdesc(Dwarf_Debug dbg, + Dwarf_Block * loc_block, + Dwarf_Half address_size, + Dwarf_Addr lowpc, + Dwarf_Addr highpc, + Dwarf_Error * error) +{ + /* Size of the block containing the location expression. */ + Dwarf_Unsigned loc_len = 0; + + /* Sweeps the block containing the location expression. */ + Dwarf_Small *loc_ptr = 0; + + /* Current location operator. */ + Dwarf_Small atom = 0; + + /* Offset of current operator from start of block. */ + Dwarf_Unsigned offset = 0; + + /* Operands of current location operator. */ + Dwarf_Unsigned operand1, operand2; + + /* Used to chain the Dwarf_Loc_Chain_s structs. */ + Dwarf_Loc_Chain curr_loc = NULL; + Dwarf_Loc_Chain prev_loc = NULL; + Dwarf_Loc_Chain head_loc = NULL; + + /* Count of the number of location operators. */ + Dwarf_Unsigned op_count = 0; + + /* Contiguous block of Dwarf_Loc's for Dwarf_Locdesc. */ + Dwarf_Loc *block_loc = 0; + + /* Dwarf_Locdesc pointer to be returned. */ + Dwarf_Locdesc *locdesc = 0; + + Dwarf_Word leb128_length = 0; + Dwarf_Unsigned i = 0; + + /* ***** BEGIN CODE ***** */ + + loc_len = loc_block->bl_len; + loc_ptr = loc_block->bl_data; + + offset = 0; + op_count = 0; + while (offset < loc_len) { + + operand1 = 0; + operand2 = 0; + op_count++; + + atom = *(Dwarf_Small *) loc_ptr; + loc_ptr++; + offset++; + + curr_loc = + (Dwarf_Loc_Chain) _dwarf_get_alloc(dbg, DW_DLA_LOC_CHAIN, + 1); + if (curr_loc == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (NULL); + } + curr_loc->lc_offset = offset; + curr_loc->lc_atom = atom; + switch (atom) { + + case DW_OP_reg0: + case DW_OP_reg1: + case DW_OP_reg2: + case DW_OP_reg3: + case DW_OP_reg4: + case DW_OP_reg5: + case DW_OP_reg6: + case DW_OP_reg7: + case DW_OP_reg8: + case DW_OP_reg9: + case DW_OP_reg10: + case DW_OP_reg11: + case DW_OP_reg12: + case DW_OP_reg13: + case DW_OP_reg14: + case DW_OP_reg15: + case DW_OP_reg16: + case DW_OP_reg17: + case DW_OP_reg18: + case DW_OP_reg19: + case DW_OP_reg20: + case DW_OP_reg21: + case DW_OP_reg22: + case DW_OP_reg23: + case DW_OP_reg24: + case DW_OP_reg25: + case DW_OP_reg26: + case DW_OP_reg27: + case DW_OP_reg28: + case DW_OP_reg29: + case DW_OP_reg30: + case DW_OP_reg31: + break; + + case DW_OP_regx: + operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); + loc_ptr = loc_ptr + leb128_length; + offset = offset + leb128_length; + break; + + case DW_OP_lit0: + case DW_OP_lit1: + case DW_OP_lit2: + case DW_OP_lit3: + case DW_OP_lit4: + case DW_OP_lit5: + case DW_OP_lit6: + case DW_OP_lit7: + case DW_OP_lit8: + case DW_OP_lit9: + case DW_OP_lit10: + case DW_OP_lit11: + case DW_OP_lit12: + case DW_OP_lit13: + case DW_OP_lit14: + case DW_OP_lit15: + case DW_OP_lit16: + case DW_OP_lit17: + case DW_OP_lit18: + case DW_OP_lit19: + case DW_OP_lit20: + case DW_OP_lit21: + case DW_OP_lit22: + case DW_OP_lit23: + case DW_OP_lit24: + case DW_OP_lit25: + case DW_OP_lit26: + case DW_OP_lit27: + case DW_OP_lit28: + case DW_OP_lit29: + case DW_OP_lit30: + case DW_OP_lit31: + operand1 = atom - DW_OP_lit0; + break; + + case DW_OP_addr: + READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, + loc_ptr, address_size); + loc_ptr += address_size; + offset += address_size; + break; + + case DW_OP_const1u: + operand1 = *(Dwarf_Small *) loc_ptr; + loc_ptr = loc_ptr + 1; + offset = offset + 1; + break; + + case DW_OP_const1s: + operand1 = *(Dwarf_Sbyte *) loc_ptr; + SIGN_EXTEND(operand1,1); + loc_ptr = loc_ptr + 1; + offset = offset + 1; + break; + + case DW_OP_const2u: + READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2); + loc_ptr = loc_ptr + 2; + offset = offset + 2; + break; + + case DW_OP_const2s: + READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2); + SIGN_EXTEND(operand1,2); + loc_ptr = loc_ptr + 2; + offset = offset + 2; + break; + + case DW_OP_const4u: + READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4); + loc_ptr = loc_ptr + 4; + offset = offset + 4; + break; + + case DW_OP_const4s: + READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4); + SIGN_EXTEND(operand1,4); + loc_ptr = loc_ptr + 4; + offset = offset + 4; + break; + + case DW_OP_const8u: + READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 8); + loc_ptr = loc_ptr + 8; + offset = offset + 8; + break; + + case DW_OP_const8s: + READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 8); + loc_ptr = loc_ptr + 8; + offset = offset + 8; + break; + + case DW_OP_constu: + operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); + loc_ptr = loc_ptr + leb128_length; + offset = offset + leb128_length; + break; + + case DW_OP_consts: + operand1 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length); + loc_ptr = loc_ptr + leb128_length; + offset = offset + leb128_length; + break; + + case DW_OP_fbreg: + operand1 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length); + loc_ptr = loc_ptr + leb128_length; + offset = offset + leb128_length; + break; + + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + operand1 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length); + loc_ptr = loc_ptr + leb128_length; + offset = offset + leb128_length; + break; + + case DW_OP_bregx: + /* uleb reg num followed by sleb offset */ + operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); + loc_ptr = loc_ptr + leb128_length; + offset = offset + leb128_length; + + operand2 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length); + loc_ptr = loc_ptr + leb128_length; + offset = offset + leb128_length; + break; + + case DW_OP_dup: + case DW_OP_drop: + break; + + case DW_OP_pick: + operand1 = *(Dwarf_Small *) loc_ptr; + loc_ptr = loc_ptr + 1; + offset = offset + 1; + break; + + case DW_OP_over: + case DW_OP_swap: + case DW_OP_rot: + case DW_OP_deref: + break; + + case DW_OP_deref_size: + operand1 = *(Dwarf_Small *) loc_ptr; + loc_ptr = loc_ptr + 1; + offset = offset + 1; + break; + + case DW_OP_xderef: + break; + + case DW_OP_xderef_size: + operand1 = *(Dwarf_Small *) loc_ptr; + loc_ptr = loc_ptr + 1; + offset = offset + 1; + break; + + case DW_OP_abs: + case DW_OP_and: + case DW_OP_div: + case DW_OP_minus: + case DW_OP_mod: + case DW_OP_mul: + case DW_OP_neg: + case DW_OP_not: + case DW_OP_or: + case DW_OP_plus: + break; + + case DW_OP_plus_uconst: + operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); + loc_ptr = loc_ptr + leb128_length; + offset = offset + leb128_length; + break; + + case DW_OP_shl: + case DW_OP_shr: + case DW_OP_shra: + case DW_OP_xor: + break; + + case DW_OP_le: + case DW_OP_ge: + case DW_OP_eq: + case DW_OP_lt: + case DW_OP_gt: + case DW_OP_ne: + break; + + case DW_OP_skip: + case DW_OP_bra: + READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2); + loc_ptr = loc_ptr + 2; + offset = offset + 2; + break; + + case DW_OP_piece: + operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); + loc_ptr = loc_ptr + leb128_length; + offset = offset + leb128_length; + break; + + case DW_OP_nop: + break; + case DW_OP_push_object_address: /* DWARF3 */ + break; + case DW_OP_call2: /* DWARF3 */ + READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2); + loc_ptr = loc_ptr + 2; + offset = offset + 2; + break; + + case DW_OP_call4: /* DWARF3 */ + READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4); + loc_ptr = loc_ptr + 4; + offset = offset + 4; + break; + case DW_OP_call_ref: /* DWARF3 */ + READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, + dbg->de_length_size); + loc_ptr = loc_ptr + dbg->de_length_size; + offset = offset + dbg->de_length_size; + break; + + case DW_OP_form_tls_address: /* DWARF3f */ + break; + case DW_OP_call_frame_cfa: /* DWARF3f */ + break; + case DW_OP_bit_piece: /* DWARF3f */ + /* uleb size in bits followed by uleb offset in bits */ + operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); + loc_ptr = loc_ptr + leb128_length; + offset = offset + leb128_length; + + operand2 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); + loc_ptr = loc_ptr + leb128_length; + offset = offset + leb128_length; + break; + case DW_OP_implicit_value: /* DWARF4 */ + /* uleb length of value bytes followed by that + number of bytes of the value. */ + operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); + loc_ptr = loc_ptr + leb128_length; + offset = offset + leb128_length; + + /* Second operand is block of 'operand1' bytes of stuff. */ + /* This using the second operand as a pointer + is quite ugly. */ + /* This gets an ugly compiler warning. Sorry. */ + operand2 = (Dwarf_Unsigned)(uintptr_t)loc_ptr; + offset = offset + operand1; + loc_ptr = loc_ptr + operand1; + break; + case DW_OP_stack_value: /* DWARF4 */ + break; + + + default: + _dwarf_error(dbg, error, DW_DLE_LOC_EXPR_BAD); + return (NULL); + } + + + curr_loc->lc_number = operand1; + curr_loc->lc_number2 = operand2; + + if (head_loc == NULL) + head_loc = prev_loc = curr_loc; + else { + prev_loc->lc_next = curr_loc; + prev_loc = curr_loc; + } + } + + block_loc = + (Dwarf_Loc *) _dwarf_get_alloc(dbg, DW_DLA_LOC_BLOCK, op_count); + if (block_loc == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (NULL); + } + + curr_loc = head_loc; + for (i = 0; i < op_count; i++) { + (block_loc + i)->lr_atom = curr_loc->lc_atom; + (block_loc + i)->lr_number = curr_loc->lc_number; + (block_loc + i)->lr_number2 = curr_loc->lc_number2; + (block_loc + i)->lr_offset = curr_loc->lc_offset; + + prev_loc = curr_loc; + curr_loc = curr_loc->lc_next; + dwarf_dealloc(dbg, prev_loc, DW_DLA_LOC_CHAIN); + } + + locdesc = + (Dwarf_Locdesc *) _dwarf_get_alloc(dbg, DW_DLA_LOCDESC, 1); + if (locdesc == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (NULL); + } + + locdesc->ld_cents = op_count; + locdesc->ld_s = block_loc; + locdesc->ld_from_loclist = loc_block->bl_from_loclist; + locdesc->ld_section_offset = loc_block->bl_section_offset; + locdesc->ld_lopc = lowpc; + locdesc->ld_hipc = highpc; + + return (locdesc); +} + +/* Using a loclist offset to get the in-memory + address of .debug_loc data to read, returns the loclist + 'header' info in return_block. +*/ + +#define MAX_ADDR ((address_size == 8)?0xffffffffffffffffULL:0xffffffff) + +static int +_dwarf_read_loc_section(Dwarf_Debug dbg, + Dwarf_Block * return_block, + Dwarf_Addr * lowpc, Dwarf_Addr * hipc, + Dwarf_Off sec_offset, + Dwarf_Half address_size, + Dwarf_Error * error) +{ + Dwarf_Small *beg = dbg->de_debug_loc.dss_data + sec_offset; + + Dwarf_Addr start_addr = 0; + Dwarf_Addr end_addr = 0; + Dwarf_Half exprblock_size = 0; + Dwarf_Unsigned exprblock_off = + 2 * address_size + sizeof(Dwarf_Half); + + if (sec_offset >= dbg->de_debug_loc.dss_size) { + /* We're at the end. No more present. */ + return DW_DLV_NO_ENTRY; + } + + /* If it goes past end, error */ + if (exprblock_off > dbg->de_debug_loc.dss_size) { + _dwarf_error(NULL, error, DW_DLE_DEBUG_LOC_SECTION_SHORT); + return DW_DLV_ERROR; + } + + READ_UNALIGNED(dbg, start_addr, Dwarf_Addr, beg, address_size); + READ_UNALIGNED(dbg, end_addr, Dwarf_Addr, + beg + address_size, address_size); + if (start_addr == 0 && end_addr == 0) { + /* If start_addr and end_addr are 0, it's the end and no + exprblock_size field follows. */ + exprblock_size = 0; + exprblock_off -= sizeof(Dwarf_Half); + } else if (start_addr == MAX_ADDR) { + /* end address is a base address, no exprblock_size field here + either */ + exprblock_size = 0; + exprblock_off -= sizeof(Dwarf_Half); + } else { + + READ_UNALIGNED(dbg, exprblock_size, Dwarf_Half, + beg + 2 * address_size, sizeof(Dwarf_Half)); + /* exprblock_size can be zero, means no expression */ + if ((exprblock_off + exprblock_size) > dbg->de_debug_loc.dss_size) { + _dwarf_error(NULL, error, DW_DLE_DEBUG_LOC_SECTION_SHORT); + return DW_DLV_ERROR; + } + } +#undef MAX_ADDR + *lowpc = start_addr; + *hipc = end_addr; + + return_block->bl_len = exprblock_size; + return_block->bl_from_loclist = 1; + return_block->bl_data = beg + exprblock_off; + return_block->bl_section_offset = + ((Dwarf_Small *) return_block->bl_data) - dbg->de_debug_loc.dss_data; + + return DW_DLV_OK; + +} +static int +_dwarf_get_loclist_count(Dwarf_Debug dbg, + Dwarf_Off loclist_offset, + Dwarf_Half address_size, + int *loclist_count, Dwarf_Error * error) +{ + int count = 0; + Dwarf_Off offset = loclist_offset; + + + for (;;) { + Dwarf_Block b; + Dwarf_Addr lowpc; + Dwarf_Addr highpc; + int res = _dwarf_read_loc_section(dbg, &b, + &lowpc, &highpc, + offset, address_size,error); + + if (res != DW_DLV_OK) { + return res; + } + offset = b.bl_len + b.bl_section_offset; + if (lowpc == 0 && highpc == 0) { + break; + } + count++; + } + *loclist_count = count; + return DW_DLV_OK; +} + +/* Helper routine to avoid code duplication. +*/ +static int +_dwarf_setup_loc(Dwarf_Attribute attr, + Dwarf_Debug * dbg_ret, + Dwarf_CU_Context *cucontext_ret, + Dwarf_Half * form_ret, Dwarf_Error * error) +{ + Dwarf_Debug dbg = 0; + Dwarf_Half form = 0; + int blkres = DW_DLV_ERROR; + + if (attr == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); + return (DW_DLV_ERROR); + } + if (attr->ar_cu_context == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); + return (DW_DLV_ERROR); + } + *cucontext_ret = attr->ar_cu_context; + + dbg = attr->ar_cu_context->cc_dbg; + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); + return (DW_DLV_ERROR); + } + *dbg_ret = dbg; + blkres = dwarf_whatform(attr, &form, error); + if (blkres != DW_DLV_OK) { + _dwarf_error(dbg, error, DW_DLE_LOC_EXPR_BAD); + return blkres; + } + *form_ret = form; + return DW_DLV_OK; +} + +/* Helper routine to avoid code duplication. +*/ +static int +_dwarf_get_loclist_header_start(Dwarf_Debug dbg, + Dwarf_Attribute attr, + Dwarf_Unsigned * loclist_offset, + Dwarf_Error * error) +{ + int blkres = dwarf_formudata(attr, loclist_offset, error); + if (blkres != DW_DLV_OK) { + return (blkres); + } + + if (!dbg->de_debug_loc.dss_data) { + int secload = _dwarf_load_section(dbg, &dbg->de_debug_loc,error); + if (secload != DW_DLV_OK) { + return secload; + } + } + return DW_DLV_OK; +} + +/* When llbuf (see dwarf_loclist_n) is partially set up + and an error is encountered, tear it down as it + won't be used. +*/ +static void +_dwarf_cleanup_llbuf(Dwarf_Debug dbg, Dwarf_Locdesc ** llbuf, int count) +{ + int i; + for (i = 0; i < count; ++i) { + dwarf_dealloc(dbg, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK); + dwarf_dealloc(dbg, llbuf[i], DW_DLA_LOCDESC); + } + dwarf_dealloc(dbg, llbuf, DW_DLA_LIST); +} + +/* + Handles simple location entries and loclists. + Returns all the Locdesc's thru llbuf. + +*/ +int +dwarf_loclist_n(Dwarf_Attribute attr, + Dwarf_Locdesc *** llbuf_out, + Dwarf_Signed * listlen_out, Dwarf_Error * error) +{ + Dwarf_Debug dbg; + + /* + Dwarf_Attribute that describes the DW_AT_location in die, if + present. */ + Dwarf_Attribute loc_attr = attr; + + /* Dwarf_Block that describes a single location expression. */ + Dwarf_Block loc_block; + + /* A pointer to the current Dwarf_Locdesc read. */ + Dwarf_Locdesc *locdesc = 0; + + Dwarf_Half form = 0; + Dwarf_Addr lowpc = 0; + Dwarf_Addr highpc = 0; + Dwarf_Signed listlen = 0; + Dwarf_Locdesc **llbuf = 0; + Dwarf_CU_Context cucontext = 0; + unsigned address_size = 0; + + int blkres = DW_DLV_ERROR; + int setup_res = DW_DLV_ERROR; + + /* ***** BEGIN CODE ***** */ + setup_res = _dwarf_setup_loc(attr, &dbg,&cucontext, &form, error); + if (setup_res != DW_DLV_OK) { + return setup_res; + } + address_size = cucontext->cc_address_size; + /* If this is a form_block then it's a location expression. If it's + DW_FORM_data4 or DW_FORM_data8 it's a loclist offset */ + if (((cucontext->cc_version_stamp == CURRENT_VERSION_STAMP || + cucontext->cc_version_stamp == CURRENT_VERSION_STAMP3) && + (form == DW_FORM_data4 || form == DW_FORM_data8)) || + (cucontext->cc_version_stamp == CURRENT_VERSION_STAMP4 && + form == DW_FORM_sec_offset)) + { + + + /* A reference to .debug_loc, with an offset in .debug_loc of a + loclist */ + Dwarf_Unsigned loclist_offset = 0; + int off_res = DW_DLV_ERROR; + int count_res = DW_DLV_ERROR; + int loclist_count; + int lli; + + off_res = _dwarf_get_loclist_header_start(dbg, + attr, &loclist_offset, + error); + if (off_res != DW_DLV_OK) { + return off_res; + } + count_res = _dwarf_get_loclist_count(dbg, loclist_offset, + address_size, + &loclist_count, error); + listlen = loclist_count; + if (count_res != DW_DLV_OK) { + return count_res; + } + if (loclist_count == 0) { + return DW_DLV_NO_ENTRY; + } + + llbuf = (Dwarf_Locdesc **) + _dwarf_get_alloc(dbg, DW_DLA_LIST, loclist_count); + if (!llbuf) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + for (lli = 0; lli < loclist_count; ++lli) { + blkres = _dwarf_read_loc_section(dbg, &loc_block, + &lowpc, + &highpc, + loclist_offset, + address_size, + error); + if (blkres != DW_DLV_OK) { + _dwarf_cleanup_llbuf(dbg, llbuf, lli); + return (blkres); + } + locdesc = _dwarf_get_locdesc(dbg, &loc_block, + address_size, + lowpc, highpc, error); + if (locdesc == NULL) { + _dwarf_cleanup_llbuf(dbg, llbuf, lli); + /* low level error already set: let it be passed back */ + return (DW_DLV_ERROR); + } + llbuf[lli] = locdesc; + + /* Now get to next loclist entry offset. */ + loclist_offset = loc_block.bl_section_offset + + loc_block.bl_len; + } + + + } else { + Dwarf_Block *tblock = 0; + + blkres = dwarf_formblock(loc_attr, &tblock, error); + if (blkres != DW_DLV_OK) { + return (blkres); + } + loc_block = *tblock; + /* We copied tblock contents to the stack var, so can dealloc + tblock now. Avoids leaks. */ + dwarf_dealloc(dbg, tblock, DW_DLA_BLOCK); + listlen = 1; /* One by definition of a location entry. */ + lowpc = 0; /* HACK */ + highpc = (Dwarf_Unsigned) (-1LL); /* HACK */ + + /* An empty location description (block length 0) means the + code generator emitted no variable, the variable was not + generated, it was unused or perhaps never tested after being + set. Dwarf2, section 2.4.1 In other words, it is not an + error, and we don't test for block length 0 specially here. */ + locdesc = _dwarf_get_locdesc(dbg, &loc_block, + address_size, + lowpc, highpc, error); + if (locdesc == NULL) { + /* low level error already set: let it be passed back */ + return (DW_DLV_ERROR); + } + llbuf = (Dwarf_Locdesc **) + _dwarf_get_alloc(dbg, DW_DLA_LIST, listlen); + if (!llbuf) { + /* Free the locdesc we allocated but won't use. */ + dwarf_dealloc(dbg, locdesc, DW_DLA_LOCDESC); + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + llbuf[0] = locdesc; + } + + *llbuf_out = llbuf; + *listlen_out = listlen; + return (DW_DLV_OK); +} + + +/* + Handles only a location expression. + If called on a loclist, just returns one of those. + Cannot not handle a real loclist. + It returns the location expression as a loclist with + a single entry. + See dwarf_loclist_n() which handles any number + of location list entries. + + This is the original definition, and it simply + does not work for loclists. Kept for compatibility. +*/ +int +dwarf_loclist(Dwarf_Attribute attr, + Dwarf_Locdesc ** llbuf, + Dwarf_Signed * listlen, Dwarf_Error * error) +{ + Dwarf_Debug dbg; + + /* Dwarf_Attribute that describes the DW_AT_location in die, if + present. */ + Dwarf_Attribute loc_attr = attr; + + /* Dwarf_Block that describes a single location expression. */ + Dwarf_Block loc_block; + + /* A pointer to the current Dwarf_Locdesc read. */ + Dwarf_Locdesc *locdesc = 0; + + Dwarf_Half form = 0; + Dwarf_Addr lowpc = 0; + Dwarf_Addr highpc = 0; + Dwarf_CU_Context cucontext = 0; + unsigned address_size = 0; + + int blkres = DW_DLV_ERROR; + int setup_res = DW_DLV_ERROR; + + /* ***** BEGIN CODE ***** */ + setup_res = _dwarf_setup_loc(attr, &dbg, &cucontext, &form, error); + if (setup_res != DW_DLV_OK) { + return setup_res; + } + address_size = cucontext->cc_address_size; + /* If this is a form_block then it's a location expression. If it's + DW_FORM_data4 or DW_FORM_data8 it's a loclist offset */ + if (((cucontext->cc_version_stamp == CURRENT_VERSION_STAMP || + cucontext->cc_version_stamp == CURRENT_VERSION_STAMP3) && + (form == DW_FORM_data4 || form == DW_FORM_data8)) || + (cucontext->cc_version_stamp == CURRENT_VERSION_STAMP4 && + form == DW_FORM_sec_offset)) + { + + /* A reference to .debug_loc, with an offset in .debug_loc of a + loclist */ + Dwarf_Unsigned loclist_offset = 0; + int off_res = DW_DLV_ERROR; + + off_res = _dwarf_get_loclist_header_start(dbg, + attr, &loclist_offset, + error); + if (off_res != DW_DLV_OK) { + return off_res; + } + + /* With dwarf_loclist, just read a single entry */ + blkres = _dwarf_read_loc_section(dbg, &loc_block, + &lowpc, + &highpc, + loclist_offset, + address_size, + error); + if (blkres != DW_DLV_OK) { + return (blkres); + } + } else { + Dwarf_Block *tblock = 0; + + blkres = dwarf_formblock(loc_attr, &tblock, error); + if (blkres != DW_DLV_OK) { + return (blkres); + } + loc_block = *tblock; + /* We copied tblock contents to the stack var, so can dealloc + tblock now. Avoids leaks. */ + dwarf_dealloc(dbg, tblock, DW_DLA_BLOCK); + lowpc = 0; /* HACK */ + highpc = (Dwarf_Unsigned) (-1LL); /* HACK */ + } + + /* An empty location description (block length 0) means the code + generator emitted no variable, the variable was not generated, + it was unused or perhaps never tested after being set. Dwarf2, + section 2.4.1 In other words, it is not an error, and we don't + test for block length 0 specially here. + See *dwarf_loclist_n() which handles the general case, this case + handles only a single location expression. */ + locdesc = _dwarf_get_locdesc(dbg, &loc_block, + address_size, + lowpc, highpc, error); + if (locdesc == NULL) { + /* low level error already set: let it be passed back */ + return (DW_DLV_ERROR); + } + + *llbuf = locdesc; + *listlen = 1; + return (DW_DLV_OK); +} + + + +/* + Handles only a location expression. + It returns the location expression as a loclist with + a single entry. + + Usable to access dwarf expressions from any source, but + specifically from + DW_CFA_def_cfa_expression + DW_CFA_expression + DW_CFA_val_expression + + expression_in must point to a valid dwarf expression + set of bytes of length expression_length. Not + a DW_FORM_block*, just the expression bytes. + + If the address_size != de_pointer_size this will not work + right. FIXME. +*/ +int +dwarf_loclist_from_expr(Dwarf_Debug dbg, + Dwarf_Ptr expression_in, + Dwarf_Unsigned expression_length, + Dwarf_Locdesc ** llbuf, + Dwarf_Signed * listlen, Dwarf_Error * error) +{ + int res = 0; + Dwarf_Half addr_size = dbg->de_pointer_size; + res = dwarf_loclist_from_expr_a(dbg,expression_in, + expression_length, addr_size,llbuf,listlen,error); + return res; +} +/* New April 27 2009. Adding addr_size argument for the rare + * cases where an object has CUs with a different address_size. */ +int +dwarf_loclist_from_expr_a(Dwarf_Debug dbg, + Dwarf_Ptr expression_in, + Dwarf_Unsigned expression_length, + Dwarf_Half addr_size, + Dwarf_Locdesc ** llbuf, + Dwarf_Signed * listlen, Dwarf_Error * error) +{ + /* Dwarf_Block that describes a single location expression. */ + Dwarf_Block loc_block; + + /* A pointer to the current Dwarf_Locdesc read. */ + Dwarf_Locdesc *locdesc = 0; + Dwarf_Addr lowpc = 0; + Dwarf_Addr highpc = (Dwarf_Unsigned) (-1LL); + + memset(&loc_block,0,sizeof(loc_block)); + loc_block.bl_len = expression_length; + loc_block.bl_data = expression_in; + loc_block.bl_from_loclist = 0; /* Not from loclist. */ + loc_block.bl_section_offset = 0; /* Fake. Not meaningful. */ + + /* An empty location description (block length 0) means the code + generator emitted no variable, the variable was not generated, + it was unused or perhaps never tested after being set. Dwarf2, + section 2.4.1 In other words, it is not an error, and we don't + test for block length 0 specially here. */ + locdesc = _dwarf_get_locdesc(dbg, &loc_block, + addr_size,lowpc, highpc, error); + if (locdesc == NULL) { + /* low level error already set: let it be passed back */ + return (DW_DLV_ERROR); + } + + *llbuf = locdesc; + *listlen = 1; + return (DW_DLV_OK); +} + +/* Usable to read a single loclist or to read a block of them + or to read an entire section's loclists. + + It's broken because it's not safe to read a loclist entry + when we do not know the address size (in any object where + address size can vary by compilation unit). +*/ + + /*ARGSUSED*/ int +dwarf_get_loclist_entry(Dwarf_Debug dbg, + Dwarf_Unsigned offset, + Dwarf_Addr * hipc_offset, + Dwarf_Addr * lopc_offset, + Dwarf_Ptr * data, + Dwarf_Unsigned * entry_len, + Dwarf_Unsigned * next_entry, + Dwarf_Error * error) +{ + Dwarf_Block b; + Dwarf_Addr lowpc = 0; + Dwarf_Addr highpc = 0; + Dwarf_Half address_size = 0; + int res = DW_DLV_ERROR; + + if (!dbg->de_debug_loc.dss_data) { + int secload = _dwarf_load_section(dbg, &dbg->de_debug_loc,error); + if (secload != DW_DLV_OK) { + return secload; + } + } + + /* FIXME: address_size is not necessarily the same in every frame. */ + address_size = dbg->de_pointer_size; + res = _dwarf_read_loc_section(dbg, + &b, &lowpc, &highpc, offset, + address_size,error); + if (res != DW_DLV_OK) { + return res; + } + *hipc_offset = highpc; + *lopc_offset = lowpc; + *entry_len = b.bl_len; + *data = b.bl_data; + *next_entry = b.bl_len + b.bl_section_offset; + return DW_DLV_OK; +} + + diff --git a/usr/src/lib/libdwarf/common/dwarf_loc.h b/usr/src/lib/libdwarf/common/dwarf_loc.h new file mode 100644 index 0000000000..685d199f29 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_loc.h @@ -0,0 +1,46 @@ +/* + + Copyright (C) 2000, 2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +typedef struct Dwarf_Loc_Chain_s *Dwarf_Loc_Chain; + +struct Dwarf_Loc_Chain_s { + Dwarf_Small lc_atom; + Dwarf_Unsigned lc_number; + Dwarf_Unsigned lc_number2; + Dwarf_Unsigned lc_offset; + Dwarf_Loc_Chain lc_next; +}; diff --git a/usr/src/lib/libdwarf/common/dwarf_macro.c b/usr/src/lib/libdwarf/common/dwarf_macro.c new file mode 100644 index 0000000000..e1ff976d8c --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_macro.c @@ -0,0 +1,467 @@ +/* + + Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif /* HAVE_STDLIB_H */ +#include "dwarf_macro.h" + + +#define LEFTPAREN '(' +#define RIGHTPAREN ')' +#define SPACE ' ' + +/* + Given the dwarf macro string, return a pointer to + the value. Returns pointer to 0 byte at end of string + if no value found (meaning the value is the empty string). + + Only understands well-formed dwarf macinfo strings. +*/ +char * +dwarf_find_macro_value_start(char *str) +{ + char *lcp; + int funclike = 0; + + for (lcp = str; *lcp; ++lcp) { + switch (*lcp) { + case LEFTPAREN: + funclike = 1; + break; + case RIGHTPAREN: + /* lcp+1 must be a space, and following char is the value */ + return lcp + 2; + case SPACE: + /* we allow extraneous spaces inside macro parameter ** + list, just in case... This is not really needed. */ + if (!funclike) { + return lcp + 1; + } + break; + } + } + /* never found value: returns pointer to the 0 byte at end of + string */ + return lcp; + +} + + +/* + Try to keep fileindex correct in every Macro_Details + record by tracking file starts and ends. + Uses high water mark: space reused, not freed. + Presumption is that this makes sense for most uses. + STARTERMAX is set so that the array need not be expanded for + most files: it is the initial include file depth. +*/ +struct macro_stack_s { + Dwarf_Signed *st_base; + long max; + long next_to_use; + int was_fault; +}; + +static void _dwarf_reset_index_macro_stack(struct macro_stack_s *ms); +static void +free_macro_stack(Dwarf_Debug dbg, struct macro_stack_s *ms) +{ + dwarf_dealloc(dbg,ms->st_base,DW_DLA_STRING); + _dwarf_reset_index_macro_stack(ms); +} + +#define STARTERMAX 10 +static void +_dwarf_reset_index_macro_stack(struct macro_stack_s *ms) +{ + ms->st_base = 0; + ms->max = 0; + ms->next_to_use = 0; + ms->was_fault = 0; +} +static int +_dwarf_macro_stack_push_index(Dwarf_Debug dbg, Dwarf_Signed indx, + struct macro_stack_s *ms) +{ + Dwarf_Signed *newbase; + + if (ms->next_to_use >= ms->max) { + long new_size; + + if (ms->max == 0) { + ms->max = STARTERMAX; + } + new_size = ms->max * 2; + newbase = + _dwarf_get_alloc(dbg, DW_DLA_STRING, + new_size * sizeof(Dwarf_Signed)); + if (newbase == 0) { + /* just leave the old array in place */ + ms->was_fault = 1; + return DW_DLV_ERROR; + } + if(ms->st_base) { + memcpy(newbase, ms->st_base, + ms->next_to_use * sizeof(Dwarf_Signed)); + dwarf_dealloc(dbg, ms->st_base, DW_DLA_STRING); + } + ms->st_base = newbase; + ms->max = new_size; + } + ms->st_base[ms->next_to_use] = indx; + ++ms->next_to_use; + return DW_DLV_OK; +} + +static Dwarf_Signed +_dwarf_macro_stack_pop_index(struct macro_stack_s *ms) +{ + if (ms->was_fault) { + return -1; + } + if (ms->next_to_use > 0) { + ms->next_to_use--; + return (ms->st_base[ms->next_to_use]); + } else { + ms->was_fault = 1; + } + return -1; +} + +/* starting at macro_offset in .debug_macinfo, + if maximum_count is 0, treat as if it is infinite. + get macro data up thru + maximum_count entries or the end of a compilation + unit's entries (whichever comes first). +*/ + +int +dwarf_get_macro_details(Dwarf_Debug dbg, + Dwarf_Off macro_offset, + Dwarf_Unsigned maximum_count, + Dwarf_Signed * entry_count, + Dwarf_Macro_Details ** details, + Dwarf_Error * error) +{ + Dwarf_Small *macro_base = 0; + Dwarf_Small *pnext = 0; + Dwarf_Unsigned endloc = 0; + unsigned char uc = 0; + unsigned long depth = 0; + /* By section 6.3.2 Dwarf3 draft 8/9, + the base file should appear as + DW_MACINFO_start_file. See + http://gcc.gnu.org/ml/gcc-bugs/2005-02/msg03442.html + on "[Bug debug/20253] New: [3.4/4.0 regression]: + Macro debug info broken due to lexer change" for how + gcc is broken in some versions. We no longer use + depth as a stopping point, it's not needed as a + stopping point anyway. */ + int res = 0; + /* count space used by strings */ + unsigned long str_space = 0; + int done = 0; + unsigned long space_needed = 0; + unsigned long string_offset = 0; + Dwarf_Small *return_data = 0; + Dwarf_Small *pdata = 0; + unsigned long final_count = 0; + Dwarf_Signed fileindex = -1; + Dwarf_Small *latest_str_loc = 0; + struct macro_stack_s msdata; + + unsigned long count = 0; + unsigned long max_count = (unsigned long) maximum_count; + + _dwarf_reset_index_macro_stack(&msdata); + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_DBG_NULL); + free_macro_stack(dbg,&msdata); + return (DW_DLV_ERROR); + } + + res = _dwarf_load_section(dbg, &dbg->de_debug_macinfo,error); + if (res != DW_DLV_OK) { + free_macro_stack(dbg,&msdata); + return res; + } + + macro_base = dbg->de_debug_macinfo.dss_data; + if (macro_base == NULL) { + free_macro_stack(dbg,&msdata); + return (DW_DLV_NO_ENTRY); + } + if (macro_offset >= dbg->de_debug_macinfo.dss_size) { + free_macro_stack(dbg,&msdata); + return (DW_DLV_NO_ENTRY); + } + + pnext = macro_base + macro_offset; + if (maximum_count == 0) { + max_count = ULONG_MAX; + } + + + /* how many entries and how much space will they take? */ + + endloc = (pnext - macro_base); + if (endloc >= dbg->de_debug_macinfo.dss_size) { + if (endloc == dbg->de_debug_macinfo.dss_size) { + /* normal: found last entry */ + free_macro_stack(dbg,&msdata); + return DW_DLV_NO_ENTRY; + } + _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD); + free_macro_stack(dbg,&msdata); + return (DW_DLV_ERROR); + } + for (count = 0; !done && count < max_count; ++count) { + unsigned long slen; + Dwarf_Word len; + + uc = *pnext; + ++pnext; /* get past the type code */ + switch (uc) { + case DW_MACINFO_define: + case DW_MACINFO_undef: + /* line, string */ + case DW_MACINFO_vendor_ext: + /* number, string */ + (void) _dwarf_decode_u_leb128(pnext, &len); + + pnext += len; + if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { + free_macro_stack(dbg,&msdata); + _dwarf_error(dbg, error, + DW_DLE_DEBUG_MACRO_INCONSISTENT); + return (DW_DLV_ERROR); + } + slen = strlen((char *) pnext) + 1; + pnext += slen; + if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { + free_macro_stack(dbg,&msdata); + _dwarf_error(dbg, error, + DW_DLE_DEBUG_MACRO_INCONSISTENT); + return (DW_DLV_ERROR); + } + str_space += slen; + break; + case DW_MACINFO_start_file: + /* line, file index */ + (void) _dwarf_decode_u_leb128(pnext, &len); + pnext += len; + if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { + free_macro_stack(dbg,&msdata); + _dwarf_error(dbg, error, + DW_DLE_DEBUG_MACRO_INCONSISTENT); + return (DW_DLV_ERROR); + } + (void) _dwarf_decode_u_leb128(pnext, &len); + pnext += len; + if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { + free_macro_stack(dbg,&msdata); + _dwarf_error(dbg, error, + DW_DLE_DEBUG_MACRO_INCONSISTENT); + return (DW_DLV_ERROR); + } + ++depth; + break; + + case DW_MACINFO_end_file: + if (--depth == 0) { + /* done = 1; no, do not stop here, at least one gcc had + the wrong depth settings in the gcc 3.4 timeframe. */ + } + break; /* no string or number here */ + case 0: + /* end of cu's entries */ + done = 1; + break; + default: + free_macro_stack(dbg,&msdata); + _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT); + return (DW_DLV_ERROR); + /* bogus macinfo! */ + } + + endloc = (pnext - macro_base); + if (endloc == dbg->de_debug_macinfo.dss_size) { + done = 1; + } else if (endloc > dbg->de_debug_macinfo.dss_size) { + _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD); + free_macro_stack(dbg,&msdata); + return (DW_DLV_ERROR); + } + } + if (count == 0) { + free_macro_stack(dbg,&msdata); + _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INTERNAL_ERR); + return (DW_DLV_ERROR); + } + + /* we have 'count' array entries to allocate and str_space bytes of + string space to provide for. */ + + string_offset = count * sizeof(Dwarf_Macro_Details); + + /* extra 2 not really needed */ + space_needed = string_offset + str_space + 2; + return_data = pdata = + _dwarf_get_alloc(dbg, DW_DLA_STRING, space_needed); + latest_str_loc = pdata + string_offset; + if (pdata == 0) { + free_macro_stack(dbg,&msdata); + _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_MALLOC_SPACE); + return (DW_DLV_ERROR); + } + pnext = macro_base + macro_offset; + + done = 0; + + /* A series ends with a type code of 0. */ + + for (final_count = 0; !done && final_count < count; ++final_count) { + unsigned long slen; + Dwarf_Word len; + Dwarf_Unsigned v1; + Dwarf_Macro_Details *pdmd = (Dwarf_Macro_Details *) (pdata + + (final_count * sizeof (Dwarf_Macro_Details))); + + endloc = (pnext - macro_base); + if (endloc > dbg->de_debug_macinfo.dss_size) { + free_macro_stack(dbg,&msdata); + _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD); + return (DW_DLV_ERROR); + } + uc = *pnext; + pdmd->dmd_offset = (pnext - macro_base); + pdmd->dmd_type = uc; + pdmd->dmd_fileindex = fileindex; + pdmd->dmd_lineno = 0; + pdmd->dmd_macro = 0; + ++pnext; /* get past the type code */ + switch (uc) { + case DW_MACINFO_define: + case DW_MACINFO_undef: + /* line, string */ + case DW_MACINFO_vendor_ext: + /* number, string */ + v1 = _dwarf_decode_u_leb128(pnext, &len); + pdmd->dmd_lineno = v1; + + pnext += len; + if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { + free_macro_stack(dbg,&msdata); + dwarf_dealloc(dbg, return_data, DW_DLA_STRING); + _dwarf_error(dbg, error, + DW_DLE_DEBUG_MACRO_INCONSISTENT); + return (DW_DLV_ERROR); + } + slen = strlen((char *) pnext) + 1; + strcpy((char *) latest_str_loc, (char *) pnext); + pdmd->dmd_macro = (char *) latest_str_loc; + latest_str_loc += slen; + pnext += slen; + if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { + free_macro_stack(dbg,&msdata); + dwarf_dealloc(dbg, return_data, DW_DLA_STRING); + _dwarf_error(dbg, error, + DW_DLE_DEBUG_MACRO_INCONSISTENT); + return (DW_DLV_ERROR); + } + break; + case DW_MACINFO_start_file: + /* Line, file index */ + v1 = _dwarf_decode_u_leb128(pnext, &len); + pdmd->dmd_lineno = v1; + pnext += len; + if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { + free_macro_stack(dbg,&msdata); + dwarf_dealloc(dbg, return_data, DW_DLA_STRING); + _dwarf_error(dbg, error, + DW_DLE_DEBUG_MACRO_INCONSISTENT); + return (DW_DLV_ERROR); + } + v1 = _dwarf_decode_u_leb128(pnext, &len); + pdmd->dmd_fileindex = v1; + (void) _dwarf_macro_stack_push_index(dbg, fileindex, + &msdata); + /* We ignore the error, we just let fileindex ** be -1 when + we pop this one. */ + fileindex = v1; + pnext += len; + if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { + free_macro_stack(dbg,&msdata); + dwarf_dealloc(dbg, return_data, DW_DLA_STRING); + _dwarf_error(dbg, error, + DW_DLE_DEBUG_MACRO_INCONSISTENT); + return (DW_DLV_ERROR); + } + break; + + case DW_MACINFO_end_file: + fileindex = _dwarf_macro_stack_pop_index(&msdata); + break; /* no string or number here */ + case 0: + /* Type code of 0 means the end of cu's entries. */ + done = 1; + break; + default: + /* Bogus macinfo! */ + dwarf_dealloc(dbg, return_data, DW_DLA_STRING); + free_macro_stack(dbg,&msdata); + _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT); + return (DW_DLV_ERROR); + } + } + *entry_count = count; + *details = (Dwarf_Macro_Details *) return_data; + free_macro_stack(dbg,&msdata); + return DW_DLV_OK; +} diff --git a/usr/src/lib/libdwarf/common/dwarf_macro.h b/usr/src/lib/libdwarf/common/dwarf_macro.h new file mode 100644 index 0000000000..31ea2e6e67 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_macro.h @@ -0,0 +1,44 @@ +/* + + Copyright (C) 2000, 2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + +/* + + + dwarf_macro.h + + $Revision: 1.4 $ $Date: 2004/10/28 22:19:14 $ + +*/ diff --git a/usr/src/lib/libdwarf/common/dwarf_names.c b/usr/src/lib/libdwarf/common/dwarf_names.c new file mode 100644 index 0000000000..417e025690 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_names.c @@ -0,0 +1,2408 @@ +/* Generated routines, do not edit. */ +/* Generated on May 22 2011 03:05:33 */ + +/* BEGIN FILE */ + +#include "dwarf.h" + +#include "libdwarf.h" + +/* ARGSUSED */ +int +dwarf_get_TAG_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_TAG_array_type: + *s_out = "DW_TAG_array_type"; + return DW_DLV_OK; + case DW_TAG_class_type: + *s_out = "DW_TAG_class_type"; + return DW_DLV_OK; + case DW_TAG_entry_point: + *s_out = "DW_TAG_entry_point"; + return DW_DLV_OK; + case DW_TAG_enumeration_type: + *s_out = "DW_TAG_enumeration_type"; + return DW_DLV_OK; + case DW_TAG_formal_parameter: + *s_out = "DW_TAG_formal_parameter"; + return DW_DLV_OK; + case DW_TAG_imported_declaration: + *s_out = "DW_TAG_imported_declaration"; + return DW_DLV_OK; + case DW_TAG_label: + *s_out = "DW_TAG_label"; + return DW_DLV_OK; + case DW_TAG_lexical_block: + *s_out = "DW_TAG_lexical_block"; + return DW_DLV_OK; + case DW_TAG_member: + *s_out = "DW_TAG_member"; + return DW_DLV_OK; + case DW_TAG_pointer_type: + *s_out = "DW_TAG_pointer_type"; + return DW_DLV_OK; + case DW_TAG_reference_type: + *s_out = "DW_TAG_reference_type"; + return DW_DLV_OK; + case DW_TAG_compile_unit: + *s_out = "DW_TAG_compile_unit"; + return DW_DLV_OK; + case DW_TAG_string_type: + *s_out = "DW_TAG_string_type"; + return DW_DLV_OK; + case DW_TAG_structure_type: + *s_out = "DW_TAG_structure_type"; + return DW_DLV_OK; + case DW_TAG_subroutine_type: + *s_out = "DW_TAG_subroutine_type"; + return DW_DLV_OK; + case DW_TAG_typedef: + *s_out = "DW_TAG_typedef"; + return DW_DLV_OK; + case DW_TAG_union_type: + *s_out = "DW_TAG_union_type"; + return DW_DLV_OK; + case DW_TAG_unspecified_parameters: + *s_out = "DW_TAG_unspecified_parameters"; + return DW_DLV_OK; + case DW_TAG_variant: + *s_out = "DW_TAG_variant"; + return DW_DLV_OK; + case DW_TAG_common_block: + *s_out = "DW_TAG_common_block"; + return DW_DLV_OK; + case DW_TAG_common_inclusion: + *s_out = "DW_TAG_common_inclusion"; + return DW_DLV_OK; + case DW_TAG_inheritance: + *s_out = "DW_TAG_inheritance"; + return DW_DLV_OK; + case DW_TAG_inlined_subroutine: + *s_out = "DW_TAG_inlined_subroutine"; + return DW_DLV_OK; + case DW_TAG_module: + *s_out = "DW_TAG_module"; + return DW_DLV_OK; + case DW_TAG_ptr_to_member_type: + *s_out = "DW_TAG_ptr_to_member_type"; + return DW_DLV_OK; + case DW_TAG_set_type: + *s_out = "DW_TAG_set_type"; + return DW_DLV_OK; + case DW_TAG_subrange_type: + *s_out = "DW_TAG_subrange_type"; + return DW_DLV_OK; + case DW_TAG_with_stmt: + *s_out = "DW_TAG_with_stmt"; + return DW_DLV_OK; + case DW_TAG_access_declaration: + *s_out = "DW_TAG_access_declaration"; + return DW_DLV_OK; + case DW_TAG_base_type: + *s_out = "DW_TAG_base_type"; + return DW_DLV_OK; + case DW_TAG_catch_block: + *s_out = "DW_TAG_catch_block"; + return DW_DLV_OK; + case DW_TAG_const_type: + *s_out = "DW_TAG_const_type"; + return DW_DLV_OK; + case DW_TAG_constant: + *s_out = "DW_TAG_constant"; + return DW_DLV_OK; + case DW_TAG_enumerator: + *s_out = "DW_TAG_enumerator"; + return DW_DLV_OK; + case DW_TAG_file_type: + *s_out = "DW_TAG_file_type"; + return DW_DLV_OK; + case DW_TAG_friend: + *s_out = "DW_TAG_friend"; + return DW_DLV_OK; + case DW_TAG_namelist: + *s_out = "DW_TAG_namelist"; + return DW_DLV_OK; + case DW_TAG_namelist_item: + *s_out = "DW_TAG_namelist_item"; + return DW_DLV_OK; + case DW_TAG_packed_type: + *s_out = "DW_TAG_packed_type"; + return DW_DLV_OK; + case DW_TAG_subprogram: + *s_out = "DW_TAG_subprogram"; + return DW_DLV_OK; + case DW_TAG_template_type_parameter: + *s_out = "DW_TAG_template_type_parameter"; + return DW_DLV_OK; + case DW_TAG_template_value_parameter: + *s_out = "DW_TAG_template_value_parameter"; + return DW_DLV_OK; + case DW_TAG_thrown_type: + *s_out = "DW_TAG_thrown_type"; + return DW_DLV_OK; + case DW_TAG_try_block: + *s_out = "DW_TAG_try_block"; + return DW_DLV_OK; + case DW_TAG_variant_part: + *s_out = "DW_TAG_variant_part"; + return DW_DLV_OK; + case DW_TAG_variable: + *s_out = "DW_TAG_variable"; + return DW_DLV_OK; + case DW_TAG_volatile_type: + *s_out = "DW_TAG_volatile_type"; + return DW_DLV_OK; + case DW_TAG_dwarf_procedure: + *s_out = "DW_TAG_dwarf_procedure"; + return DW_DLV_OK; + case DW_TAG_restrict_type: + *s_out = "DW_TAG_restrict_type"; + return DW_DLV_OK; + case DW_TAG_interface_type: + *s_out = "DW_TAG_interface_type"; + return DW_DLV_OK; + case DW_TAG_namespace: + *s_out = "DW_TAG_namespace"; + return DW_DLV_OK; + case DW_TAG_imported_module: + *s_out = "DW_TAG_imported_module"; + return DW_DLV_OK; + case DW_TAG_unspecified_type: + *s_out = "DW_TAG_unspecified_type"; + return DW_DLV_OK; + case DW_TAG_partial_unit: + *s_out = "DW_TAG_partial_unit"; + return DW_DLV_OK; + case DW_TAG_imported_unit: + *s_out = "DW_TAG_imported_unit"; + return DW_DLV_OK; + case DW_TAG_mutable_type: + *s_out = "DW_TAG_mutable_type"; + return DW_DLV_OK; + case DW_TAG_condition: + *s_out = "DW_TAG_condition"; + return DW_DLV_OK; + case DW_TAG_shared_type: + *s_out = "DW_TAG_shared_type"; + return DW_DLV_OK; + case DW_TAG_type_unit: + *s_out = "DW_TAG_type_unit"; + return DW_DLV_OK; + case DW_TAG_rvalue_reference_type: + *s_out = "DW_TAG_rvalue_reference_type"; + return DW_DLV_OK; + case DW_TAG_template_alias: + *s_out = "DW_TAG_template_alias"; + return DW_DLV_OK; + case DW_TAG_lo_user: + *s_out = "DW_TAG_lo_user"; + return DW_DLV_OK; + case DW_TAG_MIPS_loop: + *s_out = "DW_TAG_MIPS_loop"; + return DW_DLV_OK; + case DW_TAG_HP_array_descriptor: + *s_out = "DW_TAG_HP_array_descriptor"; + return DW_DLV_OK; + case DW_TAG_format_label: + *s_out = "DW_TAG_format_label"; + return DW_DLV_OK; + case DW_TAG_function_template: + *s_out = "DW_TAG_function_template"; + return DW_DLV_OK; + case DW_TAG_class_template: + *s_out = "DW_TAG_class_template"; + return DW_DLV_OK; + case DW_TAG_GNU_BINCL: + *s_out = "DW_TAG_GNU_BINCL"; + return DW_DLV_OK; + case DW_TAG_GNU_EINCL: + *s_out = "DW_TAG_GNU_EINCL"; + return DW_DLV_OK; + case DW_TAG_GNU_template_template_parameter: + *s_out = "DW_TAG_GNU_template_template_parameter"; + return DW_DLV_OK; + case DW_TAG_GNU_template_parameter_pack: + *s_out = "DW_TAG_GNU_template_parameter_pack"; + return DW_DLV_OK; + case DW_TAG_GNU_formal_parameter_pack: + *s_out = "DW_TAG_GNU_formal_parameter_pack"; + return DW_DLV_OK; + case DW_TAG_SUN_function_template: + *s_out = "DW_TAG_SUN_function_template"; + return DW_DLV_OK; + case DW_TAG_SUN_class_template: + *s_out = "DW_TAG_SUN_class_template"; + return DW_DLV_OK; + case DW_TAG_SUN_struct_template: + *s_out = "DW_TAG_SUN_struct_template"; + return DW_DLV_OK; + case DW_TAG_SUN_union_template: + *s_out = "DW_TAG_SUN_union_template"; + return DW_DLV_OK; + case DW_TAG_SUN_indirect_inheritance: + *s_out = "DW_TAG_SUN_indirect_inheritance"; + return DW_DLV_OK; + case DW_TAG_SUN_codeflags: + *s_out = "DW_TAG_SUN_codeflags"; + return DW_DLV_OK; + case DW_TAG_SUN_memop_info: + *s_out = "DW_TAG_SUN_memop_info"; + return DW_DLV_OK; + case DW_TAG_SUN_omp_child_func: + *s_out = "DW_TAG_SUN_omp_child_func"; + return DW_DLV_OK; + case DW_TAG_SUN_rtti_descriptor: + *s_out = "DW_TAG_SUN_rtti_descriptor"; + return DW_DLV_OK; + case DW_TAG_SUN_dtor_info: + *s_out = "DW_TAG_SUN_dtor_info"; + return DW_DLV_OK; + case DW_TAG_SUN_dtor: + *s_out = "DW_TAG_SUN_dtor"; + return DW_DLV_OK; + case DW_TAG_SUN_f90_interface: + *s_out = "DW_TAG_SUN_f90_interface"; + return DW_DLV_OK; + case DW_TAG_SUN_fortran_vax_structure: + *s_out = "DW_TAG_SUN_fortran_vax_structure"; + return DW_DLV_OK; + case DW_TAG_SUN_hi: + *s_out = "DW_TAG_SUN_hi"; + return DW_DLV_OK; + case DW_TAG_ALTIUM_circ_type: + *s_out = "DW_TAG_ALTIUM_circ_type"; + return DW_DLV_OK; + case DW_TAG_ALTIUM_mwa_circ_type: + *s_out = "DW_TAG_ALTIUM_mwa_circ_type"; + return DW_DLV_OK; + case DW_TAG_ALTIUM_rev_carry_type: + *s_out = "DW_TAG_ALTIUM_rev_carry_type"; + return DW_DLV_OK; + case DW_TAG_ALTIUM_rom: + *s_out = "DW_TAG_ALTIUM_rom"; + return DW_DLV_OK; + case DW_TAG_upc_shared_type: + *s_out = "DW_TAG_upc_shared_type"; + return DW_DLV_OK; + case DW_TAG_upc_strict_type: + *s_out = "DW_TAG_upc_strict_type"; + return DW_DLV_OK; + case DW_TAG_upc_relaxed_type: + *s_out = "DW_TAG_upc_relaxed_type"; + return DW_DLV_OK; + case DW_TAG_PGI_kanji_type: + *s_out = "DW_TAG_PGI_kanji_type"; + return DW_DLV_OK; + case DW_TAG_PGI_interface_block: + *s_out = "DW_TAG_PGI_interface_block"; + return DW_DLV_OK; + case DW_TAG_hi_user: + *s_out = "DW_TAG_hi_user"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_children_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_children_no: + *s_out = "DW_children_no"; + return DW_DLV_OK; + case DW_children_yes: + *s_out = "DW_children_yes"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_FORM_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_FORM_addr: + *s_out = "DW_FORM_addr"; + return DW_DLV_OK; + case DW_FORM_block2: + *s_out = "DW_FORM_block2"; + return DW_DLV_OK; + case DW_FORM_block4: + *s_out = "DW_FORM_block4"; + return DW_DLV_OK; + case DW_FORM_data2: + *s_out = "DW_FORM_data2"; + return DW_DLV_OK; + case DW_FORM_data4: + *s_out = "DW_FORM_data4"; + return DW_DLV_OK; + case DW_FORM_data8: + *s_out = "DW_FORM_data8"; + return DW_DLV_OK; + case DW_FORM_string: + *s_out = "DW_FORM_string"; + return DW_DLV_OK; + case DW_FORM_block: + *s_out = "DW_FORM_block"; + return DW_DLV_OK; + case DW_FORM_block1: + *s_out = "DW_FORM_block1"; + return DW_DLV_OK; + case DW_FORM_data1: + *s_out = "DW_FORM_data1"; + return DW_DLV_OK; + case DW_FORM_flag: + *s_out = "DW_FORM_flag"; + return DW_DLV_OK; + case DW_FORM_sdata: + *s_out = "DW_FORM_sdata"; + return DW_DLV_OK; + case DW_FORM_strp: + *s_out = "DW_FORM_strp"; + return DW_DLV_OK; + case DW_FORM_udata: + *s_out = "DW_FORM_udata"; + return DW_DLV_OK; + case DW_FORM_ref_addr: + *s_out = "DW_FORM_ref_addr"; + return DW_DLV_OK; + case DW_FORM_ref1: + *s_out = "DW_FORM_ref1"; + return DW_DLV_OK; + case DW_FORM_ref2: + *s_out = "DW_FORM_ref2"; + return DW_DLV_OK; + case DW_FORM_ref4: + *s_out = "DW_FORM_ref4"; + return DW_DLV_OK; + case DW_FORM_ref8: + *s_out = "DW_FORM_ref8"; + return DW_DLV_OK; + case DW_FORM_ref_udata: + *s_out = "DW_FORM_ref_udata"; + return DW_DLV_OK; + case DW_FORM_indirect: + *s_out = "DW_FORM_indirect"; + return DW_DLV_OK; + case DW_FORM_sec_offset: + *s_out = "DW_FORM_sec_offset"; + return DW_DLV_OK; + case DW_FORM_exprloc: + *s_out = "DW_FORM_exprloc"; + return DW_DLV_OK; + case DW_FORM_flag_present: + *s_out = "DW_FORM_flag_present"; + return DW_DLV_OK; + case DW_FORM_ref_sig8: + *s_out = "DW_FORM_ref_sig8"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_AT_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_AT_sibling: + *s_out = "DW_AT_sibling"; + return DW_DLV_OK; + case DW_AT_location: + *s_out = "DW_AT_location"; + return DW_DLV_OK; + case DW_AT_name: + *s_out = "DW_AT_name"; + return DW_DLV_OK; + case DW_AT_ordering: + *s_out = "DW_AT_ordering"; + return DW_DLV_OK; + case DW_AT_subscr_data: + *s_out = "DW_AT_subscr_data"; + return DW_DLV_OK; + case DW_AT_byte_size: + *s_out = "DW_AT_byte_size"; + return DW_DLV_OK; + case DW_AT_bit_offset: + *s_out = "DW_AT_bit_offset"; + return DW_DLV_OK; + case DW_AT_bit_size: + *s_out = "DW_AT_bit_size"; + return DW_DLV_OK; + case DW_AT_element_list: + *s_out = "DW_AT_element_list"; + return DW_DLV_OK; + case DW_AT_stmt_list: + *s_out = "DW_AT_stmt_list"; + return DW_DLV_OK; + case DW_AT_low_pc: + *s_out = "DW_AT_low_pc"; + return DW_DLV_OK; + case DW_AT_high_pc: + *s_out = "DW_AT_high_pc"; + return DW_DLV_OK; + case DW_AT_language: + *s_out = "DW_AT_language"; + return DW_DLV_OK; + case DW_AT_member: + *s_out = "DW_AT_member"; + return DW_DLV_OK; + case DW_AT_discr: + *s_out = "DW_AT_discr"; + return DW_DLV_OK; + case DW_AT_discr_value: + *s_out = "DW_AT_discr_value"; + return DW_DLV_OK; + case DW_AT_visibility: + *s_out = "DW_AT_visibility"; + return DW_DLV_OK; + case DW_AT_import: + *s_out = "DW_AT_import"; + return DW_DLV_OK; + case DW_AT_string_length: + *s_out = "DW_AT_string_length"; + return DW_DLV_OK; + case DW_AT_common_reference: + *s_out = "DW_AT_common_reference"; + return DW_DLV_OK; + case DW_AT_comp_dir: + *s_out = "DW_AT_comp_dir"; + return DW_DLV_OK; + case DW_AT_const_value: + *s_out = "DW_AT_const_value"; + return DW_DLV_OK; + case DW_AT_containing_type: + *s_out = "DW_AT_containing_type"; + return DW_DLV_OK; + case DW_AT_default_value: + *s_out = "DW_AT_default_value"; + return DW_DLV_OK; + case DW_AT_inline: + *s_out = "DW_AT_inline"; + return DW_DLV_OK; + case DW_AT_is_optional: + *s_out = "DW_AT_is_optional"; + return DW_DLV_OK; + case DW_AT_lower_bound: + *s_out = "DW_AT_lower_bound"; + return DW_DLV_OK; + case DW_AT_producer: + *s_out = "DW_AT_producer"; + return DW_DLV_OK; + case DW_AT_prototyped: + *s_out = "DW_AT_prototyped"; + return DW_DLV_OK; + case DW_AT_return_addr: + *s_out = "DW_AT_return_addr"; + return DW_DLV_OK; + case DW_AT_start_scope: + *s_out = "DW_AT_start_scope"; + return DW_DLV_OK; + case DW_AT_bit_stride: + *s_out = "DW_AT_bit_stride"; + return DW_DLV_OK; + case DW_AT_upper_bound: + *s_out = "DW_AT_upper_bound"; + return DW_DLV_OK; + case DW_AT_abstract_origin: + *s_out = "DW_AT_abstract_origin"; + return DW_DLV_OK; + case DW_AT_accessibility: + *s_out = "DW_AT_accessibility"; + return DW_DLV_OK; + case DW_AT_address_class: + *s_out = "DW_AT_address_class"; + return DW_DLV_OK; + case DW_AT_artificial: + *s_out = "DW_AT_artificial"; + return DW_DLV_OK; + case DW_AT_base_types: + *s_out = "DW_AT_base_types"; + return DW_DLV_OK; + case DW_AT_calling_convention: + *s_out = "DW_AT_calling_convention"; + return DW_DLV_OK; + case DW_AT_count: + *s_out = "DW_AT_count"; + return DW_DLV_OK; + case DW_AT_data_member_location: + *s_out = "DW_AT_data_member_location"; + return DW_DLV_OK; + case DW_AT_decl_column: + *s_out = "DW_AT_decl_column"; + return DW_DLV_OK; + case DW_AT_decl_file: + *s_out = "DW_AT_decl_file"; + return DW_DLV_OK; + case DW_AT_decl_line: + *s_out = "DW_AT_decl_line"; + return DW_DLV_OK; + case DW_AT_declaration: + *s_out = "DW_AT_declaration"; + return DW_DLV_OK; + case DW_AT_discr_list: + *s_out = "DW_AT_discr_list"; + return DW_DLV_OK; + case DW_AT_encoding: + *s_out = "DW_AT_encoding"; + return DW_DLV_OK; + case DW_AT_external: + *s_out = "DW_AT_external"; + return DW_DLV_OK; + case DW_AT_frame_base: + *s_out = "DW_AT_frame_base"; + return DW_DLV_OK; + case DW_AT_friend: + *s_out = "DW_AT_friend"; + return DW_DLV_OK; + case DW_AT_identifier_case: + *s_out = "DW_AT_identifier_case"; + return DW_DLV_OK; + case DW_AT_macro_info: + *s_out = "DW_AT_macro_info"; + return DW_DLV_OK; + case DW_AT_namelist_item: + *s_out = "DW_AT_namelist_item"; + return DW_DLV_OK; + case DW_AT_priority: + *s_out = "DW_AT_priority"; + return DW_DLV_OK; + case DW_AT_segment: + *s_out = "DW_AT_segment"; + return DW_DLV_OK; + case DW_AT_specification: + *s_out = "DW_AT_specification"; + return DW_DLV_OK; + case DW_AT_static_link: + *s_out = "DW_AT_static_link"; + return DW_DLV_OK; + case DW_AT_type: + *s_out = "DW_AT_type"; + return DW_DLV_OK; + case DW_AT_use_location: + *s_out = "DW_AT_use_location"; + return DW_DLV_OK; + case DW_AT_variable_parameter: + *s_out = "DW_AT_variable_parameter"; + return DW_DLV_OK; + case DW_AT_virtuality: + *s_out = "DW_AT_virtuality"; + return DW_DLV_OK; + case DW_AT_vtable_elem_location: + *s_out = "DW_AT_vtable_elem_location"; + return DW_DLV_OK; + case DW_AT_allocated: + *s_out = "DW_AT_allocated"; + return DW_DLV_OK; + case DW_AT_associated: + *s_out = "DW_AT_associated"; + return DW_DLV_OK; + case DW_AT_data_location: + *s_out = "DW_AT_data_location"; + return DW_DLV_OK; + case DW_AT_stride: + *s_out = "DW_AT_stride"; + return DW_DLV_OK; + case DW_AT_entry_pc: + *s_out = "DW_AT_entry_pc"; + return DW_DLV_OK; + case DW_AT_use_UTF8: + *s_out = "DW_AT_use_UTF8"; + return DW_DLV_OK; + case DW_AT_extension: + *s_out = "DW_AT_extension"; + return DW_DLV_OK; + case DW_AT_ranges: + *s_out = "DW_AT_ranges"; + return DW_DLV_OK; + case DW_AT_trampoline: + *s_out = "DW_AT_trampoline"; + return DW_DLV_OK; + case DW_AT_call_column: + *s_out = "DW_AT_call_column"; + return DW_DLV_OK; + case DW_AT_call_file: + *s_out = "DW_AT_call_file"; + return DW_DLV_OK; + case DW_AT_call_line: + *s_out = "DW_AT_call_line"; + return DW_DLV_OK; + case DW_AT_description: + *s_out = "DW_AT_description"; + return DW_DLV_OK; + case DW_AT_binary_scale: + *s_out = "DW_AT_binary_scale"; + return DW_DLV_OK; + case DW_AT_decimal_scale: + *s_out = "DW_AT_decimal_scale"; + return DW_DLV_OK; + case DW_AT_small: + *s_out = "DW_AT_small"; + return DW_DLV_OK; + case DW_AT_decimal_sign: + *s_out = "DW_AT_decimal_sign"; + return DW_DLV_OK; + case DW_AT_digit_count: + *s_out = "DW_AT_digit_count"; + return DW_DLV_OK; + case DW_AT_picture_string: + *s_out = "DW_AT_picture_string"; + return DW_DLV_OK; + case DW_AT_mutable: + *s_out = "DW_AT_mutable"; + return DW_DLV_OK; + case DW_AT_threads_scaled: + *s_out = "DW_AT_threads_scaled"; + return DW_DLV_OK; + case DW_AT_explicit: + *s_out = "DW_AT_explicit"; + return DW_DLV_OK; + case DW_AT_object_pointer: + *s_out = "DW_AT_object_pointer"; + return DW_DLV_OK; + case DW_AT_endianity: + *s_out = "DW_AT_endianity"; + return DW_DLV_OK; + case DW_AT_elemental: + *s_out = "DW_AT_elemental"; + return DW_DLV_OK; + case DW_AT_pure: + *s_out = "DW_AT_pure"; + return DW_DLV_OK; + case DW_AT_recursive: + *s_out = "DW_AT_recursive"; + return DW_DLV_OK; + case DW_AT_signature: + *s_out = "DW_AT_signature"; + return DW_DLV_OK; + case DW_AT_main_subprogram: + *s_out = "DW_AT_main_subprogram"; + return DW_DLV_OK; + case DW_AT_data_bit_offset: + *s_out = "DW_AT_data_bit_offset"; + return DW_DLV_OK; + case DW_AT_const_expr: + *s_out = "DW_AT_const_expr"; + return DW_DLV_OK; + case DW_AT_enum_class: + *s_out = "DW_AT_enum_class"; + return DW_DLV_OK; + case DW_AT_linkage_name: + *s_out = "DW_AT_linkage_name"; + return DW_DLV_OK; + case DW_AT_lo_user: + *s_out = "DW_AT_lo_user"; + return DW_DLV_OK; + case DW_AT_HP_unmodifiable: + *s_out = "DW_AT_HP_unmodifiable"; + return DW_DLV_OK; + case DW_AT_MIPS_loop_begin: + *s_out = "DW_AT_MIPS_loop_begin"; + return DW_DLV_OK; + case DW_AT_CPQ_split_lifetimes_var: + *s_out = "DW_AT_CPQ_split_lifetimes_var"; + return DW_DLV_OK; + case DW_AT_MIPS_epilog_begin: + *s_out = "DW_AT_MIPS_epilog_begin"; + return DW_DLV_OK; + case DW_AT_CPQ_prologue_length: + *s_out = "DW_AT_CPQ_prologue_length"; + return DW_DLV_OK; + case DW_AT_MIPS_software_pipeline_depth: + *s_out = "DW_AT_MIPS_software_pipeline_depth"; + return DW_DLV_OK; + case DW_AT_MIPS_linkage_name: + *s_out = "DW_AT_MIPS_linkage_name"; + return DW_DLV_OK; + case DW_AT_MIPS_stride: + *s_out = "DW_AT_MIPS_stride"; + return DW_DLV_OK; + case DW_AT_MIPS_abstract_name: + *s_out = "DW_AT_MIPS_abstract_name"; + return DW_DLV_OK; + case DW_AT_MIPS_clone_origin: + *s_out = "DW_AT_MIPS_clone_origin"; + return DW_DLV_OK; + case DW_AT_MIPS_has_inlines: + *s_out = "DW_AT_MIPS_has_inlines"; + return DW_DLV_OK; + case DW_AT_MIPS_stride_byte: + *s_out = "DW_AT_MIPS_stride_byte"; + return DW_DLV_OK; + case DW_AT_MIPS_stride_elem: + *s_out = "DW_AT_MIPS_stride_elem"; + return DW_DLV_OK; + case DW_AT_MIPS_ptr_dopetype: + *s_out = "DW_AT_MIPS_ptr_dopetype"; + return DW_DLV_OK; + case DW_AT_MIPS_allocatable_dopetype: + *s_out = "DW_AT_MIPS_allocatable_dopetype"; + return DW_DLV_OK; + case DW_AT_MIPS_assumed_shape_dopetype: + *s_out = "DW_AT_MIPS_assumed_shape_dopetype"; + return DW_DLV_OK; + case DW_AT_HP_proc_per_section: + *s_out = "DW_AT_HP_proc_per_section"; + return DW_DLV_OK; + case DW_AT_HP_raw_data_ptr: + *s_out = "DW_AT_HP_raw_data_ptr"; + return DW_DLV_OK; + case DW_AT_HP_pass_by_reference: + *s_out = "DW_AT_HP_pass_by_reference"; + return DW_DLV_OK; + case DW_AT_HP_opt_level: + *s_out = "DW_AT_HP_opt_level"; + return DW_DLV_OK; + case DW_AT_HP_prof_version_id: + *s_out = "DW_AT_HP_prof_version_id"; + return DW_DLV_OK; + case DW_AT_HP_opt_flags: + *s_out = "DW_AT_HP_opt_flags"; + return DW_DLV_OK; + case DW_AT_HP_cold_region_low_pc: + *s_out = "DW_AT_HP_cold_region_low_pc"; + return DW_DLV_OK; + case DW_AT_HP_cold_region_high_pc: + *s_out = "DW_AT_HP_cold_region_high_pc"; + return DW_DLV_OK; + case DW_AT_HP_all_variables_modifiable: + *s_out = "DW_AT_HP_all_variables_modifiable"; + return DW_DLV_OK; + case DW_AT_HP_linkage_name: + *s_out = "DW_AT_HP_linkage_name"; + return DW_DLV_OK; + case DW_AT_HP_prof_flags: + *s_out = "DW_AT_HP_prof_flags"; + return DW_DLV_OK; + case DW_AT_INTEL_other_endian: + *s_out = "DW_AT_INTEL_other_endian"; + return DW_DLV_OK; + case DW_AT_sf_names: + *s_out = "DW_AT_sf_names"; + return DW_DLV_OK; + case DW_AT_src_info: + *s_out = "DW_AT_src_info"; + return DW_DLV_OK; + case DW_AT_mac_info: + *s_out = "DW_AT_mac_info"; + return DW_DLV_OK; + case DW_AT_src_coords: + *s_out = "DW_AT_src_coords"; + return DW_DLV_OK; + case DW_AT_body_begin: + *s_out = "DW_AT_body_begin"; + return DW_DLV_OK; + case DW_AT_body_end: + *s_out = "DW_AT_body_end"; + return DW_DLV_OK; + case DW_AT_GNU_vector: + *s_out = "DW_AT_GNU_vector"; + return DW_DLV_OK; + case DW_AT_GNU_template_name: + *s_out = "DW_AT_GNU_template_name"; + return DW_DLV_OK; + case DW_AT_VMS_rtnbeg_pd_address: + *s_out = "DW_AT_VMS_rtnbeg_pd_address"; + return DW_DLV_OK; + case DW_AT_SUN_alignment: + *s_out = "DW_AT_SUN_alignment"; + return DW_DLV_OK; + case DW_AT_SUN_vtable: + *s_out = "DW_AT_SUN_vtable"; + return DW_DLV_OK; + case DW_AT_SUN_count_guarantee: + *s_out = "DW_AT_SUN_count_guarantee"; + return DW_DLV_OK; + case DW_AT_SUN_command_line: + *s_out = "DW_AT_SUN_command_line"; + return DW_DLV_OK; + case DW_AT_SUN_vbase: + *s_out = "DW_AT_SUN_vbase"; + return DW_DLV_OK; + case DW_AT_SUN_compile_options: + *s_out = "DW_AT_SUN_compile_options"; + return DW_DLV_OK; + case DW_AT_SUN_language: + *s_out = "DW_AT_SUN_language"; + return DW_DLV_OK; + case DW_AT_SUN_browser_file: + *s_out = "DW_AT_SUN_browser_file"; + return DW_DLV_OK; + case DW_AT_SUN_vtable_abi: + *s_out = "DW_AT_SUN_vtable_abi"; + return DW_DLV_OK; + case DW_AT_SUN_func_offsets: + *s_out = "DW_AT_SUN_func_offsets"; + return DW_DLV_OK; + case DW_AT_SUN_cf_kind: + *s_out = "DW_AT_SUN_cf_kind"; + return DW_DLV_OK; + case DW_AT_SUN_vtable_index: + *s_out = "DW_AT_SUN_vtable_index"; + return DW_DLV_OK; + case DW_AT_SUN_omp_tpriv_addr: + *s_out = "DW_AT_SUN_omp_tpriv_addr"; + return DW_DLV_OK; + case DW_AT_SUN_omp_child_func: + *s_out = "DW_AT_SUN_omp_child_func"; + return DW_DLV_OK; + case DW_AT_SUN_func_offset: + *s_out = "DW_AT_SUN_func_offset"; + return DW_DLV_OK; + case DW_AT_SUN_memop_type_ref: + *s_out = "DW_AT_SUN_memop_type_ref"; + return DW_DLV_OK; + case DW_AT_SUN_profile_id: + *s_out = "DW_AT_SUN_profile_id"; + return DW_DLV_OK; + case DW_AT_SUN_memop_signature: + *s_out = "DW_AT_SUN_memop_signature"; + return DW_DLV_OK; + case DW_AT_SUN_obj_dir: + *s_out = "DW_AT_SUN_obj_dir"; + return DW_DLV_OK; + case DW_AT_SUN_obj_file: + *s_out = "DW_AT_SUN_obj_file"; + return DW_DLV_OK; + case DW_AT_SUN_original_name: + *s_out = "DW_AT_SUN_original_name"; + return DW_DLV_OK; + case DW_AT_SUN_hwcprof_signature: + *s_out = "DW_AT_SUN_hwcprof_signature"; + return DW_DLV_OK; + case DW_AT_SUN_amd64_parmdump: + *s_out = "DW_AT_SUN_amd64_parmdump"; + return DW_DLV_OK; + case DW_AT_SUN_part_link_name: + *s_out = "DW_AT_SUN_part_link_name"; + return DW_DLV_OK; + case DW_AT_SUN_link_name: + *s_out = "DW_AT_SUN_link_name"; + return DW_DLV_OK; + case DW_AT_SUN_pass_with_const: + *s_out = "DW_AT_SUN_pass_with_const"; + return DW_DLV_OK; + case DW_AT_SUN_return_with_const: + *s_out = "DW_AT_SUN_return_with_const"; + return DW_DLV_OK; + case DW_AT_SUN_import_by_name: + *s_out = "DW_AT_SUN_import_by_name"; + return DW_DLV_OK; + case DW_AT_SUN_f90_pointer: + *s_out = "DW_AT_SUN_f90_pointer"; + return DW_DLV_OK; + case DW_AT_SUN_pass_by_ref: + *s_out = "DW_AT_SUN_pass_by_ref"; + return DW_DLV_OK; + case DW_AT_SUN_f90_allocatable: + *s_out = "DW_AT_SUN_f90_allocatable"; + return DW_DLV_OK; + case DW_AT_SUN_f90_assumed_shape_array: + *s_out = "DW_AT_SUN_f90_assumed_shape_array"; + return DW_DLV_OK; + case DW_AT_SUN_c_vla: + *s_out = "DW_AT_SUN_c_vla"; + return DW_DLV_OK; + case DW_AT_SUN_return_value_ptr: + *s_out = "DW_AT_SUN_return_value_ptr"; + return DW_DLV_OK; + case DW_AT_SUN_dtor_start: + *s_out = "DW_AT_SUN_dtor_start"; + return DW_DLV_OK; + case DW_AT_SUN_dtor_length: + *s_out = "DW_AT_SUN_dtor_length"; + return DW_DLV_OK; + case DW_AT_SUN_dtor_state_initial: + *s_out = "DW_AT_SUN_dtor_state_initial"; + return DW_DLV_OK; + case DW_AT_SUN_dtor_state_final: + *s_out = "DW_AT_SUN_dtor_state_final"; + return DW_DLV_OK; + case DW_AT_SUN_dtor_state_deltas: + *s_out = "DW_AT_SUN_dtor_state_deltas"; + return DW_DLV_OK; + case DW_AT_SUN_import_by_lname: + *s_out = "DW_AT_SUN_import_by_lname"; + return DW_DLV_OK; + case DW_AT_SUN_f90_use_only: + *s_out = "DW_AT_SUN_f90_use_only"; + return DW_DLV_OK; + case DW_AT_SUN_namelist_spec: + *s_out = "DW_AT_SUN_namelist_spec"; + return DW_DLV_OK; + case DW_AT_SUN_is_omp_child_func: + *s_out = "DW_AT_SUN_is_omp_child_func"; + return DW_DLV_OK; + case DW_AT_SUN_fortran_main_alias: + *s_out = "DW_AT_SUN_fortran_main_alias"; + return DW_DLV_OK; + case DW_AT_SUN_fortran_based: + *s_out = "DW_AT_SUN_fortran_based"; + return DW_DLV_OK; + case DW_AT_ALTIUM_loclist: + *s_out = "DW_AT_ALTIUM_loclist"; + return DW_DLV_OK; + case DW_AT_upc_threads_scaled: + *s_out = "DW_AT_upc_threads_scaled"; + return DW_DLV_OK; + case DW_AT_PGI_lbase: + *s_out = "DW_AT_PGI_lbase"; + return DW_DLV_OK; + case DW_AT_PGI_soffset: + *s_out = "DW_AT_PGI_soffset"; + return DW_DLV_OK; + case DW_AT_PGI_lstride: + *s_out = "DW_AT_PGI_lstride"; + return DW_DLV_OK; + case DW_AT_APPLE_closure: + *s_out = "DW_AT_APPLE_closure"; + return DW_DLV_OK; + case DW_AT_APPLE_major_runtime_vers: + *s_out = "DW_AT_APPLE_major_runtime_vers"; + return DW_DLV_OK; + case DW_AT_APPLE_runtime_class: + *s_out = "DW_AT_APPLE_runtime_class"; + return DW_DLV_OK; + case DW_AT_hi_user: + *s_out = "DW_AT_hi_user"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_OP_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_OP_addr: + *s_out = "DW_OP_addr"; + return DW_DLV_OK; + case DW_OP_deref: + *s_out = "DW_OP_deref"; + return DW_DLV_OK; + case DW_OP_const1u: + *s_out = "DW_OP_const1u"; + return DW_DLV_OK; + case DW_OP_const1s: + *s_out = "DW_OP_const1s"; + return DW_DLV_OK; + case DW_OP_const2u: + *s_out = "DW_OP_const2u"; + return DW_DLV_OK; + case DW_OP_const2s: + *s_out = "DW_OP_const2s"; + return DW_DLV_OK; + case DW_OP_const4u: + *s_out = "DW_OP_const4u"; + return DW_DLV_OK; + case DW_OP_const4s: + *s_out = "DW_OP_const4s"; + return DW_DLV_OK; + case DW_OP_const8u: + *s_out = "DW_OP_const8u"; + return DW_DLV_OK; + case DW_OP_const8s: + *s_out = "DW_OP_const8s"; + return DW_DLV_OK; + case DW_OP_constu: + *s_out = "DW_OP_constu"; + return DW_DLV_OK; + case DW_OP_consts: + *s_out = "DW_OP_consts"; + return DW_DLV_OK; + case DW_OP_dup: + *s_out = "DW_OP_dup"; + return DW_DLV_OK; + case DW_OP_drop: + *s_out = "DW_OP_drop"; + return DW_DLV_OK; + case DW_OP_over: + *s_out = "DW_OP_over"; + return DW_DLV_OK; + case DW_OP_pick: + *s_out = "DW_OP_pick"; + return DW_DLV_OK; + case DW_OP_swap: + *s_out = "DW_OP_swap"; + return DW_DLV_OK; + case DW_OP_rot: + *s_out = "DW_OP_rot"; + return DW_DLV_OK; + case DW_OP_xderef: + *s_out = "DW_OP_xderef"; + return DW_DLV_OK; + case DW_OP_abs: + *s_out = "DW_OP_abs"; + return DW_DLV_OK; + case DW_OP_and: + *s_out = "DW_OP_and"; + return DW_DLV_OK; + case DW_OP_div: + *s_out = "DW_OP_div"; + return DW_DLV_OK; + case DW_OP_minus: + *s_out = "DW_OP_minus"; + return DW_DLV_OK; + case DW_OP_mod: + *s_out = "DW_OP_mod"; + return DW_DLV_OK; + case DW_OP_mul: + *s_out = "DW_OP_mul"; + return DW_DLV_OK; + case DW_OP_neg: + *s_out = "DW_OP_neg"; + return DW_DLV_OK; + case DW_OP_not: + *s_out = "DW_OP_not"; + return DW_DLV_OK; + case DW_OP_or: + *s_out = "DW_OP_or"; + return DW_DLV_OK; + case DW_OP_plus: + *s_out = "DW_OP_plus"; + return DW_DLV_OK; + case DW_OP_plus_uconst: + *s_out = "DW_OP_plus_uconst"; + return DW_DLV_OK; + case DW_OP_shl: + *s_out = "DW_OP_shl"; + return DW_DLV_OK; + case DW_OP_shr: + *s_out = "DW_OP_shr"; + return DW_DLV_OK; + case DW_OP_shra: + *s_out = "DW_OP_shra"; + return DW_DLV_OK; + case DW_OP_xor: + *s_out = "DW_OP_xor"; + return DW_DLV_OK; + case DW_OP_bra: + *s_out = "DW_OP_bra"; + return DW_DLV_OK; + case DW_OP_eq: + *s_out = "DW_OP_eq"; + return DW_DLV_OK; + case DW_OP_ge: + *s_out = "DW_OP_ge"; + return DW_DLV_OK; + case DW_OP_gt: + *s_out = "DW_OP_gt"; + return DW_DLV_OK; + case DW_OP_le: + *s_out = "DW_OP_le"; + return DW_DLV_OK; + case DW_OP_lt: + *s_out = "DW_OP_lt"; + return DW_DLV_OK; + case DW_OP_ne: + *s_out = "DW_OP_ne"; + return DW_DLV_OK; + case DW_OP_skip: + *s_out = "DW_OP_skip"; + return DW_DLV_OK; + case DW_OP_lit0: + *s_out = "DW_OP_lit0"; + return DW_DLV_OK; + case DW_OP_lit1: + *s_out = "DW_OP_lit1"; + return DW_DLV_OK; + case DW_OP_lit2: + *s_out = "DW_OP_lit2"; + return DW_DLV_OK; + case DW_OP_lit3: + *s_out = "DW_OP_lit3"; + return DW_DLV_OK; + case DW_OP_lit4: + *s_out = "DW_OP_lit4"; + return DW_DLV_OK; + case DW_OP_lit5: + *s_out = "DW_OP_lit5"; + return DW_DLV_OK; + case DW_OP_lit6: + *s_out = "DW_OP_lit6"; + return DW_DLV_OK; + case DW_OP_lit7: + *s_out = "DW_OP_lit7"; + return DW_DLV_OK; + case DW_OP_lit8: + *s_out = "DW_OP_lit8"; + return DW_DLV_OK; + case DW_OP_lit9: + *s_out = "DW_OP_lit9"; + return DW_DLV_OK; + case DW_OP_lit10: + *s_out = "DW_OP_lit10"; + return DW_DLV_OK; + case DW_OP_lit11: + *s_out = "DW_OP_lit11"; + return DW_DLV_OK; + case DW_OP_lit12: + *s_out = "DW_OP_lit12"; + return DW_DLV_OK; + case DW_OP_lit13: + *s_out = "DW_OP_lit13"; + return DW_DLV_OK; + case DW_OP_lit14: + *s_out = "DW_OP_lit14"; + return DW_DLV_OK; + case DW_OP_lit15: + *s_out = "DW_OP_lit15"; + return DW_DLV_OK; + case DW_OP_lit16: + *s_out = "DW_OP_lit16"; + return DW_DLV_OK; + case DW_OP_lit17: + *s_out = "DW_OP_lit17"; + return DW_DLV_OK; + case DW_OP_lit18: + *s_out = "DW_OP_lit18"; + return DW_DLV_OK; + case DW_OP_lit19: + *s_out = "DW_OP_lit19"; + return DW_DLV_OK; + case DW_OP_lit20: + *s_out = "DW_OP_lit20"; + return DW_DLV_OK; + case DW_OP_lit21: + *s_out = "DW_OP_lit21"; + return DW_DLV_OK; + case DW_OP_lit22: + *s_out = "DW_OP_lit22"; + return DW_DLV_OK; + case DW_OP_lit23: + *s_out = "DW_OP_lit23"; + return DW_DLV_OK; + case DW_OP_lit24: + *s_out = "DW_OP_lit24"; + return DW_DLV_OK; + case DW_OP_lit25: + *s_out = "DW_OP_lit25"; + return DW_DLV_OK; + case DW_OP_lit26: + *s_out = "DW_OP_lit26"; + return DW_DLV_OK; + case DW_OP_lit27: + *s_out = "DW_OP_lit27"; + return DW_DLV_OK; + case DW_OP_lit28: + *s_out = "DW_OP_lit28"; + return DW_DLV_OK; + case DW_OP_lit29: + *s_out = "DW_OP_lit29"; + return DW_DLV_OK; + case DW_OP_lit30: + *s_out = "DW_OP_lit30"; + return DW_DLV_OK; + case DW_OP_lit31: + *s_out = "DW_OP_lit31"; + return DW_DLV_OK; + case DW_OP_reg0: + *s_out = "DW_OP_reg0"; + return DW_DLV_OK; + case DW_OP_reg1: + *s_out = "DW_OP_reg1"; + return DW_DLV_OK; + case DW_OP_reg2: + *s_out = "DW_OP_reg2"; + return DW_DLV_OK; + case DW_OP_reg3: + *s_out = "DW_OP_reg3"; + return DW_DLV_OK; + case DW_OP_reg4: + *s_out = "DW_OP_reg4"; + return DW_DLV_OK; + case DW_OP_reg5: + *s_out = "DW_OP_reg5"; + return DW_DLV_OK; + case DW_OP_reg6: + *s_out = "DW_OP_reg6"; + return DW_DLV_OK; + case DW_OP_reg7: + *s_out = "DW_OP_reg7"; + return DW_DLV_OK; + case DW_OP_reg8: + *s_out = "DW_OP_reg8"; + return DW_DLV_OK; + case DW_OP_reg9: + *s_out = "DW_OP_reg9"; + return DW_DLV_OK; + case DW_OP_reg10: + *s_out = "DW_OP_reg10"; + return DW_DLV_OK; + case DW_OP_reg11: + *s_out = "DW_OP_reg11"; + return DW_DLV_OK; + case DW_OP_reg12: + *s_out = "DW_OP_reg12"; + return DW_DLV_OK; + case DW_OP_reg13: + *s_out = "DW_OP_reg13"; + return DW_DLV_OK; + case DW_OP_reg14: + *s_out = "DW_OP_reg14"; + return DW_DLV_OK; + case DW_OP_reg15: + *s_out = "DW_OP_reg15"; + return DW_DLV_OK; + case DW_OP_reg16: + *s_out = "DW_OP_reg16"; + return DW_DLV_OK; + case DW_OP_reg17: + *s_out = "DW_OP_reg17"; + return DW_DLV_OK; + case DW_OP_reg18: + *s_out = "DW_OP_reg18"; + return DW_DLV_OK; + case DW_OP_reg19: + *s_out = "DW_OP_reg19"; + return DW_DLV_OK; + case DW_OP_reg20: + *s_out = "DW_OP_reg20"; + return DW_DLV_OK; + case DW_OP_reg21: + *s_out = "DW_OP_reg21"; + return DW_DLV_OK; + case DW_OP_reg22: + *s_out = "DW_OP_reg22"; + return DW_DLV_OK; + case DW_OP_reg23: + *s_out = "DW_OP_reg23"; + return DW_DLV_OK; + case DW_OP_reg24: + *s_out = "DW_OP_reg24"; + return DW_DLV_OK; + case DW_OP_reg25: + *s_out = "DW_OP_reg25"; + return DW_DLV_OK; + case DW_OP_reg26: + *s_out = "DW_OP_reg26"; + return DW_DLV_OK; + case DW_OP_reg27: + *s_out = "DW_OP_reg27"; + return DW_DLV_OK; + case DW_OP_reg28: + *s_out = "DW_OP_reg28"; + return DW_DLV_OK; + case DW_OP_reg29: + *s_out = "DW_OP_reg29"; + return DW_DLV_OK; + case DW_OP_reg30: + *s_out = "DW_OP_reg30"; + return DW_DLV_OK; + case DW_OP_reg31: + *s_out = "DW_OP_reg31"; + return DW_DLV_OK; + case DW_OP_breg0: + *s_out = "DW_OP_breg0"; + return DW_DLV_OK; + case DW_OP_breg1: + *s_out = "DW_OP_breg1"; + return DW_DLV_OK; + case DW_OP_breg2: + *s_out = "DW_OP_breg2"; + return DW_DLV_OK; + case DW_OP_breg3: + *s_out = "DW_OP_breg3"; + return DW_DLV_OK; + case DW_OP_breg4: + *s_out = "DW_OP_breg4"; + return DW_DLV_OK; + case DW_OP_breg5: + *s_out = "DW_OP_breg5"; + return DW_DLV_OK; + case DW_OP_breg6: + *s_out = "DW_OP_breg6"; + return DW_DLV_OK; + case DW_OP_breg7: + *s_out = "DW_OP_breg7"; + return DW_DLV_OK; + case DW_OP_breg8: + *s_out = "DW_OP_breg8"; + return DW_DLV_OK; + case DW_OP_breg9: + *s_out = "DW_OP_breg9"; + return DW_DLV_OK; + case DW_OP_breg10: + *s_out = "DW_OP_breg10"; + return DW_DLV_OK; + case DW_OP_breg11: + *s_out = "DW_OP_breg11"; + return DW_DLV_OK; + case DW_OP_breg12: + *s_out = "DW_OP_breg12"; + return DW_DLV_OK; + case DW_OP_breg13: + *s_out = "DW_OP_breg13"; + return DW_DLV_OK; + case DW_OP_breg14: + *s_out = "DW_OP_breg14"; + return DW_DLV_OK; + case DW_OP_breg15: + *s_out = "DW_OP_breg15"; + return DW_DLV_OK; + case DW_OP_breg16: + *s_out = "DW_OP_breg16"; + return DW_DLV_OK; + case DW_OP_breg17: + *s_out = "DW_OP_breg17"; + return DW_DLV_OK; + case DW_OP_breg18: + *s_out = "DW_OP_breg18"; + return DW_DLV_OK; + case DW_OP_breg19: + *s_out = "DW_OP_breg19"; + return DW_DLV_OK; + case DW_OP_breg20: + *s_out = "DW_OP_breg20"; + return DW_DLV_OK; + case DW_OP_breg21: + *s_out = "DW_OP_breg21"; + return DW_DLV_OK; + case DW_OP_breg22: + *s_out = "DW_OP_breg22"; + return DW_DLV_OK; + case DW_OP_breg23: + *s_out = "DW_OP_breg23"; + return DW_DLV_OK; + case DW_OP_breg24: + *s_out = "DW_OP_breg24"; + return DW_DLV_OK; + case DW_OP_breg25: + *s_out = "DW_OP_breg25"; + return DW_DLV_OK; + case DW_OP_breg26: + *s_out = "DW_OP_breg26"; + return DW_DLV_OK; + case DW_OP_breg27: + *s_out = "DW_OP_breg27"; + return DW_DLV_OK; + case DW_OP_breg28: + *s_out = "DW_OP_breg28"; + return DW_DLV_OK; + case DW_OP_breg29: + *s_out = "DW_OP_breg29"; + return DW_DLV_OK; + case DW_OP_breg30: + *s_out = "DW_OP_breg30"; + return DW_DLV_OK; + case DW_OP_breg31: + *s_out = "DW_OP_breg31"; + return DW_DLV_OK; + case DW_OP_regx: + *s_out = "DW_OP_regx"; + return DW_DLV_OK; + case DW_OP_fbreg: + *s_out = "DW_OP_fbreg"; + return DW_DLV_OK; + case DW_OP_bregx: + *s_out = "DW_OP_bregx"; + return DW_DLV_OK; + case DW_OP_piece: + *s_out = "DW_OP_piece"; + return DW_DLV_OK; + case DW_OP_deref_size: + *s_out = "DW_OP_deref_size"; + return DW_DLV_OK; + case DW_OP_xderef_size: + *s_out = "DW_OP_xderef_size"; + return DW_DLV_OK; + case DW_OP_nop: + *s_out = "DW_OP_nop"; + return DW_DLV_OK; + case DW_OP_push_object_address: + *s_out = "DW_OP_push_object_address"; + return DW_DLV_OK; + case DW_OP_call2: + *s_out = "DW_OP_call2"; + return DW_DLV_OK; + case DW_OP_call4: + *s_out = "DW_OP_call4"; + return DW_DLV_OK; + case DW_OP_call_ref: + *s_out = "DW_OP_call_ref"; + return DW_DLV_OK; + case DW_OP_form_tls_address: + *s_out = "DW_OP_form_tls_address"; + return DW_DLV_OK; + case DW_OP_call_frame_cfa: + *s_out = "DW_OP_call_frame_cfa"; + return DW_DLV_OK; + case DW_OP_bit_piece: + *s_out = "DW_OP_bit_piece"; + return DW_DLV_OK; + case DW_OP_implicit_value: + *s_out = "DW_OP_implicit_value"; + return DW_DLV_OK; + case DW_OP_stack_value: + *s_out = "DW_OP_stack_value"; + return DW_DLV_OK; + case DW_OP_lo_user: + *s_out = "DW_OP_lo_user"; + return DW_DLV_OK; + case DW_OP_HP_is_value: + *s_out = "DW_OP_HP_is_value"; + return DW_DLV_OK; + case DW_OP_HP_fltconst4: + *s_out = "DW_OP_HP_fltconst4"; + return DW_DLV_OK; + case DW_OP_HP_fltconst8: + *s_out = "DW_OP_HP_fltconst8"; + return DW_DLV_OK; + case DW_OP_HP_mod_range: + *s_out = "DW_OP_HP_mod_range"; + return DW_DLV_OK; + case DW_OP_HP_unmod_range: + *s_out = "DW_OP_HP_unmod_range"; + return DW_DLV_OK; + case DW_OP_HP_tls: + *s_out = "DW_OP_HP_tls"; + return DW_DLV_OK; + case DW_OP_INTEL_bit_piece: + *s_out = "DW_OP_INTEL_bit_piece"; + return DW_DLV_OK; + case DW_OP_APPLE_uninit: + *s_out = "DW_OP_APPLE_uninit"; + return DW_DLV_OK; + case DW_OP_hi_user: + *s_out = "DW_OP_hi_user"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_ATE_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_ATE_address: + *s_out = "DW_ATE_address"; + return DW_DLV_OK; + case DW_ATE_boolean: + *s_out = "DW_ATE_boolean"; + return DW_DLV_OK; + case DW_ATE_complex_float: + *s_out = "DW_ATE_complex_float"; + return DW_DLV_OK; + case DW_ATE_float: + *s_out = "DW_ATE_float"; + return DW_DLV_OK; + case DW_ATE_signed: + *s_out = "DW_ATE_signed"; + return DW_DLV_OK; + case DW_ATE_signed_char: + *s_out = "DW_ATE_signed_char"; + return DW_DLV_OK; + case DW_ATE_unsigned: + *s_out = "DW_ATE_unsigned"; + return DW_DLV_OK; + case DW_ATE_unsigned_char: + *s_out = "DW_ATE_unsigned_char"; + return DW_DLV_OK; + case DW_ATE_imaginary_float: + *s_out = "DW_ATE_imaginary_float"; + return DW_DLV_OK; + case DW_ATE_packed_decimal: + *s_out = "DW_ATE_packed_decimal"; + return DW_DLV_OK; + case DW_ATE_numeric_string: + *s_out = "DW_ATE_numeric_string"; + return DW_DLV_OK; + case DW_ATE_edited: + *s_out = "DW_ATE_edited"; + return DW_DLV_OK; + case DW_ATE_signed_fixed: + *s_out = "DW_ATE_signed_fixed"; + return DW_DLV_OK; + case DW_ATE_unsigned_fixed: + *s_out = "DW_ATE_unsigned_fixed"; + return DW_DLV_OK; + case DW_ATE_decimal_float: + *s_out = "DW_ATE_decimal_float"; + return DW_DLV_OK; + case DW_ATE_HP_float80: + *s_out = "DW_ATE_HP_float80"; + return DW_DLV_OK; + case DW_ATE_HP_complex_float80: + *s_out = "DW_ATE_HP_complex_float80"; + return DW_DLV_OK; + case DW_ATE_HP_float128: + *s_out = "DW_ATE_HP_float128"; + return DW_DLV_OK; + case DW_ATE_HP_complex_float128: + *s_out = "DW_ATE_HP_complex_float128"; + return DW_DLV_OK; + case DW_ATE_HP_floathpintel: + *s_out = "DW_ATE_HP_floathpintel"; + return DW_DLV_OK; + case DW_ATE_HP_imaginary_float80: + *s_out = "DW_ATE_HP_imaginary_float80"; + return DW_DLV_OK; + case DW_ATE_HP_imaginary_float128: + *s_out = "DW_ATE_HP_imaginary_float128"; + return DW_DLV_OK; + case DW_ATE_SUN_interval_float: + *s_out = "DW_ATE_SUN_interval_float"; + return DW_DLV_OK; + case DW_ATE_SUN_imaginary_float: + *s_out = "DW_ATE_SUN_imaginary_float"; + return DW_DLV_OK; + case DW_ATE_hi_user: + *s_out = "DW_ATE_hi_user"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_DS_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_DS_unsigned: + *s_out = "DW_DS_unsigned"; + return DW_DLV_OK; + case DW_DS_leading_overpunch: + *s_out = "DW_DS_leading_overpunch"; + return DW_DLV_OK; + case DW_DS_trailing_overpunch: + *s_out = "DW_DS_trailing_overpunch"; + return DW_DLV_OK; + case DW_DS_leading_separate: + *s_out = "DW_DS_leading_separate"; + return DW_DLV_OK; + case DW_DS_trailing_separate: + *s_out = "DW_DS_trailing_separate"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_END_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_END_default: + *s_out = "DW_END_default"; + return DW_DLV_OK; + case DW_END_big: + *s_out = "DW_END_big"; + return DW_DLV_OK; + case DW_END_little: + *s_out = "DW_END_little"; + return DW_DLV_OK; + case DW_END_lo_user: + *s_out = "DW_END_lo_user"; + return DW_DLV_OK; + case DW_END_hi_user: + *s_out = "DW_END_hi_user"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_ATCF_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_ATCF_lo_user: + *s_out = "DW_ATCF_lo_user"; + return DW_DLV_OK; + case DW_ATCF_SUN_mop_bitfield: + *s_out = "DW_ATCF_SUN_mop_bitfield"; + return DW_DLV_OK; + case DW_ATCF_SUN_mop_spill: + *s_out = "DW_ATCF_SUN_mop_spill"; + return DW_DLV_OK; + case DW_ATCF_SUN_mop_scopy: + *s_out = "DW_ATCF_SUN_mop_scopy"; + return DW_DLV_OK; + case DW_ATCF_SUN_func_start: + *s_out = "DW_ATCF_SUN_func_start"; + return DW_DLV_OK; + case DW_ATCF_SUN_end_ctors: + *s_out = "DW_ATCF_SUN_end_ctors"; + return DW_DLV_OK; + case DW_ATCF_SUN_branch_target: + *s_out = "DW_ATCF_SUN_branch_target"; + return DW_DLV_OK; + case DW_ATCF_SUN_mop_stack_probe: + *s_out = "DW_ATCF_SUN_mop_stack_probe"; + return DW_DLV_OK; + case DW_ATCF_SUN_func_epilog: + *s_out = "DW_ATCF_SUN_func_epilog"; + return DW_DLV_OK; + case DW_ATCF_hi_user: + *s_out = "DW_ATCF_hi_user"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_ACCESS_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_ACCESS_public: + *s_out = "DW_ACCESS_public"; + return DW_DLV_OK; + case DW_ACCESS_protected: + *s_out = "DW_ACCESS_protected"; + return DW_DLV_OK; + case DW_ACCESS_private: + *s_out = "DW_ACCESS_private"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_VIS_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_VIS_local: + *s_out = "DW_VIS_local"; + return DW_DLV_OK; + case DW_VIS_exported: + *s_out = "DW_VIS_exported"; + return DW_DLV_OK; + case DW_VIS_qualified: + *s_out = "DW_VIS_qualified"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_VIRTUALITY_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_VIRTUALITY_none: + *s_out = "DW_VIRTUALITY_none"; + return DW_DLV_OK; + case DW_VIRTUALITY_virtual: + *s_out = "DW_VIRTUALITY_virtual"; + return DW_DLV_OK; + case DW_VIRTUALITY_pure_virtual: + *s_out = "DW_VIRTUALITY_pure_virtual"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_LANG_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_LANG_C89: + *s_out = "DW_LANG_C89"; + return DW_DLV_OK; + case DW_LANG_C: + *s_out = "DW_LANG_C"; + return DW_DLV_OK; + case DW_LANG_Ada83: + *s_out = "DW_LANG_Ada83"; + return DW_DLV_OK; + case DW_LANG_C_plus_plus: + *s_out = "DW_LANG_C_plus_plus"; + return DW_DLV_OK; + case DW_LANG_Cobol74: + *s_out = "DW_LANG_Cobol74"; + return DW_DLV_OK; + case DW_LANG_Cobol85: + *s_out = "DW_LANG_Cobol85"; + return DW_DLV_OK; + case DW_LANG_Fortran77: + *s_out = "DW_LANG_Fortran77"; + return DW_DLV_OK; + case DW_LANG_Fortran90: + *s_out = "DW_LANG_Fortran90"; + return DW_DLV_OK; + case DW_LANG_Pascal83: + *s_out = "DW_LANG_Pascal83"; + return DW_DLV_OK; + case DW_LANG_Modula2: + *s_out = "DW_LANG_Modula2"; + return DW_DLV_OK; + case DW_LANG_Java: + *s_out = "DW_LANG_Java"; + return DW_DLV_OK; + case DW_LANG_C99: + *s_out = "DW_LANG_C99"; + return DW_DLV_OK; + case DW_LANG_Ada95: + *s_out = "DW_LANG_Ada95"; + return DW_DLV_OK; + case DW_LANG_Fortran95: + *s_out = "DW_LANG_Fortran95"; + return DW_DLV_OK; + case DW_LANG_PLI: + *s_out = "DW_LANG_PLI"; + return DW_DLV_OK; + case DW_LANG_ObjC: + *s_out = "DW_LANG_ObjC"; + return DW_DLV_OK; + case DW_LANG_ObjC_plus_plus: + *s_out = "DW_LANG_ObjC_plus_plus"; + return DW_DLV_OK; + case DW_LANG_UPC: + *s_out = "DW_LANG_UPC"; + return DW_DLV_OK; + case DW_LANG_D: + *s_out = "DW_LANG_D"; + return DW_DLV_OK; + case DW_LANG_Python: + *s_out = "DW_LANG_Python"; + return DW_DLV_OK; + case DW_LANG_OpenCL: + *s_out = "DW_LANG_OpenCL"; + return DW_DLV_OK; + case DW_LANG_Go: + *s_out = "DW_LANG_Go"; + return DW_DLV_OK; + case DW_LANG_lo_user: + *s_out = "DW_LANG_lo_user"; + return DW_DLV_OK; + case DW_LANG_Mips_Assembler: + *s_out = "DW_LANG_Mips_Assembler"; + return DW_DLV_OK; + case DW_LANG_Upc: + *s_out = "DW_LANG_Upc"; + return DW_DLV_OK; + case DW_LANG_SUN_Assembler: + *s_out = "DW_LANG_SUN_Assembler"; + return DW_DLV_OK; + case DW_LANG_ALTIUM_Assembler: + *s_out = "DW_LANG_ALTIUM_Assembler"; + return DW_DLV_OK; + case DW_LANG_hi_user: + *s_out = "DW_LANG_hi_user"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_ID_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_ID_case_sensitive: + *s_out = "DW_ID_case_sensitive"; + return DW_DLV_OK; + case DW_ID_up_case: + *s_out = "DW_ID_up_case"; + return DW_DLV_OK; + case DW_ID_down_case: + *s_out = "DW_ID_down_case"; + return DW_DLV_OK; + case DW_ID_case_insensitive: + *s_out = "DW_ID_case_insensitive"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_CC_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_CC_normal: + *s_out = "DW_CC_normal"; + return DW_DLV_OK; + case DW_CC_program: + *s_out = "DW_CC_program"; + return DW_DLV_OK; + case DW_CC_nocall: + *s_out = "DW_CC_nocall"; + return DW_DLV_OK; + case DW_CC_lo_user: + *s_out = "DW_CC_lo_user"; + return DW_DLV_OK; + case DW_CC_ALTIUM_interrupt: + *s_out = "DW_CC_ALTIUM_interrupt"; + return DW_DLV_OK; + case DW_CC_ALTIUM_near_system_stack: + *s_out = "DW_CC_ALTIUM_near_system_stack"; + return DW_DLV_OK; + case DW_CC_ALTIUM_near_user_stack: + *s_out = "DW_CC_ALTIUM_near_user_stack"; + return DW_DLV_OK; + case DW_CC_ALTIUM_huge_user_stack: + *s_out = "DW_CC_ALTIUM_huge_user_stack"; + return DW_DLV_OK; + case DW_CC_hi_user: + *s_out = "DW_CC_hi_user"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_INL_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_INL_not_inlined: + *s_out = "DW_INL_not_inlined"; + return DW_DLV_OK; + case DW_INL_inlined: + *s_out = "DW_INL_inlined"; + return DW_DLV_OK; + case DW_INL_declared_not_inlined: + *s_out = "DW_INL_declared_not_inlined"; + return DW_DLV_OK; + case DW_INL_declared_inlined: + *s_out = "DW_INL_declared_inlined"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_ORD_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_ORD_row_major: + *s_out = "DW_ORD_row_major"; + return DW_DLV_OK; + case DW_ORD_col_major: + *s_out = "DW_ORD_col_major"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_DSC_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_DSC_label: + *s_out = "DW_DSC_label"; + return DW_DLV_OK; + case DW_DSC_range: + *s_out = "DW_DSC_range"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_LNS_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_LNS_copy: + *s_out = "DW_LNS_copy"; + return DW_DLV_OK; + case DW_LNS_advance_pc: + *s_out = "DW_LNS_advance_pc"; + return DW_DLV_OK; + case DW_LNS_advance_line: + *s_out = "DW_LNS_advance_line"; + return DW_DLV_OK; + case DW_LNS_set_file: + *s_out = "DW_LNS_set_file"; + return DW_DLV_OK; + case DW_LNS_set_column: + *s_out = "DW_LNS_set_column"; + return DW_DLV_OK; + case DW_LNS_negate_stmt: + *s_out = "DW_LNS_negate_stmt"; + return DW_DLV_OK; + case DW_LNS_set_basic_block: + *s_out = "DW_LNS_set_basic_block"; + return DW_DLV_OK; + case DW_LNS_const_add_pc: + *s_out = "DW_LNS_const_add_pc"; + return DW_DLV_OK; + case DW_LNS_fixed_advance_pc: + *s_out = "DW_LNS_fixed_advance_pc"; + return DW_DLV_OK; + case DW_LNS_set_prologue_end: + *s_out = "DW_LNS_set_prologue_end"; + return DW_DLV_OK; + case DW_LNS_set_epilogue_begin: + *s_out = "DW_LNS_set_epilogue_begin"; + return DW_DLV_OK; + case DW_LNS_set_isa: + *s_out = "DW_LNS_set_isa"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_LNE_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_LNE_end_sequence: + *s_out = "DW_LNE_end_sequence"; + return DW_DLV_OK; + case DW_LNE_set_address: + *s_out = "DW_LNE_set_address"; + return DW_DLV_OK; + case DW_LNE_define_file: + *s_out = "DW_LNE_define_file"; + return DW_DLV_OK; + case DW_LNE_set_discriminator: + *s_out = "DW_LNE_set_discriminator"; + return DW_DLV_OK; + case DW_LNE_HP_negate_is_UV_update: + *s_out = "DW_LNE_HP_negate_is_UV_update"; + return DW_DLV_OK; + case DW_LNE_HP_push_context: + *s_out = "DW_LNE_HP_push_context"; + return DW_DLV_OK; + case DW_LNE_HP_pop_context: + *s_out = "DW_LNE_HP_pop_context"; + return DW_DLV_OK; + case DW_LNE_HP_set_file_line_column: + *s_out = "DW_LNE_HP_set_file_line_column"; + return DW_DLV_OK; + case DW_LNE_HP_set_routine_name: + *s_out = "DW_LNE_HP_set_routine_name"; + return DW_DLV_OK; + case DW_LNE_HP_set_sequence: + *s_out = "DW_LNE_HP_set_sequence"; + return DW_DLV_OK; + case DW_LNE_HP_negate_post_semantics: + *s_out = "DW_LNE_HP_negate_post_semantics"; + return DW_DLV_OK; + case DW_LNE_HP_negate_function_exit: + *s_out = "DW_LNE_HP_negate_function_exit"; + return DW_DLV_OK; + case DW_LNE_HP_negate_front_end_logical: + *s_out = "DW_LNE_HP_negate_front_end_logical"; + return DW_DLV_OK; + case DW_LNE_HP_define_proc: + *s_out = "DW_LNE_HP_define_proc"; + return DW_DLV_OK; + case DW_LNE_lo_user: + *s_out = "DW_LNE_lo_user"; + return DW_DLV_OK; + case DW_LNE_hi_user: + *s_out = "DW_LNE_hi_user"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_ISA_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_ISA_UNKNOWN: + *s_out = "DW_ISA_UNKNOWN"; + return DW_DLV_OK; + case DW_ISA_ARM_thumb: + *s_out = "DW_ISA_ARM_thumb"; + return DW_DLV_OK; + case DW_ISA_ARM_arm: + *s_out = "DW_ISA_ARM_arm"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_MACINFO_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_MACINFO_define: + *s_out = "DW_MACINFO_define"; + return DW_DLV_OK; + case DW_MACINFO_undef: + *s_out = "DW_MACINFO_undef"; + return DW_DLV_OK; + case DW_MACINFO_start_file: + *s_out = "DW_MACINFO_start_file"; + return DW_DLV_OK; + case DW_MACINFO_end_file: + *s_out = "DW_MACINFO_end_file"; + return DW_DLV_OK; + case DW_MACINFO_vendor_ext: + *s_out = "DW_MACINFO_vendor_ext"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_CFA_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_CFA_extended: + *s_out = "DW_CFA_extended"; + return DW_DLV_OK; + case DW_CFA_set_loc: + *s_out = "DW_CFA_set_loc"; + return DW_DLV_OK; + case DW_CFA_advance_loc1: + *s_out = "DW_CFA_advance_loc1"; + return DW_DLV_OK; + case DW_CFA_advance_loc2: + *s_out = "DW_CFA_advance_loc2"; + return DW_DLV_OK; + case DW_CFA_advance_loc4: + *s_out = "DW_CFA_advance_loc4"; + return DW_DLV_OK; + case DW_CFA_offset_extended: + *s_out = "DW_CFA_offset_extended"; + return DW_DLV_OK; + case DW_CFA_restore_extended: + *s_out = "DW_CFA_restore_extended"; + return DW_DLV_OK; + case DW_CFA_undefined: + *s_out = "DW_CFA_undefined"; + return DW_DLV_OK; + case DW_CFA_same_value: + *s_out = "DW_CFA_same_value"; + return DW_DLV_OK; + case DW_CFA_register: + *s_out = "DW_CFA_register"; + return DW_DLV_OK; + case DW_CFA_remember_state: + *s_out = "DW_CFA_remember_state"; + return DW_DLV_OK; + case DW_CFA_restore_state: + *s_out = "DW_CFA_restore_state"; + return DW_DLV_OK; + case DW_CFA_def_cfa: + *s_out = "DW_CFA_def_cfa"; + return DW_DLV_OK; + case DW_CFA_def_cfa_register: + *s_out = "DW_CFA_def_cfa_register"; + return DW_DLV_OK; + case DW_CFA_def_cfa_offset: + *s_out = "DW_CFA_def_cfa_offset"; + return DW_DLV_OK; + case DW_CFA_def_cfa_expression: + *s_out = "DW_CFA_def_cfa_expression"; + return DW_DLV_OK; + case DW_CFA_expression: + *s_out = "DW_CFA_expression"; + return DW_DLV_OK; + case DW_CFA_offset_extended_sf: + *s_out = "DW_CFA_offset_extended_sf"; + return DW_DLV_OK; + case DW_CFA_def_cfa_sf: + *s_out = "DW_CFA_def_cfa_sf"; + return DW_DLV_OK; + case DW_CFA_def_cfa_offset_sf: + *s_out = "DW_CFA_def_cfa_offset_sf"; + return DW_DLV_OK; + case DW_CFA_val_offset: + *s_out = "DW_CFA_val_offset"; + return DW_DLV_OK; + case DW_CFA_val_offset_sf: + *s_out = "DW_CFA_val_offset_sf"; + return DW_DLV_OK; + case DW_CFA_val_expression: + *s_out = "DW_CFA_val_expression"; + return DW_DLV_OK; + case DW_CFA_lo_user: + *s_out = "DW_CFA_lo_user"; + return DW_DLV_OK; + case DW_CFA_MIPS_advance_loc8: + *s_out = "DW_CFA_MIPS_advance_loc8"; + return DW_DLV_OK; + case DW_CFA_GNU_window_save: + *s_out = "DW_CFA_GNU_window_save"; + return DW_DLV_OK; + case DW_CFA_GNU_args_size: + *s_out = "DW_CFA_GNU_args_size"; + return DW_DLV_OK; + case DW_CFA_GNU_negative_offset_extended: + *s_out = "DW_CFA_GNU_negative_offset_extended"; + return DW_DLV_OK; + case DW_CFA_high_user: + *s_out = "DW_CFA_high_user"; + return DW_DLV_OK; + case DW_CFA_advance_loc: + *s_out = "DW_CFA_advance_loc"; + return DW_DLV_OK; + case DW_CFA_offset: + *s_out = "DW_CFA_offset"; + return DW_DLV_OK; + case DW_CFA_restore: + *s_out = "DW_CFA_restore"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_EH_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_EH_PE_absptr: + *s_out = "DW_EH_PE_absptr"; + return DW_DLV_OK; + case DW_EH_PE_uleb128: + *s_out = "DW_EH_PE_uleb128"; + return DW_DLV_OK; + case DW_EH_PE_udata2: + *s_out = "DW_EH_PE_udata2"; + return DW_DLV_OK; + case DW_EH_PE_udata4: + *s_out = "DW_EH_PE_udata4"; + return DW_DLV_OK; + case DW_EH_PE_udata8: + *s_out = "DW_EH_PE_udata8"; + return DW_DLV_OK; + case DW_EH_PE_sleb128: + *s_out = "DW_EH_PE_sleb128"; + return DW_DLV_OK; + case DW_EH_PE_sdata2: + *s_out = "DW_EH_PE_sdata2"; + return DW_DLV_OK; + case DW_EH_PE_sdata4: + *s_out = "DW_EH_PE_sdata4"; + return DW_DLV_OK; + case DW_EH_PE_sdata8: + *s_out = "DW_EH_PE_sdata8"; + return DW_DLV_OK; + case DW_EH_PE_pcrel: + *s_out = "DW_EH_PE_pcrel"; + return DW_DLV_OK; + case DW_EH_PE_textrel: + *s_out = "DW_EH_PE_textrel"; + return DW_DLV_OK; + case DW_EH_PE_datarel: + *s_out = "DW_EH_PE_datarel"; + return DW_DLV_OK; + case DW_EH_PE_funcrel: + *s_out = "DW_EH_PE_funcrel"; + return DW_DLV_OK; + case DW_EH_PE_aligned: + *s_out = "DW_EH_PE_aligned"; + return DW_DLV_OK; + case DW_EH_PE_omit: + *s_out = "DW_EH_PE_omit"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_FRAME_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_FRAME_CFA_COL: + *s_out = "DW_FRAME_CFA_COL"; + return DW_DLV_OK; + case DW_FRAME_REG1: + *s_out = "DW_FRAME_REG1"; + return DW_DLV_OK; + case DW_FRAME_REG2: + *s_out = "DW_FRAME_REG2"; + return DW_DLV_OK; + case DW_FRAME_REG3: + *s_out = "DW_FRAME_REG3"; + return DW_DLV_OK; + case DW_FRAME_REG4: + *s_out = "DW_FRAME_REG4"; + return DW_DLV_OK; + case DW_FRAME_REG5: + *s_out = "DW_FRAME_REG5"; + return DW_DLV_OK; + case DW_FRAME_REG6: + *s_out = "DW_FRAME_REG6"; + return DW_DLV_OK; + case DW_FRAME_REG7: + *s_out = "DW_FRAME_REG7"; + return DW_DLV_OK; + case DW_FRAME_REG8: + *s_out = "DW_FRAME_REG8"; + return DW_DLV_OK; + case DW_FRAME_REG9: + *s_out = "DW_FRAME_REG9"; + return DW_DLV_OK; + case DW_FRAME_REG10: + *s_out = "DW_FRAME_REG10"; + return DW_DLV_OK; + case DW_FRAME_REG11: + *s_out = "DW_FRAME_REG11"; + return DW_DLV_OK; + case DW_FRAME_REG12: + *s_out = "DW_FRAME_REG12"; + return DW_DLV_OK; + case DW_FRAME_REG13: + *s_out = "DW_FRAME_REG13"; + return DW_DLV_OK; + case DW_FRAME_REG14: + *s_out = "DW_FRAME_REG14"; + return DW_DLV_OK; + case DW_FRAME_REG15: + *s_out = "DW_FRAME_REG15"; + return DW_DLV_OK; + case DW_FRAME_REG16: + *s_out = "DW_FRAME_REG16"; + return DW_DLV_OK; + case DW_FRAME_REG17: + *s_out = "DW_FRAME_REG17"; + return DW_DLV_OK; + case DW_FRAME_REG18: + *s_out = "DW_FRAME_REG18"; + return DW_DLV_OK; + case DW_FRAME_REG19: + *s_out = "DW_FRAME_REG19"; + return DW_DLV_OK; + case DW_FRAME_REG20: + *s_out = "DW_FRAME_REG20"; + return DW_DLV_OK; + case DW_FRAME_REG21: + *s_out = "DW_FRAME_REG21"; + return DW_DLV_OK; + case DW_FRAME_REG22: + *s_out = "DW_FRAME_REG22"; + return DW_DLV_OK; + case DW_FRAME_REG23: + *s_out = "DW_FRAME_REG23"; + return DW_DLV_OK; + case DW_FRAME_REG24: + *s_out = "DW_FRAME_REG24"; + return DW_DLV_OK; + case DW_FRAME_REG25: + *s_out = "DW_FRAME_REG25"; + return DW_DLV_OK; + case DW_FRAME_REG26: + *s_out = "DW_FRAME_REG26"; + return DW_DLV_OK; + case DW_FRAME_REG27: + *s_out = "DW_FRAME_REG27"; + return DW_DLV_OK; + case DW_FRAME_REG28: + *s_out = "DW_FRAME_REG28"; + return DW_DLV_OK; + case DW_FRAME_REG29: + *s_out = "DW_FRAME_REG29"; + return DW_DLV_OK; + case DW_FRAME_REG30: + *s_out = "DW_FRAME_REG30"; + return DW_DLV_OK; + case DW_FRAME_REG31: + *s_out = "DW_FRAME_REG31"; + return DW_DLV_OK; + case DW_FRAME_FREG0: + *s_out = "DW_FRAME_FREG0"; + return DW_DLV_OK; + case DW_FRAME_FREG1: + *s_out = "DW_FRAME_FREG1"; + return DW_DLV_OK; + case DW_FRAME_FREG2: + *s_out = "DW_FRAME_FREG2"; + return DW_DLV_OK; + case DW_FRAME_FREG3: + *s_out = "DW_FRAME_FREG3"; + return DW_DLV_OK; + case DW_FRAME_FREG4: + *s_out = "DW_FRAME_FREG4"; + return DW_DLV_OK; + case DW_FRAME_FREG5: + *s_out = "DW_FRAME_FREG5"; + return DW_DLV_OK; + case DW_FRAME_FREG6: + *s_out = "DW_FRAME_FREG6"; + return DW_DLV_OK; + case DW_FRAME_FREG7: + *s_out = "DW_FRAME_FREG7"; + return DW_DLV_OK; + case DW_FRAME_FREG8: + *s_out = "DW_FRAME_FREG8"; + return DW_DLV_OK; + case DW_FRAME_FREG9: + *s_out = "DW_FRAME_FREG9"; + return DW_DLV_OK; + case DW_FRAME_FREG10: + *s_out = "DW_FRAME_FREG10"; + return DW_DLV_OK; + case DW_FRAME_FREG11: + *s_out = "DW_FRAME_FREG11"; + return DW_DLV_OK; + case DW_FRAME_FREG12: + *s_out = "DW_FRAME_FREG12"; + return DW_DLV_OK; + case DW_FRAME_FREG13: + *s_out = "DW_FRAME_FREG13"; + return DW_DLV_OK; + case DW_FRAME_FREG14: + *s_out = "DW_FRAME_FREG14"; + return DW_DLV_OK; + case DW_FRAME_FREG15: + *s_out = "DW_FRAME_FREG15"; + return DW_DLV_OK; + case DW_FRAME_FREG16: + *s_out = "DW_FRAME_FREG16"; + return DW_DLV_OK; + case DW_FRAME_FREG17: + *s_out = "DW_FRAME_FREG17"; + return DW_DLV_OK; + case DW_FRAME_FREG18: + *s_out = "DW_FRAME_FREG18"; + return DW_DLV_OK; + case DW_FRAME_FREG19: + *s_out = "DW_FRAME_FREG19"; + return DW_DLV_OK; + case DW_FRAME_FREG20: + *s_out = "DW_FRAME_FREG20"; + return DW_DLV_OK; + case DW_FRAME_FREG21: + *s_out = "DW_FRAME_FREG21"; + return DW_DLV_OK; + case DW_FRAME_FREG22: + *s_out = "DW_FRAME_FREG22"; + return DW_DLV_OK; + case DW_FRAME_FREG23: + *s_out = "DW_FRAME_FREG23"; + return DW_DLV_OK; + case DW_FRAME_FREG24: + *s_out = "DW_FRAME_FREG24"; + return DW_DLV_OK; + case DW_FRAME_FREG25: + *s_out = "DW_FRAME_FREG25"; + return DW_DLV_OK; + case DW_FRAME_FREG26: + *s_out = "DW_FRAME_FREG26"; + return DW_DLV_OK; + case DW_FRAME_FREG27: + *s_out = "DW_FRAME_FREG27"; + return DW_DLV_OK; + case DW_FRAME_FREG28: + *s_out = "DW_FRAME_FREG28"; + return DW_DLV_OK; + case DW_FRAME_FREG29: + *s_out = "DW_FRAME_FREG29"; + return DW_DLV_OK; + case DW_FRAME_FREG30: + *s_out = "DW_FRAME_FREG30"; + return DW_DLV_OK; + case DW_FRAME_HIGHEST_NORMAL_REGISTER: + *s_out = "DW_FRAME_HIGHEST_NORMAL_REGISTER"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_CHILDREN_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_CHILDREN_no: + *s_out = "DW_CHILDREN_no"; + return DW_DLV_OK; + case DW_CHILDREN_yes: + *s_out = "DW_CHILDREN_yes"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} +/* ARGSUSED */ +int +dwarf_get_ADDR_name (unsigned int val,const char ** s_out) +{ + switch (val) { + case DW_ADDR_none: + *s_out = "DW_ADDR_none"; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} + +/* END FILE */ diff --git a/usr/src/lib/libdwarf/common/dwarf_names.h b/usr/src/lib/libdwarf/common/dwarf_names.h new file mode 100644 index 0000000000..6edafa5fdd --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_names.h @@ -0,0 +1,34 @@ +/* Generated routines, do not edit. */ +/* Generated on May 22 2011 03:05:33 */ + +/* BEGIN FILE */ + +extern int dwarf_get_TAG_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_children_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_FORM_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_AT_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_OP_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_ATE_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_DS_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_END_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_ATCF_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_ACCESS_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_VIS_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_VIRTUALITY_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_LANG_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_ID_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_CC_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_INL_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_ORD_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_DSC_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_LNS_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_LNE_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_ISA_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_MACINFO_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_CFA_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_EH_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_FRAME_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_CHILDREN_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_ADDR_name(unsigned int /*val_in*/, const char ** /*s_out */); + +/* END FILE */ diff --git a/usr/src/lib/libdwarf/common/dwarf_opaque.h b/usr/src/lib/libdwarf/common/dwarf_opaque.h new file mode 100644 index 0000000000..b235a9c7b4 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_opaque.h @@ -0,0 +1,339 @@ +/* + + Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. + Portions Copyright (C) 2008-2010 Arxan Technologies, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* The versions applicable by section are: + DWARF2 DWARF3 DWARF4 + .debug_abbrev - - - + .debug_aranges 2 2 2 + .debug_frame 1 3 4 + .debug_info 2 3 4 + .debug_line 2 3 4 + .debug_loc - - - + .debug_macinfo - - - + .debug_pubtypes x 2 2 + .debug_pubnames 2 2 2 + .debug_ranges x - - + .debug_str - - - + .debug_types x x 4 +*/ + +#include + + +struct Dwarf_Die_s { + Dwarf_Byte_Ptr di_debug_info_ptr; + Dwarf_Abbrev_List di_abbrev_list; + Dwarf_CU_Context di_cu_context; + int di_abbrev_code; +}; + +struct Dwarf_Attribute_s { + Dwarf_Half ar_attribute; /* Attribute Value. */ + Dwarf_Half ar_attribute_form; /* Attribute Form. */ + Dwarf_Half ar_attribute_form_direct; + /* Identical to ar_attribute_form except that if + the original form uleb was DW_FORM_indirect, + ar_attribute_form_direct contains DW_FORM_indirect + but ar_attribute_form contains the true form. */ + + Dwarf_CU_Context ar_cu_context; + Dwarf_Small *ar_debug_info_ptr; + Dwarf_Attribute ar_next; +}; + +/* + This structure provides the context for a compilation unit. + Thus, it contains the Dwarf_Debug, cc_dbg, that this cu + belongs to. It contains the information in the compilation + unit header, cc_length, cc_version_stamp, cc_abbrev_offset, + and cc_address_size, in the .debug_info section for that cu. + In addition, it contains the count, cc_count_cu, of the cu + number of that cu in the list of cu's in the .debug_info. + The count starts at 1, ie cc_count_cu is 1 for the first cu, + 2 for the second and so on. This struct also contains a + pointer, cc_abbrev_table, to a list of pairs of abbrev code + and a pointer to the start of that abbrev + in the .debug_abbrev section. + + Each die will also contain a pointer to such a struct to + record the context for that die. + + Notice that a pointer to the CU DIE itself is + Dwarf_Off off2 = cu_context->cc_debug_info_offset; + cu_die_info_ptr = dbg->de_debug_info.dss_data + + off2 + _dwarf_length_of_cu_header(dbg, off2); + + **Updated by dwarf_next_cu_header in dwarf_die_deliv.c +*/ +struct Dwarf_CU_Context_s { + Dwarf_Debug cc_dbg; + /* The sum of cc_length, cc_length_size, and cc_extension_size + is the total length of the CU including its header. */ + Dwarf_Word cc_length; + /* cc_length_size is the size in bytes of an offset. + 4 for 32bit dwarf, 8 for 64bit dwarf (whether MIPS/IRIX + 64bit dwarf or standard 64bit dwarf using the extension + mechanism). */ + Dwarf_Small cc_length_size; + /* cc_extension_size is zero unless this is standard + DWARF3 and later 64bit dwarf using the extension mechanism. + If it is the DWARF3 and later 64bit dwarf cc_extension + size is 4. So for 32bit dwarf and MIPS/IRIX 64bit dwarf + cc_extension_size is zero. */ + Dwarf_Small cc_extension_size; + Dwarf_Half cc_version_stamp; + Dwarf_Sword cc_abbrev_offset; + Dwarf_Small cc_address_size; + /* cc_debug_info_offset is the offset in the section + of the CU header of this CU. Dwarf_Word + should be large enough. */ + Dwarf_Word cc_debug_info_offset; + Dwarf_Byte_Ptr cc_last_abbrev_ptr; + Dwarf_Hash_Table cc_abbrev_hash_table; + Dwarf_CU_Context cc_next; + /*unsigned char cc_offset_length; */ +}; + +/* Consolidates section-specific data in one place. + Section is an Elf specific term, intended as a general + term (for non-Elf objects some code must synthesize the + values somehow). + Makes adding more section-data much simpler. */ +struct Dwarf_Section_s { + Dwarf_Small * dss_data; + Dwarf_Unsigned dss_size; + Dwarf_Word dss_index; + /* dss_addr is the 'section address' which is only + non-zero for a GNU eh section. + Purpose: to handle DW_EH_PE_pcrel encoding. Leaving + it zero is fine for non-elf. */ + Dwarf_Addr dss_addr; + Dwarf_Small dss_data_was_malloc; + + /* For non-elf, leaving the following fields zero + will mean they are ignored. */ + /* dss_link should be zero unless a section has a link + to another (sh_link). Used to access relocation data for + a section (and for symtab section, access its strtab). */ + Dwarf_Word dss_link; + /* The following is used when reading .rela sections + (such sections appear in some .o files). */ + Dwarf_Half dss_reloc_index; /* Zero means ignore the reloc fields. */ + Dwarf_Small * dss_reloc_data; + Dwarf_Unsigned dss_reloc_size; + Dwarf_Addr dss_reloc_addr; + /* dss_reloc_symtab is the sh_link of a .rela to its .symtab, leave + it 0 if non-meaningful. */ + Dwarf_Addr dss_reloc_symtab; + /* dss_reloc_link should be zero unless a reloc section has a link + to another (sh_link). Used to access the symtab for relocations + a section. */ + Dwarf_Word dss_reloc_link; + /* Pointer to the elf symtab, used for elf .rela. Leave it 0 + if not relevant. */ + struct Dwarf_Section_s *dss_symtab; +}; + +/* Overview: if next_to_use== first, no error slots are used. + If next_to_use+1 (mod maxcount) == first the slots are all used +*/ +struct Dwarf_Harmless_s { + unsigned dh_maxcount; + unsigned dh_next_to_use; + unsigned dh_first; + unsigned dh_errs_count; + char ** dh_errors; +}; + +struct Dwarf_Debug_s { + /* All file access methods and support data + are hidden in this structure. + We get a pointer, callers control the lifetime of the + structure and contents. */ + struct Dwarf_Obj_Access_Interface_s *de_obj_file; + + Dwarf_Handler de_errhand; + Dwarf_Ptr de_errarg; + + /* + Context for the compilation_unit just read by a call to + dwarf_next_cu_header. **Updated by dwarf_next_cu_header in + dwarf_die_deliv.c */ + Dwarf_CU_Context de_cu_context; + + /* + Points to linked list of CU Contexts for the CU's already read. + These are only CU's read by dwarf_next_cu_header(). */ + Dwarf_CU_Context de_cu_context_list; + + /* + Points to the last CU Context added to the list by + dwarf_next_cu_header(). */ + Dwarf_CU_Context de_cu_context_list_end; + + /* + This is the list of CU contexts read for dwarf_offdie(). These + may read ahead of dwarf_next_cu_header(). */ + Dwarf_CU_Context de_offdie_cu_context; + Dwarf_CU_Context de_offdie_cu_context_end; + + /* Offset of last byte of last CU read. */ + Dwarf_Word de_info_last_offset; + + /* + Number of bytes in the length, and offset field in various + .debug_* sections. It's not very meaningful, and is + only used in one 'approximate' calculation. */ + Dwarf_Small de_length_size; + + /* number of bytes in a pointer of the target in various .debug_ + sections. 4 in 32bit, 8 in MIPS 64, ia64. */ + Dwarf_Small de_pointer_size; + + /* set at creation of a Dwarf_Debug to say if form_string should be + checked for valid length at every call. 0 means do the check. + non-zero means do not do the check. */ + Dwarf_Small de_assume_string_in_bounds; + + /* + Dwarf_Alloc_Hdr_s structs used to manage chunks that are + malloc'ed for each allocation type for structs. */ + struct Dwarf_Alloc_Hdr_s de_alloc_hdr[ALLOC_AREA_REAL_TABLE_MAX]; +#ifdef DWARF_SIMPLE_MALLOC + struct simple_malloc_record_s * de_simple_malloc_base; +#endif + + + /* + These fields are used to process debug_frame section. **Updated + by dwarf_get_fde_list in dwarf_frame.h */ + /* + Points to contiguous block of pointers to Dwarf_Cie_s structs. */ + Dwarf_Cie *de_cie_data; + /* Count of number of Dwarf_Cie_s structs. */ + Dwarf_Signed de_cie_count; + /* Keep eh (GNU) separate!. */ + Dwarf_Cie *de_cie_data_eh; + Dwarf_Signed de_cie_count_eh; + /* + Points to contiguous block of pointers to Dwarf_Fde_s structs. */ + Dwarf_Fde *de_fde_data; + /* Count of number of Dwarf_Fde_s structs. */ + Dwarf_Signed de_fde_count; + /* Keep eh (GNU) separate!. */ + Dwarf_Fde *de_fde_data_eh; + Dwarf_Signed de_fde_count_eh; + + struct Dwarf_Section_s de_debug_info; + struct Dwarf_Section_s de_debug_abbrev; + struct Dwarf_Section_s de_debug_line; + struct Dwarf_Section_s de_debug_loc; + struct Dwarf_Section_s de_debug_aranges; + struct Dwarf_Section_s de_debug_macinfo; + struct Dwarf_Section_s de_debug_pubnames; + struct Dwarf_Section_s de_debug_str; + struct Dwarf_Section_s de_debug_frame; + + /* gnu: the g++ eh_frame section */ + struct Dwarf_Section_s de_debug_frame_eh_gnu; + + struct Dwarf_Section_s de_debug_pubtypes; /* DWARF3 .debug_pubtypes */ + + struct Dwarf_Section_s de_debug_funcnames; + struct Dwarf_Section_s de_debug_typenames; /* SGI IRIX extension essentially + identical to DWARF3 .debug_pubtypes. */ + struct Dwarf_Section_s de_debug_varnames; + struct Dwarf_Section_s de_debug_weaknames; + struct Dwarf_Section_s de_debug_ranges; + + /* For non-elf, simply leave the following two structs zeroed and + they will be ignored. */ + struct Dwarf_Section_s de_elf_symtab; + struct Dwarf_Section_s de_elf_strtab; + + + void *(*de_copy_word) (void *, const void *, size_t); + unsigned char de_same_endian; + unsigned char de_elf_must_close; /* if non-zero, then + it was dwarf_init (not dwarf_elf_init) + so must elf_end() */ + + /* Default is DW_FRAME_INITIAL_VALUE from header. */ + Dwarf_Half de_frame_rule_initial_value; + + /* Default is DW_FRAME_LAST_REG_NUM. */ + Dwarf_Half de_frame_reg_rules_entry_count; + + Dwarf_Half de_frame_cfa_col_number; + Dwarf_Half de_frame_same_value_number; + Dwarf_Half de_frame_undefined_value_number; + + unsigned char de_big_endian_object; /* non-zero if big-endian + object opened. */ + + struct Dwarf_Harmless_s de_harmless_errors; +}; + +typedef struct Dwarf_Chain_s *Dwarf_Chain; +struct Dwarf_Chain_s { + void *ch_item; + Dwarf_Chain ch_next; +}; + + +#define CURRENT_VERSION_STAMP 2 /* DWARF2 */ +#define CURRENT_VERSION_STAMP3 3 /* DWARF3 */ +#define CURRENT_VERSION_STAMP4 4 /* DWARF4 */ + + /* Size of cu header version stamp field. */ +#define CU_VERSION_STAMP_SIZE sizeof(Dwarf_Half) + + /* Size of cu header address size field. */ +#define CU_ADDRESS_SIZE_SIZE sizeof(Dwarf_Small) + +void *_dwarf_memcpy_swap_bytes(void *s1, const void *s2, size_t len); + +#define ORIGINAL_DWARF_OFFSET_SIZE 4 +#define DISTINGUISHED_VALUE 0xffffffff +#define DISTINGUISHED_VALUE_OFFSET_SIZE 8 + +/* + We don't load the sections until they are needed. This function is + used to load the section. + */ +int _dwarf_load_section(Dwarf_Debug, + struct Dwarf_Section_s *, + Dwarf_Error *); diff --git a/usr/src/lib/libdwarf/common/dwarf_original_elf_init.c b/usr/src/lib/libdwarf/common/dwarf_original_elf_init.c new file mode 100644 index 0000000000..a6d943da0a --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_original_elf_init.c @@ -0,0 +1,209 @@ +/* + + Copyright (C) 2000,2001,2002,2005,2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2008-2010 Arxan Technologies, Inc. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + +#include "config.h" +#include "dwarf_incl.h" +#include "dwarf_elf_access.h" + +#ifdef HAVE_ELF_H +#include +#endif +#ifdef HAVE_LIBELF_H +#include +#else +#ifdef HAVE_LIBELF_LIBELF_H +#include +#endif +#endif + +#include +#include +#include +#include +#include + +#define DWARF_DBG_ERROR(dbg,errval,retval) \ + _dwarf_error(dbg, error, errval); return(retval); + +#define FALSE 0 +#define TRUE 1 + +static int +dwarf_elf_init_file_ownership(dwarf_elf_handle elf_file_pointer, + int libdwarf_owns_elf, + Dwarf_Unsigned access, + Dwarf_Handler errhand, + Dwarf_Ptr errarg, + Dwarf_Debug * ret_dbg, + Dwarf_Error * error); + + +/* + The basic dwarf initializer function for consumers using + libelf. + Return a libdwarf error code on error, return DW_DLV_OK + if this succeeds. +*/ +int +dwarf_init(int fd, + Dwarf_Unsigned access, + Dwarf_Handler errhand, + Dwarf_Ptr errarg, Dwarf_Debug * ret_dbg, Dwarf_Error * error) +{ + struct stat fstat_buf; + dwarf_elf_handle elf_file_pointer = 0; + /* ELF_C_READ is a portable value */ + Elf_Cmd what_kind_of_elf_read = ELF_C_READ; + +#if !defined(S_ISREG) +#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif + if (fstat(fd, &fstat_buf) != 0) { + DWARF_DBG_ERROR(NULL, DW_DLE_FSTAT_ERROR, DW_DLV_ERROR); + } + if (!S_ISREG(fstat_buf.st_mode)) { + DWARF_DBG_ERROR(NULL, DW_DLE_FSTAT_MODE_ERROR, DW_DLV_ERROR); + } + + if (access != DW_DLC_READ) { + DWARF_DBG_ERROR(NULL, DW_DLE_INIT_ACCESS_WRONG, DW_DLV_ERROR); + } + + elf_version(EV_CURRENT); + /* changed to mmap request per bug 281217. 6/95 */ +#ifdef HAVE_ELF_C_READ_MMAP + /* ELF_C_READ_MMAP is an SGI IRIX specific enum value from IRIX + libelf.h meaning read but use mmap */ + what_kind_of_elf_read = ELF_C_READ_MMAP; +#endif /* !HAVE_ELF_C_READ_MMAP */ + + elf_file_pointer = elf_begin(fd, what_kind_of_elf_read, 0); + if (elf_file_pointer == NULL) { + DWARF_DBG_ERROR(NULL, DW_DLE_ELF_BEGIN_ERROR, DW_DLV_ERROR); + } + + return dwarf_elf_init_file_ownership(elf_file_pointer, + TRUE, + access, + errhand, + errarg, + ret_dbg, + error); +} + +/* + An alternate dwarf setup call for consumers using + libelf. + When the caller has opened libelf already, so the + caller must free libelf. +*/ +int +dwarf_elf_init(dwarf_elf_handle elf_file_pointer, + Dwarf_Unsigned access, + Dwarf_Handler errhand, + Dwarf_Ptr errarg, + Dwarf_Debug * ret_dbg, Dwarf_Error * error) +{ + return dwarf_elf_init_file_ownership(elf_file_pointer, + FALSE, + access, + errhand, + errarg, + ret_dbg, + error); +} + + +/* + Initialize the ELF object access for libdwarf. + */ +static int +dwarf_elf_init_file_ownership(dwarf_elf_handle elf_file_pointer, + int libdwarf_owns_elf, + Dwarf_Unsigned access, + Dwarf_Handler errhand, + Dwarf_Ptr errarg, + Dwarf_Debug * ret_dbg, + Dwarf_Error * error) +{ + /* ELF is no longer tied to libdwarf. */ + Dwarf_Obj_Access_Interface *binary_interface = 0; + int res = DW_DLV_OK; + int err = 0; + + if (access != DW_DLC_READ) { + DWARF_DBG_ERROR(NULL, DW_DLE_INIT_ACCESS_WRONG, DW_DLV_ERROR); + } + + /* This allocates and fills in *binary_interface. */ + res = dwarf_elf_object_access_init( + elf_file_pointer, + libdwarf_owns_elf, + &binary_interface, + &err); + if(res != DW_DLV_OK){ + DWARF_DBG_ERROR(NULL, err, DW_DLV_ERROR); + } + + /* This mallocs space and returns pointer thru ret_dbg, + saving the binary interface in 'ret-dbg' */ + res = dwarf_object_init(binary_interface, errhand, errarg, + ret_dbg, error); + if(res != DW_DLV_OK){ + dwarf_elf_object_access_finish(binary_interface); + } + return res; +} + + +/* + Frees all memory that was not previously freed + by dwarf_dealloc. + Aside from certain categories. + + This is only applicable when dwarf_init() or dwarf_elf_init() + was used to init 'dbg'. +*/ +int +dwarf_finish(Dwarf_Debug dbg, Dwarf_Error * error) +{ + dwarf_elf_object_access_finish(dbg->de_obj_file); + + return dwarf_object_finish(dbg, error); +} + diff --git a/usr/src/lib/libdwarf/common/dwarf_print_lines.c b/usr/src/lib/libdwarf/common/dwarf_print_lines.c new file mode 100644 index 0000000000..30c4889ee5 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_print_lines.c @@ -0,0 +1,737 @@ +/* + + Copyright (C) 2000,2002,2004,2005,2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include +#include "dwarf_line.h" + +/* FIXME Need to add prologue_end epilogue_begin isa fields. */ +static void +print_line_header(void) +{ + printf + (" s b e\n" + " t l s\n" + " m c e\n" + " section op col t k q\n" + " offset code address file line umn ? ? ?\n"); +} + +/* FIXME: print new line values: prologue_end epilogue_begin isa */ +static void +print_line_detail(char *prefix, + int opcode, + Dwarf_Unsigned address, + unsigned long file, + unsigned long line, + unsigned long column, + int is_stmt, int basic_block, int end_sequence, + int prologue_end, int epilogue_begin, int isa) +{ + printf("%-15s %2d 0x%08" DW_PR_DUx " " + "%2lu %4lu %2lu %1d %1d %1d\n", + prefix, + (int) opcode, + (Dwarf_Unsigned) address, + (unsigned long) file, + (unsigned long) line, + (unsigned long) column, + (int) is_stmt, (int) basic_block, (int) end_sequence); + +} + + +/* + return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR + If err_count_out is non-NULL, this is a special 'check' + call. +*/ +int +_dwarf_internal_printlines(Dwarf_Die die, Dwarf_Error * error, + int * err_count_out, int only_line_header) +{ + /* + This pointer is used to scan the portion of the .debug_line + section for the current cu. */ + Dwarf_Small *line_ptr = 0; + Dwarf_Small *orig_line_ptr = 0; + + /* + This points to the last byte of the .debug_line portion for the + current cu. */ + Dwarf_Small *line_ptr_end = 0; + + /* + Pointer to a DW_AT_stmt_list attribute in case it exists in the + die. */ + Dwarf_Attribute stmt_list_attr = 0; + + /* Pointer to DW_AT_comp_dir attribute in die. */ + Dwarf_Attribute comp_dir_attr = 0; + + /* Pointer to name of compilation directory. */ + Dwarf_Small *comp_dir = NULL; + + /* + Offset into .debug_line specified by a DW_AT_stmt_list + attribute. */ + Dwarf_Unsigned line_offset = 0; + + struct Line_Table_Prefix_s prefix; + + + /* These are the state machine state variables. */ + Dwarf_Addr address = 0; + Dwarf_Word file = 1; + Dwarf_Word line = 1; + Dwarf_Word column = 0; + Dwarf_Bool is_stmt = false; + Dwarf_Bool basic_block = false; + Dwarf_Bool end_sequence = false; + Dwarf_Bool prologue_end = false; + Dwarf_Bool epilogue_begin = false; + Dwarf_Small isa = 0; + + + Dwarf_Sword i=0; + + /* + This is the current opcode read from the statement program. */ + Dwarf_Small opcode=0; + + + /* + These variables are used to decode leb128 numbers. Leb128_num + holds the decoded number, and leb128_length is its length in + bytes. */ + Dwarf_Word leb128_num=0; + Dwarf_Word leb128_length=0; + Dwarf_Sword advance_line=0; + Dwarf_Half attrform = 0; + /* + This is the operand of the latest fixed_advance_pc extended + opcode. */ + Dwarf_Half fixed_advance_pc=0; + + /* In case there are wierd bytes 'after' the line table + * prologue this lets us print something. This is a gcc + * compiler bug and we expect the bytes count to be 12. + */ + Dwarf_Small* bogus_bytes_ptr = 0; + Dwarf_Unsigned bogus_bytes_count = 0; + + + /* The Dwarf_Debug this die belongs to. */ + Dwarf_Debug dbg=0; + int resattr = DW_DLV_ERROR; + int lres = DW_DLV_ERROR; + int res = DW_DLV_ERROR; + + /* ***** BEGIN CODE ***** */ + + if (error != NULL) { + *error = NULL; + } + + CHECK_DIE(die, DW_DLV_ERROR); + dbg = die->di_cu_context->cc_dbg; + + res = _dwarf_load_section(dbg, &dbg->de_debug_line,error); + if (res != DW_DLV_OK) { + return res; + } + + resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error); + if (resattr != DW_DLV_OK) { + return resattr; + } + + + /* The list of relevant FORMs is small. + DW_FORM_data4, DW_FORM_data8, DW_FORM_sec_offset + */ + lres = dwarf_whatform(stmt_list_attr,&attrform,error); + if (lres != DW_DLV_OK) { + return lres; + } + if (attrform != DW_FORM_data4 && attrform != DW_FORM_data8 && + attrform != DW_FORM_sec_offset ) { + _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); + return (DW_DLV_ERROR); + } + lres = dwarf_global_formref(stmt_list_attr, &line_offset, error); + if (lres != DW_DLV_OK) { + return lres; + } + + if (line_offset >= dbg->de_debug_line.dss_size) { + _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); + return (DW_DLV_ERROR); + } + orig_line_ptr = dbg->de_debug_line.dss_data; + line_ptr = dbg->de_debug_line.dss_data + line_offset; + dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR); + + /* + If die has DW_AT_comp_dir attribute, get the string that names + the compilation directory. */ + resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error); + if (resattr == DW_DLV_ERROR) { + return resattr; + } + if (resattr == DW_DLV_OK) { + int cres = DW_DLV_ERROR; + char *cdir = 0; + + cres = dwarf_formstring(comp_dir_attr, &cdir, error); + if (cres == DW_DLV_ERROR) { + return cres; + } else if (cres == DW_DLV_OK) { + comp_dir = (Dwarf_Small *) cdir; + } + } + if (resattr == DW_DLV_OK) { + dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR); + } + + dwarf_init_line_table_prefix(&prefix); + { + Dwarf_Small *line_ptr_out = 0; + int dres = dwarf_read_line_table_prefix(dbg, + line_ptr,dbg->de_debug_line.dss_size - line_offset, + &line_ptr_out, + &prefix, + &bogus_bytes_ptr, + &bogus_bytes_count, + error, + err_count_out); + if (dres == DW_DLV_ERROR) { + dwarf_free_line_table_prefix(&prefix); + return dres; + } + if (dres == DW_DLV_NO_ENTRY) { + dwarf_free_line_table_prefix(&prefix); + return dres; + } + line_ptr_end = prefix.pf_line_ptr_end; + line_ptr = line_ptr_out; + } + if(only_line_header) { + /* Just checking for header errors, nothing more here.*/ + dwarf_free_line_table_prefix(&prefix); + return DW_DLV_OK; + } + + + printf("total line info length %ld bytes, " + "line offset 0x%" DW_PR_DUx " %" DW_PR_DSd "\n", + (long) prefix.pf_total_length, + (Dwarf_Unsigned) line_offset, + (Dwarf_Signed) line_offset); + printf("line table version %d\n",(int) prefix.pf_version); + printf("line table length field length %d prologue length %d\n", + (int)prefix.pf_length_field_length, + (int)prefix.pf_prologue_length); + printf("compilation_directory %s\n", + comp_dir ? ((char *) comp_dir) : ""); + + printf(" min instruction length %d\n", + (int) prefix.pf_minimum_instruction_length); + printf(" default is stmt %d\n", (int) + prefix.pf_default_is_stmt); + printf(" line base %d\n", (int) + prefix.pf_line_base); + printf(" line_range %d\n", (int) + prefix.pf_line_range); + printf(" opcode base %d\n", (int) + prefix.pf_opcode_base); + printf(" standard opcode count %d\n", (int) + prefix.pf_std_op_count); + + for (i = 1; i < prefix.pf_opcode_base; i++) { + printf(" opcode[%2d] length %d\n", (int) i, + (int) prefix.pf_opcode_length_table[i - 1]); + } + printf(" include directories count %d\n", (int) + prefix.pf_include_directories_count); + + + for (i = 0; i < prefix.pf_include_directories_count; ++i) { + printf(" include dir[%d] %s\n", + (int) i, prefix.pf_include_directories[i]); + } + printf(" files count %d\n", (int) + prefix.pf_files_count); + + for (i = 0; i < prefix.pf_files_count; ++i) { + struct Line_Table_File_Entry_s *lfile = + prefix.pf_line_table_file_entries + i; + + Dwarf_Unsigned tlm2 = lfile->lte_last_modification_time; + Dwarf_Unsigned di = lfile->lte_directory_index; + Dwarf_Unsigned fl = lfile->lte_length_of_file; + + printf(" file[%d] %s (file-number: %d) \n", + (int) i, (char *) lfile->lte_filename, + (int)(i+1)); + + printf(" dir index %d\n", (int) di); + { + time_t tt = (time_t) tlm2; + + printf(" last time 0x%x %s", /* ctime supplies + newline */ + (unsigned) tlm2, ctime(&tt)); + } + printf(" file length %ld 0x%lx\n", + (long) fl, (unsigned long) fl); + + + } + + + { + Dwarf_Unsigned offset = 0; + if(bogus_bytes_count > 0) { + Dwarf_Unsigned wcount = bogus_bytes_count; + Dwarf_Unsigned boffset = bogus_bytes_ptr - orig_line_ptr; + printf("*** DWARF CHECK: the line table prologue header_length " + " is %" DW_PR_DUu " too high, we pretend it is smaller." + "Section offset: %" DW_PR_DUu " (0x%" DW_PR_DUx ") ***\n", + wcount, boffset,boffset); + *err_count_out += 1; + } + offset = line_ptr - orig_line_ptr; + + printf(" statement prog offset in section: %" DW_PR_DUu " 0x%" DW_PR_DUx "\n", + offset, offset); + } + + /* Initialize the part of the state machine dependent on the + prefix. */ + is_stmt = prefix.pf_default_is_stmt; + + + print_line_header(); + /* Start of statement program. */ + while (line_ptr < line_ptr_end) { + int type = 0; + + printf(" [0x%06" DW_PR_DSx "] ", + (Dwarf_Signed) (line_ptr - orig_line_ptr)); + opcode = *(Dwarf_Small *) line_ptr; + line_ptr++; + /* 'type' is the output */ + WHAT_IS_OPCODE(type, opcode, prefix.pf_opcode_base, + prefix.pf_opcode_length_table, line_ptr, + prefix.pf_std_op_count); + + if (type == LOP_DISCARD) { + int oc; + int opcnt = prefix.pf_opcode_length_table[opcode]; + + printf("*** DWARF CHECK: DISCARD standard opcode %d " + "with %d operands: " + "not understood.", opcode, opcnt); + *err_count_out += 1; + for (oc = 0; oc < opcnt; oc++) { + /* + * Read and discard operands we don't + * understand. + * Arbitrary choice of unsigned read. + * Signed read would work as well. + */ + Dwarf_Unsigned utmp2; + + DECODE_LEB128_UWORD(line_ptr, utmp2); + printf(" %" DW_PR_DUu " (0x%" DW_PR_DUx ")", + (Dwarf_Unsigned) utmp2, + (Dwarf_Unsigned) utmp2); + } + + printf("***\n"); + /* do nothing, necessary ops done */ + } else if (type == LOP_SPECIAL) { + /* This op code is a special op in the object, no matter + that it might fall into the standard op range in this + compile Thatis, these are special opcodes between + special_opcode_base and MAX_LINE_OP_CODE. (including + special_opcode_base and MAX_LINE_OP_CODE) */ + char special[50]; + unsigned origop = opcode; + + opcode = opcode - prefix.pf_opcode_base; + address = address + prefix.pf_minimum_instruction_length * + (opcode / prefix.pf_line_range); + line = + line + prefix.pf_line_base + + opcode % prefix.pf_line_range; + + sprintf(special, "Specialop %3u", origop); + print_line_detail(special, + opcode, address, (int) file, line, column, + is_stmt, basic_block, end_sequence, + prologue_end, epilogue_begin, isa); + + basic_block = false; + + } else if (type == LOP_STANDARD) { + switch (opcode) { + + case DW_LNS_copy:{ + + print_line_detail("DW_LNS_copy", + opcode, address, file, line, + column, is_stmt, basic_block, + end_sequence, prologue_end, + epilogue_begin, isa); + + basic_block = false; + break; + } + + case DW_LNS_advance_pc:{ + Dwarf_Unsigned utmp2; + + + DECODE_LEB128_UWORD(line_ptr, utmp2); + printf("DW_LNS_advance_pc val %" DW_PR_DSd " 0x%" DW_PR_DUx "\n", + (Dwarf_Signed) (Dwarf_Word) utmp2, + (Dwarf_Unsigned) (Dwarf_Word) utmp2); + leb128_num = (Dwarf_Word) utmp2; + address = + address + + prefix.pf_minimum_instruction_length * + leb128_num; + break; + } + + case DW_LNS_advance_line:{ + Dwarf_Signed stmp; + + + DECODE_LEB128_SWORD(line_ptr, stmp); + advance_line = (Dwarf_Sword) stmp; + printf("DW_LNS_advance_line val %" DW_PR_DSd " 0x%" DW_PR_DSx "\n", + (Dwarf_Signed) advance_line, + (Dwarf_Signed) advance_line); + line = line + advance_line; + break; + } + + case DW_LNS_set_file:{ + Dwarf_Unsigned utmp2; + + + DECODE_LEB128_UWORD(line_ptr, utmp2); + file = (Dwarf_Word) utmp2; + printf("DW_LNS_set_file %ld\n", (long) file); + break; + } + + case DW_LNS_set_column:{ + Dwarf_Unsigned utmp2; + + + DECODE_LEB128_UWORD(line_ptr, utmp2); + column = (Dwarf_Word) utmp2; + printf("DW_LNS_set_column val %" DW_PR_DSd " 0x%" DW_PR_DSx "\n", + (Dwarf_Signed) column, (Dwarf_Signed) column); + break; + } + + case DW_LNS_negate_stmt:{ + is_stmt = !is_stmt; + printf("DW_LNS_negate_stmt\n"); + break; + } + + case DW_LNS_set_basic_block:{ + + printf("DW_LNS_set_basic_block\n"); + basic_block = true; + break; + } + + case DW_LNS_const_add_pc:{ + opcode = MAX_LINE_OP_CODE - prefix.pf_opcode_base; + address = + address + + prefix.pf_minimum_instruction_length * (opcode / + prefix. + pf_line_range); + + printf("DW_LNS_const_add_pc new address 0x%" DW_PR_DSx "\n", + (Dwarf_Signed) address); + break; + } + + case DW_LNS_fixed_advance_pc:{ + + READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half, + line_ptr, sizeof(Dwarf_Half)); + line_ptr += sizeof(Dwarf_Half); + address = address + fixed_advance_pc; + printf("DW_LNS_fixed_advance_pc val %" DW_PR_DSd + " 0x%" DW_PR_DSx " new address 0x%" DW_PR_DSx "\n", + (Dwarf_Signed) fixed_advance_pc, + (Dwarf_Signed) fixed_advance_pc, + (Dwarf_Signed) address); + break; + } + case DW_LNS_set_prologue_end:{ + + prologue_end = true; + printf("DW_LNS_set_prologue_end set true.\n"); + break; + + + } + /* New in DWARF3 */ + case DW_LNS_set_epilogue_begin:{ + epilogue_begin = true; + printf("DW_LNS_set_epilogue_begin set true.\n"); + break; + } + + /* New in DWARF3 */ + case DW_LNS_set_isa:{ + Dwarf_Unsigned utmp2; + + DECODE_LEB128_UWORD(line_ptr, utmp2); + isa = utmp2; + printf("DW_LNS_set_isa new value 0x%" DW_PR_DUx ".\n", + (Dwarf_Unsigned) utmp2); + if (isa != utmp2) { + /* The value of the isa did not fit in our + local so we record it wrong. declare an + error. */ + dwarf_free_line_table_prefix(&prefix); + + _dwarf_error(dbg, error, + DW_DLE_LINE_NUM_OPERANDS_BAD); + return (DW_DLV_ERROR); + } + break; + } + } + + + } else if (type == LOP_EXTENDED) { + Dwarf_Unsigned utmp3 = 0; + Dwarf_Word instr_length = 0; + Dwarf_Small ext_opcode = 0; + + DECODE_LEB128_UWORD(line_ptr, utmp3); + instr_length = (Dwarf_Word) utmp3; + ext_opcode = *(Dwarf_Small *) line_ptr; + line_ptr++; + switch (ext_opcode) { + + case DW_LNE_end_sequence:{ + end_sequence = true; + + print_line_detail("DW_LNE_end_sequence extended", + opcode, address, file, line, + column, is_stmt, basic_block, + end_sequence, prologue_end, + epilogue_begin, isa); + + address = 0; + file = 1; + line = 1; + column = 0; + is_stmt = prefix.pf_default_is_stmt; + basic_block = false; + end_sequence = false; + prologue_end = false; + epilogue_begin = false; + + + break; + } + + case DW_LNE_set_address:{ + { + READ_UNALIGNED(dbg, address, Dwarf_Addr, + line_ptr, + die->di_cu_context->cc_address_size); + + line_ptr += die->di_cu_context->cc_address_size; + printf("DW_LNE_set_address address 0x%" DW_PR_DUx "\n", + (Dwarf_Unsigned) address); + } + + break; + } + + case DW_LNE_define_file:{ + Dwarf_Unsigned di = 0; + Dwarf_Unsigned tlm = 0; + Dwarf_Unsigned fl = 0; + + Dwarf_Small *fn = (Dwarf_Small *) line_ptr; + line_ptr = line_ptr + strlen((char *) line_ptr) + 1; + + di = _dwarf_decode_u_leb128(line_ptr, + &leb128_length); + line_ptr = line_ptr + leb128_length; + + tlm = _dwarf_decode_u_leb128(line_ptr, + &leb128_length); + line_ptr = line_ptr + leb128_length; + + fl = _dwarf_decode_u_leb128(line_ptr, + &leb128_length); + line_ptr = line_ptr + leb128_length; + + + printf("DW_LNE_define_file %s \n", fn); + printf(" dir index %d\n", (int) di); + { + time_t tt3 = (time_t) tlm; + + /* ctime supplies newline */ + printf(" last time 0x%x %s", + (unsigned) tlm, ctime(&tt3)); + } + printf(" file length %ld 0x%lx\n", + (long) fl, (unsigned long) fl); + + break; + } + + default:{ + /* This is an extended op code we do not know about, + other than we know now many bytes it is + (and the op code and the bytes of operand). */ + + Dwarf_Unsigned remaining_bytes = instr_length -1; + if(instr_length < 1 || remaining_bytes > DW_LNE_LEN_MAX) { + dwarf_free_line_table_prefix(&prefix); + _dwarf_error(dbg, error, + DW_DLE_LINE_EXT_OPCODE_BAD); + return (DW_DLV_ERROR); + } + printf("DW_LNE extended op 0x%x ",ext_opcode); + printf("Bytecount: " DW_PR_DUu , instr_length); + if(remaining_bytes > 0) { + printf(" linedata: 0x"); + while (remaining_bytes > 0) { + printf("%02x",(unsigned char)(*(line_ptr))); + line_ptr++; + remaining_bytes--; + } + } + printf("\n"); + } + break; + } + + } + } + + dwarf_free_line_table_prefix(&prefix); + return (DW_DLV_OK); +} + +/* + This is support for dwarfdump: making it possible + for clients wanting line detail info on stdout + to get that detail without including internal libdwarf + header information. + Caller passes in compilation unit DIE. + The _dwarf_ version is obsolete (though supported for + compatibility). + The dwarf_ version is preferred. + The functions are intentionally identical: having + _dwarf_print_lines call dwarf_print_lines might + better emphasize they are intentionally identical, but + that seemed slightly silly given how short the functions are. + Interface adds error_count (output value) February 2009. +*/ +int +dwarf_print_lines(Dwarf_Die die, Dwarf_Error * error,int *error_count) +{ + int only_line_header = 0; + int res = _dwarf_internal_printlines(die, error, + error_count, + only_line_header); + if (res != DW_DLV_OK) { + return res; + } + return res; +} +int +_dwarf_print_lines(Dwarf_Die die, Dwarf_Error * error) +{ + int only_line_header = 0; + int err_count = 0; + int res = _dwarf_internal_printlines(die, error, + &err_count, + only_line_header); + /* No way to get error count back in this interface */ + if (res != DW_DLV_OK) { + return res; + } + return res; +} + +/* The check is in case we are not printing full line data, + this gets some of the issues noted with .debug_line, + but not all. Call dwarf_print_lines() to get all issues. + Intended for apps like dwarfdump. +*/ +void +dwarf_check_lineheader(Dwarf_Die die, int *err_count_out) +{ + Dwarf_Error err; + int only_line_header = 1; + _dwarf_internal_printlines(die, &err,err_count_out, + only_line_header); + return; +} + diff --git a/usr/src/lib/libdwarf/common/dwarf_pubtypes.c b/usr/src/lib/libdwarf/common/dwarf_pubtypes.c new file mode 100644 index 0000000000..330c1c6adc --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_pubtypes.c @@ -0,0 +1,138 @@ +/* + + Copyright (C) 2000,2002,2004,2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + +/* Reads DWARF3 .debug_pubtypes section. */ + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include "dwarf_types.h" +#include "dwarf_global.h" + +int +dwarf_get_pubtypes(Dwarf_Debug dbg, + Dwarf_Type ** types, + Dwarf_Signed * ret_type_count, Dwarf_Error * error) +{ + int res = _dwarf_load_section(dbg, &dbg->de_debug_pubtypes,error); + if (res != DW_DLV_OK) { + return res; + } + + return _dwarf_internal_get_pubnames_like_data(dbg, + dbg->de_debug_pubtypes.dss_data, + dbg->de_debug_pubtypes.dss_size, + (Dwarf_Global **) types, /* Type punning for sections + with identical format. */ + ret_type_count, error, + DW_DLA_PUBTYPES_CONTEXT, + DW_DLA_GLOBAL, /* We don't have DW_DLA_PUBTYPES, + so use DW_DLA_GLOBAL. */ + DW_DLE_DEBUG_PUBTYPES_LENGTH_BAD, + DW_DLE_DEBUG_PUBTYPES_VERSION_ERROR); +} + +/* Deallocating fully requires deallocating the list + and all entries. But some internal data is + not exposed, so we need a function with internal knowledge. +*/ + +void +dwarf_pubtypes_dealloc(Dwarf_Debug dbg, Dwarf_Type * dwgl, + Dwarf_Signed count) +{ + _dwarf_internal_globals_dealloc(dbg, + (Dwarf_Global *) dwgl, + count, + DW_DLA_PUBTYPES_CONTEXT, + DW_DLA_GLOBAL, /* We don't have DW_DLA_PUBTYPES, + so use DW_DLA_GLOBAL. */ + DW_DLA_LIST); + return; +} + + + +int +dwarf_pubtypename(Dwarf_Type type_in, char **ret_name, + Dwarf_Error * error) +{ + Dwarf_Global type = (Dwarf_Global) type_in; + if (type == NULL) { + _dwarf_error(NULL, error, DW_DLE_TYPE_NULL); + return (DW_DLV_ERROR); + } + *ret_name = (char *) (type->gl_name); + return DW_DLV_OK; +} + + +int +dwarf_pubtype_type_die_offset(Dwarf_Type type_in, + Dwarf_Off * ret_offset, + Dwarf_Error * error) +{ + Dwarf_Global type = (Dwarf_Global) type_in; + + return dwarf_global_die_offset(type, ret_offset, error); +} + + +int +dwarf_pubtype_cu_offset(Dwarf_Type type_in, + Dwarf_Off * ret_offset, Dwarf_Error * error) +{ + Dwarf_Global type = (Dwarf_Global) type_in; + + return dwarf_global_cu_offset(type, ret_offset, error); + +} + + +int +dwarf_pubtype_name_offsets(Dwarf_Type type_in, + char **returned_name, + Dwarf_Off * die_offset, + Dwarf_Off * cu_die_offset, + Dwarf_Error * error) +{ + Dwarf_Global type = (Dwarf_Global) type_in; + + return dwarf_global_name_offsets(type, + returned_name, + die_offset, cu_die_offset, error); +} diff --git a/usr/src/lib/libdwarf/common/dwarf_query.c b/usr/src/lib/libdwarf/common/dwarf_query.c new file mode 100644 index 0000000000..3f21abd039 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_query.c @@ -0,0 +1,789 @@ +/* + + Copyright (C) 2000,2002,2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include "dwarf_die_deliv.h" + +/* This is normally reliable. +But not always. +If different compilation +units have different address sizes +this may not give the correct value in all contexts. +If the Elf offset size != address_size +(for example if address_size = 4 but recorded in elf64 object) +this may not give the correct value in all contexts. +*/ +int +dwarf_get_address_size(Dwarf_Debug dbg, + Dwarf_Half * ret_addr_size, Dwarf_Error * error) +{ + Dwarf_Half address_size = 0; + + if (dbg == 0) { + _dwarf_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + address_size = dbg->de_pointer_size; + *ret_addr_size = address_size; + return DW_DLV_OK; +} + +/* This will be correct in all contexts where the + CU context of a DIE is known. +*/ +int +dwarf_get_die_address_size(Dwarf_Die die, + Dwarf_Half * ret_addr_size, Dwarf_Error * error) +{ + Dwarf_Half address_size = 0; + CHECK_DIE(die, DW_DLV_ERROR); + address_size = die->di_cu_context->cc_address_size; + *ret_addr_size = address_size; + return DW_DLV_OK; +} + +int +dwarf_dieoffset(Dwarf_Die die, + Dwarf_Off * ret_offset, Dwarf_Error * error) +{ + CHECK_DIE(die, DW_DLV_ERROR); + + *ret_offset = (die->di_debug_info_ptr - + die->di_cu_context->cc_dbg->de_debug_info.dss_data); + return DW_DLV_OK; +} + + +/* + This function returns the offset of + the die relative to the start of its + compilation-unit rather than .debug_info. + Returns DW_DLV_ERROR on error. +*/ +int +dwarf_die_CU_offset(Dwarf_Die die, + Dwarf_Off * cu_off, Dwarf_Error * error) +{ + Dwarf_CU_Context cu_context = 0; + + CHECK_DIE(die, DW_DLV_ERROR); + cu_context = die->di_cu_context; + + *cu_off = + (die->di_debug_info_ptr - cu_context->cc_dbg->de_debug_info.dss_data - + cu_context->cc_debug_info_offset); + return DW_DLV_OK; +} + +/* + This function returns the global offset + (meaning the section offset) and length of + the CU that this die is a part of. + Used for correctness checking by dwarfdump. +*/ +int +dwarf_die_CU_offset_range(Dwarf_Die die, + Dwarf_Off * cu_off, + Dwarf_Off * cu_length, + Dwarf_Error * error) +{ + Dwarf_CU_Context cu_context = 0; + + CHECK_DIE(die, DW_DLV_ERROR); + cu_context = die->di_cu_context; + + *cu_off = cu_context->cc_debug_info_offset; + *cu_length = cu_context->cc_length + cu_context->cc_length_size + + cu_context->cc_extension_size; + return DW_DLV_OK; +} + + + +int +dwarf_tag(Dwarf_Die die, Dwarf_Half * tag, Dwarf_Error * error) +{ + CHECK_DIE(die, DW_DLV_ERROR); + *tag = (die->di_abbrev_list->ab_tag); + return DW_DLV_OK; +} + + +int +dwarf_attrlist(Dwarf_Die die, + Dwarf_Attribute ** attrbuf, + Dwarf_Signed * attrcnt, Dwarf_Error * error) +{ + Dwarf_Word attr_count = 0; + Dwarf_Word i = 0; + Dwarf_Half attr = 0; + Dwarf_Half attr_form = 0; + Dwarf_Byte_Ptr abbrev_ptr = 0; + Dwarf_Abbrev_List abbrev_list = 0; + Dwarf_Attribute new_attr = 0; + Dwarf_Attribute head_attr = NULL; + Dwarf_Attribute curr_attr = NULL; + Dwarf_Attribute *attr_ptr = 0; + Dwarf_Debug dbg = 0; + Dwarf_Byte_Ptr info_ptr = 0; + + CHECK_DIE(die, DW_DLV_ERROR); + dbg = die->di_cu_context->cc_dbg; + + abbrev_list = _dwarf_get_abbrev_for_code(die->di_cu_context, + die->di_abbrev_list-> + ab_code); + if (abbrev_list == NULL) { + _dwarf_error(dbg, error, DW_DLE_DIE_ABBREV_BAD); + return (DW_DLV_ERROR); + } + abbrev_ptr = abbrev_list->ab_abbrev_ptr; + + info_ptr = die->di_debug_info_ptr; + SKIP_LEB128_WORD(info_ptr); + + do { + Dwarf_Unsigned utmp2; + + DECODE_LEB128_UWORD(abbrev_ptr, utmp2); + attr = (Dwarf_Half) utmp2; + DECODE_LEB128_UWORD(abbrev_ptr, utmp2); + attr_form = (Dwarf_Half) utmp2; + + if (attr != 0) { + new_attr = + (Dwarf_Attribute) _dwarf_get_alloc(dbg, DW_DLA_ATTR, 1); + if (new_attr == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + new_attr->ar_attribute = attr; + new_attr->ar_attribute_form_direct = attr_form; + new_attr->ar_attribute_form = attr_form; + if (attr_form == DW_FORM_indirect) { + Dwarf_Unsigned utmp6; + + /* DECODE_LEB128_UWORD does info_ptr update */ + DECODE_LEB128_UWORD(info_ptr, utmp6); + attr_form = (Dwarf_Half) utmp6; + new_attr->ar_attribute_form = attr_form; + } + new_attr->ar_cu_context = die->di_cu_context; + new_attr->ar_debug_info_ptr = info_ptr; + + { + Dwarf_Unsigned sov = _dwarf_get_size_of_val(dbg, + attr_form, + die->di_cu_context->cc_address_size, + info_ptr, + die->di_cu_context->cc_length_size); + info_ptr += sov; + } + + + if (head_attr == NULL) + head_attr = curr_attr = new_attr; + else { + curr_attr->ar_next = new_attr; + curr_attr = new_attr; + } + attr_count++; + } + } while (attr != 0 || attr_form != 0); + + if (attr_count == 0) { + *attrbuf = NULL; + *attrcnt = 0; + return (DW_DLV_NO_ENTRY); + } + + attr_ptr = (Dwarf_Attribute *) + _dwarf_get_alloc(dbg, DW_DLA_LIST, attr_count); + if (attr_ptr == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + curr_attr = head_attr; + for (i = 0; i < attr_count; i++) { + *(attr_ptr + i) = curr_attr; + curr_attr = curr_attr->ar_next; + } + + *attrbuf = attr_ptr; + *attrcnt = attr_count; + return (DW_DLV_OK); +} + + +/* + This function takes a die, and an attr, and returns + a pointer to the start of the value of that attr in + the given die in the .debug_info section. The form + is returned in *attr_form. + + Returns NULL on error, or if attr is not found. + However, *attr_form is 0 on error, and positive + otherwise. +*/ +static Dwarf_Byte_Ptr +_dwarf_get_value_ptr(Dwarf_Die die, + Dwarf_Half attr, Dwarf_Half * attr_form) +{ + Dwarf_Byte_Ptr abbrev_ptr = 0; + Dwarf_Abbrev_List abbrev_list; + Dwarf_Half curr_attr = 0; + Dwarf_Half curr_attr_form = 0; + Dwarf_Byte_Ptr info_ptr = 0; + + abbrev_list = _dwarf_get_abbrev_for_code(die->di_cu_context, + die->di_abbrev_list->ab_code); + if (abbrev_list == NULL) { + *attr_form = 0; + return (NULL); + } + abbrev_ptr = abbrev_list->ab_abbrev_ptr; + + info_ptr = die->di_debug_info_ptr; + SKIP_LEB128_WORD(info_ptr); + + do { + Dwarf_Unsigned utmp3; + + DECODE_LEB128_UWORD(abbrev_ptr, utmp3); + curr_attr = (Dwarf_Half) utmp3; + DECODE_LEB128_UWORD(abbrev_ptr, utmp3); + curr_attr_form = (Dwarf_Half) utmp3; + if (curr_attr_form == DW_FORM_indirect) { + Dwarf_Unsigned utmp6; + + /* DECODE_LEB128_UWORD updates info_ptr */ + DECODE_LEB128_UWORD(info_ptr, utmp6); + curr_attr_form = (Dwarf_Half) utmp6; + } + + if (curr_attr == attr) { + *attr_form = curr_attr_form; + return (info_ptr); + } + + info_ptr += _dwarf_get_size_of_val(die->di_cu_context->cc_dbg, + curr_attr_form, + die->di_cu_context->cc_address_size, + info_ptr, + die->di_cu_context->cc_length_size); + } while (curr_attr != 0 || curr_attr_form != 0); + + *attr_form = 1; + return (NULL); +} + + +int +dwarf_diename(Dwarf_Die die, char **ret_name, Dwarf_Error * error) +{ + Dwarf_Half attr_form = 0; + Dwarf_Debug dbg = 0; + Dwarf_Byte_Ptr info_ptr = 0; + Dwarf_Unsigned string_offset = 0; + int res = DW_DLV_ERROR; + + CHECK_DIE(die, DW_DLV_ERROR); + + info_ptr = _dwarf_get_value_ptr(die, DW_AT_name, &attr_form); + if (info_ptr == NULL) { + if (attr_form == 0) { + _dwarf_error(die->di_cu_context->cc_dbg, error, + DW_DLE_DIE_BAD); + return (DW_DLV_ERROR); + } + return DW_DLV_NO_ENTRY; + } + + if (attr_form == DW_FORM_string) { + *ret_name = (char *) (info_ptr); + return DW_DLV_OK; + } + + dbg = die->di_cu_context->cc_dbg; + if (attr_form != DW_FORM_strp) { + _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD); + return (DW_DLV_ERROR); + } + + READ_UNALIGNED(dbg, string_offset, Dwarf_Unsigned, + info_ptr, die->di_cu_context->cc_length_size); + + if (string_offset >= dbg->de_debug_str.dss_size) { + _dwarf_error(dbg, error, DW_DLE_STRING_OFFSET_BAD); + return (DW_DLV_ERROR); + } + + res = _dwarf_load_section(dbg, &dbg->de_debug_str,error); + if (res != DW_DLV_OK) { + return res; + } + + *ret_name = (char *) (dbg->de_debug_str.dss_data + string_offset); + return DW_DLV_OK; +} + + +int +dwarf_hasattr(Dwarf_Die die, + Dwarf_Half attr, + Dwarf_Bool * return_bool, Dwarf_Error * error) +{ + Dwarf_Half attr_form = 0; + + CHECK_DIE(die, DW_DLV_ERROR); + + if (_dwarf_get_value_ptr(die, attr, &attr_form) == NULL) { + if (attr_form == 0) { + _dwarf_error(die->di_cu_context->cc_dbg, error, + DW_DLE_DIE_BAD); + return (DW_DLV_ERROR); + } + *return_bool = false; + return DW_DLV_OK; + } + + *return_bool = (true); + return DW_DLV_OK; +} + + +int +dwarf_attr(Dwarf_Die die, + Dwarf_Half attr, + Dwarf_Attribute * ret_attr, Dwarf_Error * error) +{ + Dwarf_Half attr_form = 0; + Dwarf_Attribute attrib = 0; + Dwarf_Byte_Ptr info_ptr = 0; + Dwarf_Debug dbg = 0; + + CHECK_DIE(die, DW_DLV_ERROR); + dbg = die->di_cu_context->cc_dbg; + + info_ptr = _dwarf_get_value_ptr(die, attr, &attr_form); + if (info_ptr == NULL) { + if (attr_form == 0) { + _dwarf_error(dbg, error, DW_DLE_DIE_BAD); + return (DW_DLV_ERROR); + } + return DW_DLV_NO_ENTRY; + } + + attrib = (Dwarf_Attribute) _dwarf_get_alloc(dbg, DW_DLA_ATTR, 1); + if (attrib == NULL) { + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (DW_DLV_ERROR); + } + + attrib->ar_attribute = attr; + attrib->ar_attribute_form = attr_form; + attrib->ar_attribute_form_direct = attr_form; + attrib->ar_cu_context = die->di_cu_context; + attrib->ar_debug_info_ptr = info_ptr; + *ret_attr = (attrib); + return DW_DLV_OK; +} + + +int +dwarf_lowpc(Dwarf_Die die, + Dwarf_Addr * return_addr, Dwarf_Error * error) +{ + Dwarf_Addr ret_addr = 0; + Dwarf_Byte_Ptr info_ptr = 0; + Dwarf_Half attr_form = 0; + Dwarf_Debug dbg = 0; + Dwarf_Half address_size = 0; + + CHECK_DIE(die, DW_DLV_ERROR); + + dbg = die->di_cu_context->cc_dbg; + address_size = die->di_cu_context->cc_address_size; + info_ptr = _dwarf_get_value_ptr(die, DW_AT_low_pc, &attr_form); + if ((info_ptr == NULL && attr_form == 0) || + (info_ptr != NULL && attr_form != DW_FORM_addr)) { + _dwarf_error(dbg, error, DW_DLE_DIE_BAD); + return (DW_DLV_ERROR); + } + if (info_ptr == NULL) { + return (DW_DLV_NO_ENTRY); + } + + + READ_UNALIGNED(dbg, ret_addr, Dwarf_Addr, + info_ptr, address_size); + + *return_addr = ret_addr; + return (DW_DLV_OK); +} + + +int +dwarf_highpc(Dwarf_Die die, + Dwarf_Addr * return_addr, Dwarf_Error * error) +{ + Dwarf_Addr ret_addr = 0; + Dwarf_Byte_Ptr info_ptr = 0; + Dwarf_Half attr_form = 0; + Dwarf_Debug dbg = 0; + Dwarf_Half address_size = 0; + + CHECK_DIE(die, DW_DLV_ERROR); + dbg = die->di_cu_context->cc_dbg; + address_size = die->di_cu_context->cc_address_size; + info_ptr = _dwarf_get_value_ptr(die, DW_AT_high_pc, &attr_form); + if ((info_ptr == NULL && attr_form == 0) || + (info_ptr != NULL && attr_form != DW_FORM_addr)) { + _dwarf_error(dbg, error, DW_DLE_DIE_BAD); + return (DW_DLV_ERROR); + } + if (info_ptr == NULL) { + return (DW_DLV_NO_ENTRY); + } + + READ_UNALIGNED(dbg, ret_addr, Dwarf_Addr, + info_ptr, address_size); + + *return_addr = ret_addr; + return (DW_DLV_OK); +} + + +/* + Takes a die, an attribute attr, and checks if attr + occurs in die. Attr is required to be an attribute + whose form is in the "constant" class. If attr occurs + in die, the value is returned. + Returns DW_DLV_OK, DW_DLV_ERROR, or DW_DLV_NO_ENTRY as + appropriate. Sets the value thru the pointer return_val. + This function is meant to do all the + processing for dwarf_bytesize, dwarf_bitsize, dwarf_bitoffset, + and dwarf_srclang. +*/ +static int +_dwarf_die_attr_unsigned_constant(Dwarf_Die die, + Dwarf_Half attr, + Dwarf_Unsigned * return_val, + Dwarf_Error * error) +{ + Dwarf_Byte_Ptr info_ptr; + Dwarf_Half attr_form; + Dwarf_Unsigned ret_value; + Dwarf_Debug dbg; + + CHECK_DIE(die, DW_DLV_ERROR); + + dbg = die->di_cu_context->cc_dbg; + info_ptr = _dwarf_get_value_ptr(die, attr, &attr_form); + if (info_ptr != NULL) { + switch (attr_form) { + + case DW_FORM_data1: + *return_val = (*(Dwarf_Small *) info_ptr); + return (DW_DLV_OK); + + case DW_FORM_data2: + READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, + info_ptr, sizeof(Dwarf_Shalf)); + *return_val = ret_value; + return (DW_DLV_OK); + + case DW_FORM_data4: + READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, + info_ptr, sizeof(Dwarf_sfixed)); + *return_val = ret_value; + return (DW_DLV_OK); + + case DW_FORM_data8: + READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, + info_ptr, sizeof(Dwarf_Unsigned)); + *return_val = ret_value; + return (DW_DLV_OK); + + case DW_FORM_udata: + *return_val = (_dwarf_decode_u_leb128(info_ptr, NULL)); + return (DW_DLV_OK); + + default: + _dwarf_error(dbg, error, DW_DLE_DIE_BAD); + return (DW_DLV_ERROR); + } + } + if (attr_form == 0) { + _dwarf_error(dbg, error, DW_DLE_DIE_BAD); + return (DW_DLV_ERROR); + } + return DW_DLV_NO_ENTRY; +} + + +int +dwarf_bytesize(Dwarf_Die die, + Dwarf_Unsigned * ret_size, Dwarf_Error * error) +{ + Dwarf_Unsigned luns = 0; + int res = _dwarf_die_attr_unsigned_constant(die, DW_AT_byte_size, + &luns, error); + *ret_size = luns; + return res; +} + + +int +dwarf_bitsize(Dwarf_Die die, + Dwarf_Unsigned * ret_size, Dwarf_Error * error) +{ + Dwarf_Unsigned luns = 0; + int res = _dwarf_die_attr_unsigned_constant(die, DW_AT_bit_size, + &luns, error); + *ret_size = luns; + return res; +} + + +int +dwarf_bitoffset(Dwarf_Die die, + Dwarf_Unsigned * ret_size, Dwarf_Error * error) +{ + Dwarf_Unsigned luns = 0; + int res = _dwarf_die_attr_unsigned_constant(die, + DW_AT_bit_offset, &luns, error); + *ret_size = luns; + return res; +} + + +/* Refer section 3.1, page 21 in Dwarf Definition. */ +int +dwarf_srclang(Dwarf_Die die, + Dwarf_Unsigned * ret_size, Dwarf_Error * error) +{ + Dwarf_Unsigned luns = 0; + int res = _dwarf_die_attr_unsigned_constant(die, DW_AT_language, + &luns, error); + *ret_size = luns; + return res; +} + + +/* Refer section 5.4, page 37 in Dwarf Definition. */ +int +dwarf_arrayorder(Dwarf_Die die, + Dwarf_Unsigned * ret_size, Dwarf_Error * error) +{ + Dwarf_Unsigned luns = 0; + int res = _dwarf_die_attr_unsigned_constant(die, DW_AT_ordering, + &luns, error); + *ret_size = luns; + return res; +} + +/* + Return DW_DLV_OK if ok + DW_DLV_ERROR if failure. + + If the die and the attr are not related the result is + meaningless. +*/ +int +dwarf_attr_offset(Dwarf_Die die, Dwarf_Attribute attr, + Dwarf_Off * offset /* return offset thru this ptr */, + Dwarf_Error * error) +{ + Dwarf_Off attroff = 0; + + CHECK_DIE(die, DW_DLV_ERROR); + + attroff = (attr->ar_debug_info_ptr - + die->di_cu_context->cc_dbg->de_debug_info.dss_data); + *offset = attroff; + return DW_DLV_OK; +} + +int +dwarf_die_abbrev_code(Dwarf_Die die) +{ + return die->di_abbrev_code; +} + +/* Helper function for finding form class. */ +static enum Dwarf_Form_Class +dw_get_special_offset(Dwarf_Half attrnum) +{ + switch(attrnum) { + case DW_AT_stmt_list: + return DW_FORM_CLASS_LINEPTR; + case DW_AT_macro_info: + return DW_FORM_CLASS_MACPTR; + case DW_AT_ranges: + return DW_FORM_CLASS_RANGELISTPTR; + case DW_AT_location: + case DW_AT_string_length: + case DW_AT_return_addr: + case DW_AT_data_member_location: + case DW_AT_frame_base: + case DW_AT_segment: + case DW_AT_static_link: + case DW_AT_use_location: + case DW_AT_vtable_elem_location: + return DW_FORM_CLASS_LOCLISTPTR; + case DW_AT_sibling: + case DW_AT_byte_size : + case DW_AT_bit_offset : + case DW_AT_bit_size : + case DW_AT_discr : + case DW_AT_import : + case DW_AT_common_reference: + case DW_AT_containing_type: + case DW_AT_default_value: + case DW_AT_lower_bound: + case DW_AT_bit_stride: + case DW_AT_upper_bound: + case DW_AT_abstract_origin: + case DW_AT_base_types: + case DW_AT_count: + case DW_AT_friend: + case DW_AT_namelist_item: + case DW_AT_priority: + case DW_AT_specification: + case DW_AT_type: + case DW_AT_allocated: + case DW_AT_associated: + case DW_AT_byte_stride: + case DW_AT_extension: + case DW_AT_trampoline: + case DW_AT_small: + case DW_AT_object_pointer: + case DW_AT_signature: + return DW_FORM_CLASS_REFERENCE; + case DW_AT_MIPS_fde: /* SGI/IRIX extension */ + return DW_FORM_CLASS_FRAMEPTR; + } + return DW_FORM_CLASS_UNKNOWN; +} + +/* It takes 4 pieces of data (including the FORM) + to accurately determine the form 'class' as documented + in the DWARF spec. This is per DWARF4, but will work + for DWARF2 or 3 as well. */ +enum Dwarf_Form_Class dwarf_get_form_class( + Dwarf_Half dwversion, + Dwarf_Half attrnum, + Dwarf_Half offset_size, + Dwarf_Half form) +{ + switch(form) { + case DW_FORM_addr: return DW_FORM_CLASS_ADDRESS; + + case DW_FORM_data2: return DW_FORM_CLASS_CONSTANT; + + case DW_FORM_data4: + if(dwversion <= 3 && offset_size == 4) { + enum Dwarf_Form_Class class = dw_get_special_offset(attrnum); + if(class != DW_FORM_CLASS_UNKNOWN) { + return class; + } + } + return DW_FORM_CLASS_CONSTANT; + case DW_FORM_data8: + if(dwversion <= 3 && offset_size == 8) { + enum Dwarf_Form_Class class = dw_get_special_offset(attrnum); + if(class != DW_FORM_CLASS_UNKNOWN) { + return class; + } + } + return DW_FORM_CLASS_CONSTANT; + + case DW_FORM_sec_offset: + { + enum Dwarf_Form_Class class = dw_get_special_offset(attrnum); + if(class != DW_FORM_CLASS_UNKNOWN) { + return class; + } + } + /* We do not know what this is. */ + break; + + case DW_FORM_string: return DW_FORM_CLASS_STRING; + case DW_FORM_strp: return DW_FORM_CLASS_STRING; + + case DW_FORM_block: return DW_FORM_CLASS_BLOCK; + case DW_FORM_block1: return DW_FORM_CLASS_BLOCK; + case DW_FORM_block2: return DW_FORM_CLASS_BLOCK; + case DW_FORM_block4: return DW_FORM_CLASS_BLOCK; + + case DW_FORM_data1: return DW_FORM_CLASS_CONSTANT; + case DW_FORM_sdata: return DW_FORM_CLASS_CONSTANT; + case DW_FORM_udata: return DW_FORM_CLASS_CONSTANT; + + case DW_FORM_ref_addr: return DW_FORM_CLASS_REFERENCE; + case DW_FORM_ref1: return DW_FORM_CLASS_REFERENCE; + case DW_FORM_ref2: return DW_FORM_CLASS_REFERENCE; + case DW_FORM_ref4: return DW_FORM_CLASS_REFERENCE; + case DW_FORM_ref8: return DW_FORM_CLASS_REFERENCE; + case DW_FORM_ref_udata: return DW_FORM_CLASS_REFERENCE; + case DW_FORM_ref_sig8: return DW_FORM_CLASS_REFERENCE; + + case DW_FORM_exprloc: return DW_FORM_CLASS_EXPRLOC; + + case DW_FORM_flag: return DW_FORM_CLASS_FLAG; + case DW_FORM_flag_present: return DW_FORM_CLASS_FLAG; + + + case DW_FORM_indirect: + default: + break; + }; + return DW_FORM_CLASS_UNKNOWN; +} + diff --git a/usr/src/lib/libdwarf/common/dwarf_ranges.c b/usr/src/lib/libdwarf/common/dwarf_ranges.c new file mode 100644 index 0000000000..ae6d5cf9b5 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_ranges.c @@ -0,0 +1,171 @@ +/* + + Copyright (C) 2008-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + + +#include "config.h" +#include +#include "dwarf_incl.h" + +struct ranges_entry { + struct ranges_entry *next; + Dwarf_Ranges cur; +}; + + +#define MAX_ADDR ((address_size == 8)?0xffffffffffffffffULL:0xffffffff) +int dwarf_get_ranges_a(Dwarf_Debug dbg, + Dwarf_Off rangesoffset, + Dwarf_Die die, + Dwarf_Ranges ** rangesbuf, + Dwarf_Signed * listlen, + Dwarf_Unsigned * bytecount, + Dwarf_Error * error) +{ + Dwarf_Small *rangeptr = 0; + Dwarf_Small *beginrangeptr = 0; + Dwarf_Small *section_end = 0; + unsigned entry_count = 0; + struct ranges_entry *base = 0; + struct ranges_entry *last = 0; + struct ranges_entry *curre = 0; + Dwarf_Ranges * ranges_data_out = 0; + unsigned copyindex = 0; + Dwarf_Half address_size = 0; + int res = DW_DLV_ERROR; + + res = _dwarf_load_section(dbg, &dbg->de_debug_ranges,error); + if (res != DW_DLV_OK) { + return res; + } + if(rangesoffset >= dbg->de_debug_ranges.dss_size) { + _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OFFSET_BAD); + return (DW_DLV_ERROR); + + } + address_size = _dwarf_get_address_size(dbg, die); + section_end = dbg->de_debug_ranges.dss_data + + dbg->de_debug_ranges.dss_size; + rangeptr = dbg->de_debug_ranges.dss_data + rangesoffset; + beginrangeptr = rangeptr; + + for(;;) { + struct ranges_entry * re = calloc(sizeof(struct ranges_entry),1); + if(!re) { + _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OUT_OF_MEM); + return (DW_DLV_ERROR); + } + if(rangeptr >= section_end) { + return (DW_DLV_NO_ENTRY); + } + if((rangeptr + (2*address_size)) > section_end) { + _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OFFSET_BAD); + return (DW_DLV_ERROR); + } + entry_count++; + READ_UNALIGNED(dbg,re->cur.dwr_addr1, + Dwarf_Addr, rangeptr, + address_size); + rangeptr += address_size; + READ_UNALIGNED(dbg,re->cur.dwr_addr2 , + Dwarf_Addr, rangeptr, + address_size); + rangeptr += address_size; + if(!base) { + base = re; + last = re; + } else { + last->next = re; + last = re; + } + if(re->cur.dwr_addr1 == 0 && re->cur.dwr_addr2 == 0) { + re->cur.dwr_type = DW_RANGES_END; + break; + } else if ( re->cur.dwr_addr1 == MAX_ADDR) { + re->cur.dwr_type = DW_RANGES_ADDRESS_SELECTION; + } else { + re->cur.dwr_type = DW_RANGES_ENTRY; + } + } + + ranges_data_out = (Dwarf_Ranges *) + _dwarf_get_alloc(dbg,DW_DLA_RANGES,entry_count); + if(!ranges_data_out) { + _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OUT_OF_MEM); + return (DW_DLV_ERROR); + } + curre = base; + *rangesbuf = ranges_data_out; + *listlen = entry_count; + for( copyindex = 0; curre && (copyindex < entry_count); + ++copyindex,++ranges_data_out) { + + struct ranges_entry *r = curre; + *ranges_data_out = curre->cur; + curre = curre->next; + free(r); + } + /* Callers will often not care about the bytes used. */ + if(bytecount) { + *bytecount = rangeptr - beginrangeptr; + } + return DW_DLV_OK; +} +int dwarf_get_ranges(Dwarf_Debug dbg, + Dwarf_Off rangesoffset, + Dwarf_Ranges ** rangesbuf, + Dwarf_Signed * listlen, + Dwarf_Unsigned * bytecount, + Dwarf_Error * error) +{ + Dwarf_Die die = 0; + int res = dwarf_get_ranges_a(dbg,rangesoffset,die, + rangesbuf,listlen,bytecount,error); + return res; +} + +void +dwarf_ranges_dealloc(Dwarf_Debug dbg, Dwarf_Ranges * rangesbuf, + Dwarf_Signed rangecount) +{ + dwarf_dealloc(dbg,rangesbuf, DW_DLA_RANGES); + +} + diff --git a/usr/src/lib/libdwarf/common/dwarf_sort_line.c b/usr/src/lib/libdwarf/common/dwarf_sort_line.c new file mode 100644 index 0000000000..3576614129 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_sort_line.c @@ -0,0 +1,733 @@ +/* + Copyright (C) 2000,2002,2004,2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + +/* This file was designed for SGI IRIX compiler use. + The static linker can rearrange the order of functions + in the layout in memory + and provided each has the right form + this will (when called by the SGI IRIX + static linker) rearrange the table so the line table + is arranged in the same order as the memory layout. */ + + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include +#include "dwarf_line.h" +#ifdef HAVE_ALLOCA_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#define MINIMUM_POSSIBLE_PROLOG_LEN 10 /* 10 is based on */ + /* the definition of the DWARF2/3 line table prolog. The value + here should be >8 (accounting for a 64 bit read) and <= the + length of a legal DWARF2/3 line prolog, which is at least 10 + bytes long (but can be longer). What this constant helps + avoid is reading past the end of a malloc'd buffer in + _dwarf_update_line_sec(). */ + +static int + _dwarf_update_line_sec(Dwarf_Small * line_ptr, + unsigned long remaining_bytes, + int *any_change, + int length_size, + int *err_code, Dwarf_Small ** new_line_ptr); + +/* Used to construct + a linked list of so we can sort and reorder the line info. +*/ +struct a_line_area { + Dwarf_Addr ala_address; /* from DW_LNE_set_address */ + Dwarf_Unsigned ala_offset; /* byte offset in buffer */ + Dwarf_Unsigned ala_length; /* byte length in buffer */ + long ala_entry_num; /* to guarantee stable sort */ + struct a_line_area *ala_next; +}; + + +/* + Written to support the SGI IRIX static linker. + It helps SGI IRIX ld + rearrange lines in .debug_line in a .o created with a text + section per function. The SGI IRIX linker option is: + -OPT:procedure_reorder=ON + where ld-cord (cord(1)ing by ld, + not by cord(1)) may have changed the function order. + + Returns + DW_DLV_OK if nothing went wrong. + DW_DLV_ERROR if could not do anything due to + error. the original buffer is unchanged. + + is_64_bit must be passed in by caller and tells + if this is a 32 or 64bit pointer object section + being processed. + + err_code must be a non-null pointer to integer. + If DW_DLV_ERROR is returned that integer is set + to a dwarf error code so the caller may + print it for diagnostic purposes. + + *any_change is set here + set 0 if no sorting (movement) done. + set 1 if some sorting (movement) done. + on all returns. On error return sets to 0. + + The _dwarf name form is now obsolete, + the dwarf_ name for is preferred. + Both names supported. + +*/ +int +_dwarf_ld_sort_lines(void *orig_buffer, + unsigned long buffer_len, + int is_64_bit, int *any_change, int *err_code) +{ + return dwarf_ld_sort_lines(orig_buffer,buffer_len, + is_64_bit,any_change,err_code); +} +int +dwarf_ld_sort_lines(void *orig_buffer, + unsigned long buffer_len, + int is_64_bit, int *any_change, int *err_code) +{ + + int length_size = 4; + Dwarf_Small *orig_line_ptr; /* our local copy of the user's input + buffer */ + Dwarf_Small *line_ptr; /* starts at orig_line_ptr, gets + incremented thru to end of our copy + of the input buffer */ + Dwarf_Small *new_line_ptr; /* output of _dwarf_update_line_sec(), + used to update line_ptr as we pass + thru compilation units in a .o + .debug_line */ + + unsigned long remaining_bytes = buffer_len; /* total length of + original area left + to be processed. + Changes as we pass + thru compilation + units in a .o + .debug_line */ + + int sec_res; + int lany_change = 0; + int did_change = 0; + + if (is_64_bit) + length_size = 8; + + *any_change = 0; + line_ptr = malloc(buffer_len); + if (!line_ptr) { + *err_code = DW_DLE_ALLOC_FAIL; + return DW_DLV_ERROR; + } + orig_line_ptr = line_ptr; + memcpy(line_ptr, orig_buffer, buffer_len); + + + /* + We must iterate thru each of a set of prologues and line data. + We process each set in turn. If all pass, we update the + passed-in buffer. */ + sec_res = DW_DLV_OK; + + for (sec_res = _dwarf_update_line_sec(line_ptr, + remaining_bytes, + &lany_change, + length_size, + err_code, + &new_line_ptr); + (sec_res == DW_DLV_OK) && (remaining_bytes > 0); + sec_res = _dwarf_update_line_sec(line_ptr, + remaining_bytes, + &lany_change, + length_size, + err_code, &new_line_ptr)) { + long bytes_used = new_line_ptr - line_ptr; + + line_ptr = new_line_ptr; + remaining_bytes -= bytes_used; + if (lany_change) { + did_change = 1; + } + if (remaining_bytes > 0) { + continue; + } + break; + } + if (sec_res == DW_DLV_ERROR) { + free(orig_line_ptr); + return sec_res; + } + + + /* all passed */ + if (did_change) { + /* So update the passed in buffer orig_buffer is caller's input + area. orig_line_ptr is our modified copy of input area. */ + memcpy(orig_buffer, orig_line_ptr, buffer_len); + *any_change = 1; + } + free(orig_line_ptr); + + return sec_res; +} + + +/* By setting ala_entry_num we guarantee a stable sort, + no duplicates + Sorting in address order. +*/ +static int +cmpr(const void *lin, const void *rin) +{ + const struct a_line_area *l = lin; + const struct a_line_area *r = rin; + + if (l->ala_address < r->ala_address) { + return -1; + } + if (l->ala_address > r->ala_address) { + return 1; + } + if (l->ala_entry_num < r->ala_entry_num) { + return -1; + } + if (l->ala_entry_num > r->ala_entry_num) { + return 1; + } + return 0; /* should never happen. */ +} + +/* The list of line area records is no longer needed. + Free the data allocated. */ +static void +free_area_data(struct a_line_area *arp) +{ + while(arp) { + struct a_line_area *next = arp->ala_next; + free(arp); + arp = next; + } +} + +/* + On entry: + line_ptr must point to first + byte of a line group for one (original) .o + + remaining_bytes is the size of the area pointed to + by line_ptr: may be larger than the + current original compilation unit . + + length size is 4 for 32bit pointers, 8 for 64bit pointers + in the data pointed to. + + + On return: + return DW_DLV_OK if all ok. (ignore + *err_code in this case) + + return DW_DLV_ERROR and set *err_code if an error. + + If some line data was moved around, set *any_change to 1. + If error or no movement, set *any_change to 0; + + Set *new_line_ptr to one-byte-past the end of the + current original compilation unit (not necessary + if returning DW_DLV_ERROR, but not harmful). + + + This copies the entire array to a malloc area, then + mallocs pieces of it (another malloc) for sorting a CU entries + and copying back. Then at end the whole new thing copied in. + The result is that on error, the input is not touched. + + An alternative would be to just update a piece at a time + and on error stop updating but leave what was done, done. + This alternative would save some temporary malloc space. + + +*/ +static int +_dwarf_update_line_sec(Dwarf_Small * line_ptr, + unsigned long remaining_bytes, + int *any_change, + int length_size, + int *err_code, Dwarf_Small ** new_line_ptr) +{ + + + /* + This points to the last byte of the .debug_line portion for the + current cu. */ + Dwarf_Small *line_ptr_end = 0; + + /* + This points to the end of the statement program prologue for the + current cu, and serves to check that the prologue was correctly + decoded. */ + + Dwarf_Small *orig_line_ptr = 0; + + /* These are the fields of the statement program header. */ + struct Dwarf_Debug_s dbg_data; + Dwarf_Debug dbg = &dbg_data; + + /* These are the state machine state variables. */ + Dwarf_Addr address = 0; + Dwarf_Word line = 1; + Dwarf_Bool is_stmt = false; + + /* Dwarf_Bool prologue_end; Dwarf_Bool epilogue_begin; */ + Dwarf_Small isa = 0; + + + struct a_line_area *area_base = 0; + struct a_line_area *area_current = 0; + long area_count = 0; + + Dwarf_Addr last_address = 0; + int need_to_sort = 0; + + /* + This is the current opcode read from the statement program. */ + Dwarf_Small opcode = 0; + + + /* + These variables are used to decode leb128 numbers. Leb128_num + holds the decoded number, and leb128_length is its length in + bytes. */ + Dwarf_Word leb128_num = 0; + Dwarf_Sword advance_line = 0; + + /* + This is the operand of the latest fixed_advance_pc extended + opcode. */ + Dwarf_Half fixed_advance_pc = 0; + + /* This is the length of an extended opcode instr. */ + Dwarf_Word instr_length = 0; + Dwarf_Small ext_opcode = 0; + struct Line_Table_Prefix_s prefix; + + + + memset(dbg, 0, sizeof(struct Dwarf_Debug_s)); + dbg->de_copy_word = memcpy; + /* + Following is a straightforward decoding of the statement program + prologue information. */ + *any_change = 0; + + + orig_line_ptr = line_ptr; + if (remaining_bytes < MINIMUM_POSSIBLE_PROLOG_LEN) { + /* We are at the end. Remaining should be zero bytes, padding. + This is really just 'end of CU buffer' not an error. The is + no 'entry' left so report there is none. We don't want to + READ_UNALIGNED the total_length below and then belatedly + discover that we read off the end already. */ + return (DW_DLV_NO_ENTRY); + } + + dwarf_init_line_table_prefix(&prefix); + { + Dwarf_Small *line_ptr_out = 0; + Dwarf_Error error; + int dres = dwarf_read_line_table_prefix(dbg, + line_ptr, + remaining_bytes, + &line_ptr_out, + &prefix, + NULL, NULL,&error, + NULL); + + if (dres == DW_DLV_ERROR) { + dwarf_free_line_table_prefix(&prefix); + *err_code = dwarf_errno(error); + dwarf_dealloc(dbg, error, DW_DLA_ERROR); + free_area_data(area_base); + return dres; + } + if (dres == DW_DLV_NO_ENTRY) { + dwarf_free_line_table_prefix(&prefix); + return dres; + } + line_ptr_end = prefix.pf_line_ptr_end; + + line_ptr = line_ptr_out; + } + + + /* Initialize the state machine. */ + /* file = 1; */ + /* column = 0; */ + is_stmt = prefix.pf_default_is_stmt; + /* basic_block = false; */ + /* end_sequence = false; */ + /* prologue_end = false; */ + /* epilogue_begin = false; */ + isa = 0; + + + /* Start of statement program. */ + while (line_ptr < line_ptr_end) { + int type; + + Dwarf_Small *stmt_prog_entry_start = line_ptr; + + opcode = *(Dwarf_Small *) line_ptr; + line_ptr++; + /* 'type' is the output */ + WHAT_IS_OPCODE(type, opcode, prefix.pf_opcode_base, + prefix.pf_opcode_length_table, line_ptr, + prefix.pf_std_op_count); + + if (type == LOP_DISCARD) { + int oc; + int opcnt = prefix.pf_opcode_length_table[opcode]; + + for (oc = 0; oc < opcnt; oc++) { + /* + ** Read and discard operands we don't + ** understand. + ** arbitrary choice of unsigned read. + ** signed read would work as well. + */ + Dwarf_Unsigned utmp2; + + DECODE_LEB128_UWORD(line_ptr, utmp2); + } + + } else if (type == LOP_SPECIAL) { + opcode = opcode - prefix.pf_opcode_base; + address = address + prefix.pf_minimum_instruction_length * + (opcode / prefix.pf_line_range); + line = + line + prefix.pf_line_base + + opcode % prefix.pf_line_range; + + /* basic_block = false; */ + + + } else if (type == LOP_STANDARD) { + + + switch (opcode) { + + + case DW_LNS_copy:{ + + /* basic_block = false; */ + break; + } + + case DW_LNS_advance_pc:{ + Dwarf_Unsigned utmp2; + + + DECODE_LEB128_UWORD(line_ptr, utmp2); + leb128_num = (Dwarf_Word) utmp2; + address = + address + + prefix.pf_minimum_instruction_length * + leb128_num; + break; + } + + case DW_LNS_advance_line:{ + Dwarf_Signed stmp; + + + DECODE_LEB128_SWORD(line_ptr, stmp); + advance_line = (Dwarf_Sword) stmp; + line = line + advance_line; + break; + } + + case DW_LNS_set_file:{ + Dwarf_Unsigned utmp2; + + + DECODE_LEB128_UWORD(line_ptr, utmp2); + /* file = (Dwarf_Word)utmp2; */ + break; + } + + case DW_LNS_set_column:{ + Dwarf_Unsigned utmp2; + + + DECODE_LEB128_UWORD(line_ptr, utmp2); + /* column = (Dwarf_Word)utmp2; */ + break; + } + + case DW_LNS_negate_stmt:{ + + is_stmt = !is_stmt; + break; + } + + case DW_LNS_set_basic_block:{ + + /* basic_block = true; */ + break; + } + + case DW_LNS_const_add_pc:{ + opcode = MAX_LINE_OP_CODE - prefix.pf_opcode_base; + address = + address + + prefix.pf_minimum_instruction_length * (opcode / + prefix. + pf_line_range); + + break; + } + + case DW_LNS_fixed_advance_pc:{ + + READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half, + line_ptr, sizeof(Dwarf_Half)); + line_ptr += sizeof(Dwarf_Half); + address = address + fixed_advance_pc; + break; + } + /* New in DWARF3 */ + case DW_LNS_set_prologue_end:{ + + /* prologue_end = true; */ + break; + + + } + /* New in DWARF3 */ + case DW_LNS_set_epilogue_begin:{ + /* epilogue_begin = true; */ + break; + } + + /* New in DWARF3 */ + case DW_LNS_set_isa:{ + Dwarf_Unsigned utmp2; + + DECODE_LEB128_UWORD(line_ptr, utmp2); + isa = utmp2; + if (isa != utmp2) { + /* The value of the isa did not fit in our + local so we record it wrong. declare an + error. */ + dwarf_free_line_table_prefix(&prefix); + *err_code = DW_DLE_LINE_NUM_OPERANDS_BAD; + free_area_data(area_base); + return (DW_DLV_ERROR); + } + break; + } + + } + } else if (type == LOP_EXTENDED) { + + Dwarf_Unsigned utmp3; + + DECODE_LEB128_UWORD(line_ptr, utmp3); + instr_length = (Dwarf_Word) utmp3; + ext_opcode = *(Dwarf_Small *) line_ptr; + line_ptr++; + switch (ext_opcode) { + + case DW_LNE_end_sequence:{ + /* end_sequence = true; */ + + address = 0; + /* file = 1; */ + line = 1; + /* column = 0; */ + is_stmt = prefix.pf_default_is_stmt; + /* basic_block = false; */ + /* end_sequence = false; */ + /* prologue_end = false; */ + /* epilogue_begin = false; */ + break; + } + + case DW_LNE_set_address:{ + { + struct a_line_area *area; + + READ_UNALIGNED(dbg, address, Dwarf_Addr, + line_ptr, length_size); + /* Here we need to remember the offset into the + buffer and check to see if address went + down. */ + if (address < last_address) { + need_to_sort = 1; + } + last_address = address; + + area = malloc(sizeof(struct a_line_area)); + area->ala_address = address; + area->ala_offset = stmt_prog_entry_start - + orig_line_ptr; + area->ala_entry_num = area_count; + area->ala_next = 0; + area->ala_length = 0; + if (area_current) { + area_current->ala_next = area; + area_current->ala_length = + area->ala_offset - + area_current->ala_offset; + } + ++area_count; + area_current = area; + if (area_base == 0) { + area_base = area; + } + + line_ptr += length_size; + } + break; + } + + case DW_LNE_define_file:{ + break; + } + + default:{ + Dwarf_Unsigned remaining_bytes = instr_length -1; + line_ptr += remaining_bytes; + break; + } + } + + } + } + + + *new_line_ptr = line_ptr; + if (!need_to_sort) { + dwarf_free_line_table_prefix(&prefix); + free_area_data(area_base); + return (DW_DLV_OK); + } + + /* So now we have something to sort. First, finish off the last + area record: */ + area_current->ala_length = (line_ptr - orig_line_ptr) + -area_current->ala_offset; + + /* Build and sort a simple array of sections. Forcing a stable sort + by comparing on sequence number. We will use the sorted list to + move sections of this part of the line table. Each 'section' + starting with a DW_LNE_set_address opcode, on the assumption + that such only get out of order where there was an ld-cord + function rearrangement and that it is meaningful to restart the + line info there. */ + { + struct a_line_area *ala_array; + struct a_line_area *local; + long start_len; + Dwarf_Small *new_area; + long i; + + ala_array = malloc(area_count * sizeof(struct a_line_area)); + if (!ala_array) { + dwarf_free_line_table_prefix(&prefix); + *err_code = DW_DLE_ALLOC_FAIL; + free_area_data(area_base); + return DW_DLV_ERROR; + } + + for (local = area_base, i = 0; local; + local = local->ala_next, ++i) { + + ala_array[i] = *local; + } + free_area_data(area_base); + /* Zero the stale pointers so we don't use them accidentally. */ + area_base = 0; + area_current = 0; + + qsort(ala_array, area_count, sizeof(struct a_line_area), cmpr); + + /* Now we must rearrange the pieces of the line table. */ + + start_len = + (prefix.pf_line_prologue_start + + prefix.pf_prologue_length) - orig_line_ptr; + new_area = malloc(remaining_bytes); + if (!new_area) { + free(ala_array); + *err_code = DW_DLE_ALLOC_FAIL; + dwarf_free_line_table_prefix(&prefix); + return DW_DLV_ERROR; + } + memcpy(new_area, orig_line_ptr, start_len); + line_ptr = new_area + start_len; + for (i = 0; i < area_count; ++i) { + memcpy(line_ptr, orig_line_ptr + + ala_array[i].ala_offset, ala_array[i].ala_length); + line_ptr += ala_array[i].ala_length; + } + + memcpy(orig_line_ptr, new_area, remaining_bytes); + + free(new_area); + free(ala_array); + ala_array = 0; + new_area = 0; + } + + *any_change = 1; + dwarf_free_line_table_prefix(&prefix); + return (DW_DLV_OK); +} diff --git a/usr/src/lib/libdwarf/common/dwarf_string.c b/usr/src/lib/libdwarf/common/dwarf_string.c new file mode 100644 index 0000000000..fafa5a097c --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_string.c @@ -0,0 +1,79 @@ +/* + + Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "dwarf_incl.h" + +int +dwarf_get_str(Dwarf_Debug dbg, + Dwarf_Off offset, + char **string, + Dwarf_Signed * returned_str_len, Dwarf_Error * error) +{ + int res = DW_DLV_ERROR; + + if (dbg == NULL) { + _dwarf_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + + if (offset == dbg->de_debug_str.dss_size) { + /* Normal (if we've iterated thru the set of strings using + dwarf_get_str and are at the end). */ + return DW_DLV_NO_ENTRY; + } + if (offset > dbg->de_debug_str.dss_size) { + _dwarf_error(dbg, error, DW_DLE_DEBUG_STR_OFFSET_BAD); + return (DW_DLV_ERROR); + } + + if (string == NULL) { + _dwarf_error(dbg, error, DW_DLE_STRING_PTR_NULL); + return (DW_DLV_ERROR); + } + + res = _dwarf_load_section(dbg, &dbg->de_debug_str,error); + if (res != DW_DLV_OK) { + return res; + } + + *string = (char *) dbg->de_debug_str.dss_data + offset; + + *returned_str_len = (strlen(*string)); + return DW_DLV_OK; +} diff --git a/usr/src/lib/libdwarf/common/dwarf_stubs.c b/usr/src/lib/libdwarf/common/dwarf_stubs.c new file mode 100644 index 0000000000..f2c1f7fd45 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_stubs.c @@ -0,0 +1,50 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "dwarf_incl.h" +#include + + + + /*ARGSUSED*/ int +dwarf_nextglob(Dwarf_Debug dbg, + Dwarf_Global glob, + Dwarf_Global * returned_nextglob, Dwarf_Error * error) +{ + return (DW_DLV_NO_ENTRY); +} diff --git a/usr/src/lib/libdwarf/common/dwarf_types.c b/usr/src/lib/libdwarf/common/dwarf_types.c new file mode 100644 index 0000000000..d547805289 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_types.c @@ -0,0 +1,129 @@ +/* + Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include "dwarf_types.h" +#include "dwarf_global.h" + +int +dwarf_get_types(Dwarf_Debug dbg, + Dwarf_Type ** types, + Dwarf_Signed * ret_type_count, Dwarf_Error * error) +{ + int res = _dwarf_load_section(dbg, &dbg->de_debug_typenames,error); + if (res != DW_DLV_OK) { + return res; + } + + return _dwarf_internal_get_pubnames_like_data(dbg, + dbg->de_debug_typenames.dss_data, + dbg->de_debug_typenames.dss_size, + (Dwarf_Global **) types, /* type punning, Dwarf_Type is + never a completed type */ + ret_type_count, + error, + DW_DLA_TYPENAME_CONTEXT, + DW_DLA_TYPENAME, + DW_DLE_DEBUG_TYPENAMES_LENGTH_BAD, + DW_DLE_DEBUG_TYPENAMES_VERSION_ERROR); +} + +/* Deallocating fully requires deallocating the list + and all entries. But some internal data is + not exposed, so we need a function with internal knowledge. +*/ + +void +dwarf_types_dealloc(Dwarf_Debug dbg, Dwarf_Type * dwgl, + Dwarf_Signed count) +{ + _dwarf_internal_globals_dealloc(dbg, (Dwarf_Global *) dwgl, + count, + DW_DLA_TYPENAME_CONTEXT, + DW_DLA_TYPENAME, DW_DLA_LIST); + return; +} + + +int +dwarf_typename(Dwarf_Type type_in, char **ret_name, Dwarf_Error * error) +{ + Dwarf_Global type = (Dwarf_Global) type_in; + + if (type == NULL) { + _dwarf_error(NULL, error, DW_DLE_TYPE_NULL); + return (DW_DLV_ERROR); + } + + *ret_name = (char *) (type->gl_name); + return DW_DLV_OK; +} + + +int +dwarf_type_die_offset(Dwarf_Type type_in, + Dwarf_Off * ret_offset, Dwarf_Error * error) +{ + Dwarf_Global type = (Dwarf_Global) type_in; + + return dwarf_global_die_offset(type, ret_offset, error); +} + + +int +dwarf_type_cu_offset(Dwarf_Type type_in, + Dwarf_Off * ret_offset, Dwarf_Error * error) +{ + Dwarf_Global type = (Dwarf_Global) type_in; + + return dwarf_global_cu_offset(type, ret_offset, error); +} + + +int +dwarf_type_name_offsets(Dwarf_Type type_in, + char **returned_name, + Dwarf_Off * die_offset, + Dwarf_Off * cu_die_offset, Dwarf_Error * error) +{ + Dwarf_Global type = (Dwarf_Global) type_in; + return dwarf_global_name_offsets(type, + returned_name, + die_offset, cu_die_offset, error); +} diff --git a/usr/src/lib/libdwarf/common/dwarf_types.h b/usr/src/lib/libdwarf/common/dwarf_types.h new file mode 100644 index 0000000000..ebd31c6c79 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_types.h @@ -0,0 +1,41 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + + +typedef struct Dwarf_Type_Context_s *Dwarf_Type_Context; + +/* type never completed see dwarf_global.h */ diff --git a/usr/src/lib/libdwarf/common/dwarf_util.c b/usr/src/lib/libdwarf/common/dwarf_util.c new file mode 100644 index 0000000000..01e0dd755d --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_util.c @@ -0,0 +1,547 @@ +/* + Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + + + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include "dwarf_die_deliv.h" + + + +/* + Given a form, and a pointer to the bytes encoding + a value of that form, val_ptr, this function returns + the length, in bytes, of a value of that form. + When using this function, check for a return of 0 + a recursive DW_FORM_INDIRECT value. +*/ +Dwarf_Unsigned +_dwarf_get_size_of_val(Dwarf_Debug dbg, + Dwarf_Unsigned form, + Dwarf_Half address_size, + Dwarf_Small * val_ptr, int v_length_size) +{ + Dwarf_Unsigned length = 0; + Dwarf_Word leb128_length = 0; + Dwarf_Unsigned form_indirect = 0; + Dwarf_Unsigned ret_value = 0; + + switch (form) { + + default: /* Handles form = 0. */ + return (form); + + case DW_FORM_addr: + if(address_size) { + return address_size; + } + /* This should never happen, address_size should be set. */ + return (dbg->de_pointer_size); + + /* DWARF2 was wrong on the size of the attribute for + DW_FORM_ref_addr. We assume compilers are using the + corrected DWARF3 text (for 32bit pointer target objects pointer and + offsets are the same size anyway). */ + case DW_FORM_ref_addr: + return (v_length_size); + + case DW_FORM_block1: + return (*(Dwarf_Small *) val_ptr + 1); + + case DW_FORM_block2: + READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, + val_ptr, sizeof(Dwarf_Half)); + return (ret_value + sizeof(Dwarf_Half)); + + case DW_FORM_block4: + READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, + val_ptr, sizeof(Dwarf_ufixed)); + return (ret_value + sizeof(Dwarf_ufixed)); + + + case DW_FORM_data1: + return (1); + + case DW_FORM_data2: + return (2); + + case DW_FORM_data4: + return (4); + + case DW_FORM_data8: + return (8); + + case DW_FORM_string: + return (strlen((char *) val_ptr) + 1); + + case DW_FORM_block: + case DW_FORM_exprloc: + length = _dwarf_decode_u_leb128(val_ptr, &leb128_length); + return (length + leb128_length); + + case DW_FORM_flag_present: + return (0); + case DW_FORM_flag: + return (1); + + case DW_FORM_sec_offset: + /* If 32bit dwarf, is 4. Else is 64bit dwarf and is 8. */ + return (v_length_size); + + case DW_FORM_ref_udata: + length = _dwarf_decode_u_leb128(val_ptr, &leb128_length); + return (leb128_length); + + case DW_FORM_indirect: + { + Dwarf_Word indir_len = 0; + + form_indirect = _dwarf_decode_u_leb128(val_ptr, &indir_len); + if (form_indirect == DW_FORM_indirect) { + return (0); /* We are in big trouble: The true form + of DW_FORM_indirect is + DW_FORM_indirect? Nonsense. Should + never happen. */ + } + return (indir_len + _dwarf_get_size_of_val(dbg, + form_indirect, + address_size, + val_ptr + indir_len, + v_length_size)); + } + + case DW_FORM_ref1: + return (1); + + case DW_FORM_ref2: + return (2); + + case DW_FORM_ref4: + return (4); + + case DW_FORM_ref8: + return (8); + + case DW_FORM_sdata: + _dwarf_decode_s_leb128(val_ptr, &leb128_length); + return (leb128_length); + + case DW_FORM_strp: + return (v_length_size); + + case DW_FORM_udata: + _dwarf_decode_u_leb128(val_ptr, &leb128_length); + return (leb128_length); + } +} + +/* We allow an arbitrary number of HT_MULTIPLE entries + before resizing. It seems up to 20 or 30 + would work nearly as well. + We could have a different resize multiple than 'resize now' + test multiple, but for now we don't do that. +*/ +#define HT_MULTIPLE 8 + +/* Copy the old entries, updating each to be in + a new list. Don't delete anything. Leave the + htin with stale data. */ +static void +copy_abbrev_table_to_new_table(Dwarf_Hash_Table htin, + Dwarf_Hash_Table htout) +{ + Dwarf_Hash_Table_Entry entry_in = htin->tb_entries; + unsigned entry_in_count = htin->tb_table_entry_count; + Dwarf_Hash_Table_Entry entry_out = htout->tb_entries; + unsigned entry_out_count = htout->tb_table_entry_count; + unsigned k = 0; + for ( ; k < entry_in_count; ++k,++entry_in) { + Dwarf_Abbrev_List listent = entry_in->at_head; + Dwarf_Abbrev_List nextlistent = 0; + + for ( ; listent ; listent = nextlistent) { + unsigned newtmp = listent->ab_code; + unsigned newhash = newtmp%entry_out_count; + Dwarf_Hash_Table_Entry e; + nextlistent = listent->ab_next; + e = entry_out+newhash; + /* Move_entry_to_new_hash. This reverses the + order of the entries, effectively, but + that does not seem significant. */ + listent->ab_next = e->at_head; + e->at_head = listent; + + htout->tb_total_abbrev_count++; + } + } +} + +/* + This function returns a pointer to a Dwarf_Abbrev_List_s + struct for the abbrev with the given code. It puts the + struct on the appropriate hash table. It also adds all + the abbrev between the last abbrev added and this one to + the hash table. In other words, the .debug_abbrev section + is scanned sequentially from the top for an abbrev with + the given code. All intervening abbrevs are also put + into the hash table. + + This function hashes the given code, and checks the chain + at that hash table entry to see if a Dwarf_Abbrev_List_s + with the given code exists. If yes, it returns a pointer + to that struct. Otherwise, it scans the .debug_abbrev + section from the last byte scanned for that CU till either + an abbrev with the given code is found, or an abbrev code + of 0 is read. It puts Dwarf_Abbrev_List_s entries for all + abbrev's read till that point into the hash table. The + hash table contains both a head pointer and a tail pointer + for each entry. + + While the lists can move and entries can be moved between + lists on reallocation, any given Dwarf_Abbrev_list entry + never moves once allocated, so the pointer is safe to return. + + Returns NULL on error. +*/ +Dwarf_Abbrev_List +_dwarf_get_abbrev_for_code(Dwarf_CU_Context cu_context, Dwarf_Unsigned code) +{ + Dwarf_Debug dbg = cu_context->cc_dbg; + Dwarf_Hash_Table hash_table_base = cu_context->cc_abbrev_hash_table; + Dwarf_Hash_Table_Entry entry_base = 0; + Dwarf_Hash_Table_Entry entry_cur = 0; + Dwarf_Word hash_num = 0; + Dwarf_Unsigned abbrev_code = 0; + Dwarf_Unsigned abbrev_tag = 0; + Dwarf_Unsigned attr_name = 0; + Dwarf_Unsigned attr_form = 0; + + Dwarf_Abbrev_List hash_abbrev_entry = 0; + + Dwarf_Abbrev_List inner_list_entry = 0; + Dwarf_Hash_Table_Entry inner_hash_entry = 0; + + Dwarf_Byte_Ptr abbrev_ptr = 0; + unsigned hashable_val; + + if ( !hash_table_base->tb_entries ) { + hash_table_base->tb_table_entry_count = HT_MULTIPLE; + hash_table_base->tb_total_abbrev_count= 0; + hash_table_base->tb_entries = _dwarf_get_alloc(dbg, + DW_DLA_HASH_TABLE_ENTRY, + hash_table_base->tb_table_entry_count); + if(! hash_table_base->tb_entries) { + return NULL; + } + + } else if (hash_table_base->tb_total_abbrev_count > + ( hash_table_base->tb_table_entry_count * HT_MULTIPLE) ) { + struct Dwarf_Hash_Table_s newht; + /* Effectively multiplies by >= HT_MULTIPLE */ + newht.tb_table_entry_count = hash_table_base->tb_total_abbrev_count; + newht.tb_total_abbrev_count = 0; + newht.tb_entries = _dwarf_get_alloc(dbg, + DW_DLA_HASH_TABLE_ENTRY, + newht.tb_table_entry_count); + + if(! newht.tb_entries) { + return NULL; + } + /* Copy the existing entries to the new table, + rehashing each. + */ + copy_abbrev_table_to_new_table(hash_table_base, &newht); + /* Dealloc only the entries hash table array, not the lists + of things pointed to by a hash table entry array. */ + dwarf_dealloc(dbg, hash_table_base->tb_entries,DW_DLA_HASH_TABLE_ENTRY); + hash_table_base->tb_entries = 0; + /* Now overwrite the existing table descriptor with + the new, newly valid, contents. */ + *hash_table_base = newht; + } /* Else is ok as is, add entry */ + + + hashable_val = code; + hash_num = hashable_val % + hash_table_base->tb_table_entry_count; + entry_base = hash_table_base->tb_entries; + entry_cur = entry_base + hash_num; + + /* Determine if the 'code' is the list of synonyms already. */ + for (hash_abbrev_entry = entry_cur->at_head; + hash_abbrev_entry != NULL && hash_abbrev_entry->ab_code != code; + hash_abbrev_entry = hash_abbrev_entry->ab_next); + if (hash_abbrev_entry != NULL) { + /* This returns a pointer to an abbrev list entry, not + the list itself. */ + return (hash_abbrev_entry); + } + + abbrev_ptr = cu_context->cc_last_abbrev_ptr != NULL ? + cu_context->cc_last_abbrev_ptr : + dbg->de_debug_abbrev.dss_data + cu_context->cc_abbrev_offset; + + /* End of abbrev's for this cu, since abbrev code is 0. */ + if (*abbrev_ptr == 0) { + return (NULL); + } + + do { + unsigned new_hashable_val; + DECODE_LEB128_UWORD(abbrev_ptr, abbrev_code); + DECODE_LEB128_UWORD(abbrev_ptr, abbrev_tag); + + inner_list_entry = (Dwarf_Abbrev_List) + _dwarf_get_alloc(cu_context->cc_dbg, DW_DLA_ABBREV_LIST, 1); + if (inner_list_entry == NULL) + return (NULL); + + new_hashable_val = abbrev_code; + hash_num = new_hashable_val % + hash_table_base->tb_table_entry_count; + inner_hash_entry = entry_base + hash_num; + /* Move_entry_to_new_hash */ + inner_list_entry->ab_next = inner_hash_entry->at_head; + inner_hash_entry->at_head = inner_list_entry; + + hash_table_base->tb_total_abbrev_count++; + + inner_list_entry->ab_code = abbrev_code; + inner_list_entry->ab_tag = abbrev_tag; + inner_list_entry->ab_has_child = *(abbrev_ptr++); + inner_list_entry->ab_abbrev_ptr = abbrev_ptr; + + /* Cycle thru the abbrev content, ignoring the content except + to find the end of the content. */ + do { + DECODE_LEB128_UWORD(abbrev_ptr, attr_name); + DECODE_LEB128_UWORD(abbrev_ptr, attr_form); + } while (attr_name != 0 && attr_form != 0); + + } while (*abbrev_ptr != 0 && abbrev_code != code); + + cu_context->cc_last_abbrev_ptr = abbrev_ptr; + return (abbrev_code == code ? inner_list_entry : NULL); +} + + +/* return 1 if string ends before 'endptr' else +** return 0 meaning string is not properly terminated. +** Presumption is the 'endptr' pts to end of some dwarf section data. +*/ +int +_dwarf_string_valid(void *startptr, void *endptr) +{ + + char *start = startptr; + char *end = endptr; + + while (start < end) { + if (*start == 0) { + return 1; /* OK! */ + } + ++start; + ++end; + } + return 0; /* FAIL! bad string! */ +} + +/* + A byte-swapping version of memcpy + for cross-endian use. + Only 2,4,8 should be lengths passed in. +*/ +void * +_dwarf_memcpy_swap_bytes(void *s1, const void *s2, size_t len) +{ + void *orig_s1 = s1; + unsigned char *targ = (unsigned char *) s1; + unsigned char *src = (unsigned char *) s2; + + if (len == 4) { + targ[3] = src[0]; + targ[2] = src[1]; + targ[1] = src[2]; + targ[0] = src[3]; + } else if (len == 8) { + targ[7] = src[0]; + targ[6] = src[1]; + targ[5] = src[2]; + targ[4] = src[3]; + targ[3] = src[4]; + targ[2] = src[5]; + targ[1] = src[6]; + targ[0] = src[7]; + } else if (len == 2) { + targ[1] = src[0]; + targ[0] = src[1]; + } +/* should NOT get below here: is not the intended use */ + else if (len == 1) { + targ[0] = src[0]; + } else { + memcpy(s1, s2, len); + } + + return orig_s1; +} + + +/* + This calculation used to be sprinkled all over. + Now brought to one place. + + We try to accurately compute the size of a cu header + given a known cu header location ( an offset in .debug_info). + +*/ +/* ARGSUSED */ +Dwarf_Unsigned +_dwarf_length_of_cu_header(Dwarf_Debug dbg, Dwarf_Unsigned offset) +{ + int local_length_size = 0; + int local_extension_size = 0; + Dwarf_Unsigned length = 0; + Dwarf_Small *cuptr = dbg->de_debug_info.dss_data + offset; + + READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned, + cuptr, local_length_size, local_extension_size); + + return local_extension_size + /* initial extesion, if present + */ + local_length_size + /* Size of cu length field. */ + sizeof(Dwarf_Half) + /* Size of version stamp field. */ + local_length_size + /* Size of abbrev offset field. */ + sizeof(Dwarf_Small); /* Size of address size field. */ + +} + +/* + Pretend we know nothing about the CU + and just roughly compute the result. +*/ +Dwarf_Unsigned +_dwarf_length_of_cu_header_simple(Dwarf_Debug dbg) +{ + return dbg->de_length_size + /* Size of cu length field. */ + sizeof(Dwarf_Half) + /* Size of version stamp field. */ + dbg->de_length_size + /* Size of abbrev offset field. */ + sizeof(Dwarf_Small); /* Size of address size field. */ +} + +/* Now that we delay loading .debug_info, we need to do the + load in more places. So putting the load + code in one place now instead of replicating it in multiple + places. + +*/ +int +_dwarf_load_debug_info(Dwarf_Debug dbg, Dwarf_Error * error) +{ + int res = DW_DLV_ERROR; + + /* Testing de_debug_info.dss_data allows us to avoid testing + de_debug_abbrev.dss_data. + One test instead of 2. .debug_info is useless + without .debug_abbrev. */ + if (dbg->de_debug_info.dss_data) { + return DW_DLV_OK; + } + + res = _dwarf_load_section(dbg, &dbg->de_debug_abbrev,error); + if (res != DW_DLV_OK) { + return res; + } + res = _dwarf_load_section(dbg, &dbg->de_debug_info, error); + return res; + +} +void +_dwarf_free_abbrev_hash_table_contents(Dwarf_Debug dbg,Dwarf_Hash_Table hash_table) +{ + /* A Hash Table is an array with tb_table_entry_count struct + Dwarf_Hash_Table_s entries in the array. */ + int hashnum = 0; + for (; hashnum < hash_table->tb_table_entry_count; ++hashnum) { + struct Dwarf_Abbrev_List_s *abbrev = 0; + struct Dwarf_Abbrev_List_s *nextabbrev = 0; + struct Dwarf_Hash_Table_Entry_s *tb = &hash_table->tb_entries[hashnum]; + + abbrev = tb->at_head; + for (; abbrev; abbrev = nextabbrev) { + nextabbrev = abbrev->ab_next; + dwarf_dealloc(dbg, abbrev, DW_DLA_ABBREV_LIST); + } + } + /* Frees all the entries at once: an array. */ + dwarf_dealloc(dbg,hash_table->tb_entries,DW_DLA_HASH_TABLE_ENTRY); +} + +/* + If no die provided the size value returned might be wrong. + If different compilation units have different address sizes + this may not give the correct value in all contexts if the die + pointer is NULL. + If the Elf offset size != address_size + (for example if address_size = 4 but recorded in elf64 object) + this may not give the correct value in all contexts if the die + pointer is NULL. + If the die pointer is non-NULL (in which case it must point to + a valid DIE) this will return the correct size. +*/ +int +_dwarf_get_address_size(Dwarf_Debug dbg, Dwarf_Die die) +{ + Dwarf_CU_Context context = 0; + Dwarf_Half addrsize = 0; + if(!die) { + return dbg->de_pointer_size; + } + context = die->di_cu_context; + addrsize = context->cc_address_size; + return addrsize; +} + + + diff --git a/usr/src/lib/libdwarf/common/dwarf_util.h b/usr/src/lib/libdwarf/common/dwarf_util.h new file mode 100644 index 0000000000..4046bb2478 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_util.h @@ -0,0 +1,311 @@ +#ifndef DWARF_UTIL_H +#define DWARF_UTIL_H +/* + + Copyright (C) 2000,2003,2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + + + +/* + Decodes unsigned leb128 encoded numbers. + Make sure ptr is a pointer to a 1-byte type. + In 2003 and earlier this was a hand-inlined + version of _dwarf_decode_u_leb128() which did + not work correctly if Dwarf_Word was 64 bits. +*/ +#define DECODE_LEB128_UWORD(ptr, value) \ + do { \ + Dwarf_Word uleblen; \ + value = _dwarf_decode_u_leb128(ptr,&uleblen); \ + ptr += uleblen; \ + } while (0) + +/* + Decodes signed leb128 encoded numbers. + Make sure ptr is a pointer to a 1-byte type. + In 2003 and earlier this was a hand-inlined + version of _dwarf_decode_s_leb128() which did + not work correctly if Dwarf_Word was 64 bits. + +*/ +#define DECODE_LEB128_SWORD(ptr, value) \ + do { \ + Dwarf_Word sleblen; \ + value = _dwarf_decode_s_leb128(ptr,&sleblen); \ + ptr += sleblen; \ + } while(0) + + +/* + Skips leb128_encoded numbers that are guaranteed + to be no more than 4 bytes long. Same for both + signed and unsigned numbers. +*/ +#define SKIP_LEB128_WORD(ptr) \ + do{ if ((*(ptr++) & 0x80) != 0) { \ + if ((*(ptr++) & 0x80) != 0) { \ + if ((*(ptr++) & 0x80) != 0) { \ + if ((*(ptr++) & 0x80) != 0) { \ + } \ + } \ + } \ + } } while (0) + + +#define CHECK_DIE(die, error_ret_value) \ +do {if (die == NULL) { \ + _dwarf_error(NULL, error, DW_DLE_DIE_NULL); \ + return(error_ret_value); \ + } \ + if (die->di_cu_context == NULL) { \ + _dwarf_error(NULL, error, DW_DLE_DIE_NO_CU_CONTEXT); \ + return(error_ret_value); \ + } \ + if (die->di_cu_context->cc_dbg == NULL) { \ + _dwarf_error(NULL, error, DW_DLE_DBG_NULL); \ + return(error_ret_value); \ + } \ +} while (0) + + +/* + Reads 'source' for 'length' bytes from unaligned addr. + + Avoids any constant-in-conditional warnings and + avoids a test in the generated code (for non-const cases, + which are in the majority.) + Uses a temp to avoid the test. + The decl here should avoid any problem of size in the temp. + This code is ENDIAN DEPENDENT + The memcpy args are the endian issue. +*/ +typedef Dwarf_Unsigned BIGGEST_UINT; + +#ifdef WORDS_BIGENDIAN +#define READ_UNALIGNED(dbg,dest,desttype, source, length) \ + do { \ + BIGGEST_UINT _ltmp = 0; \ + dbg->de_copy_word( (((char *)(&_ltmp)) + sizeof(_ltmp) - length), \ + source, length) ; \ + dest = (desttype)_ltmp; \ + } while (0) + + +/* + This macro sign-extends a variable depending on the length. + It fills the bytes between the size of the destination and + the length with appropriate padding. + This code is ENDIAN DEPENDENT but dependent only + on host endianness, not object file endianness. + The memcpy args are the issue. +*/ +#define SIGN_EXTEND(dest, length) \ + do {if (*(Dwarf_Sbyte *)((char *)&dest + sizeof(dest) - length) < 0) {\ + memcpy((char *)&dest, "\xff\xff\xff\xff\xff\xff\xff\xff", \ + sizeof(dest) - length); \ + } \ + } while (0) +#else /* LITTLE ENDIAN */ + +#define READ_UNALIGNED(dbg,dest,desttype, source, length) \ + do { \ + BIGGEST_UINT _ltmp = 0; \ + dbg->de_copy_word( (char *)(&_ltmp) , \ + source, length) ; \ + dest = (desttype)_ltmp; \ + } while (0) + + +/* + This macro sign-extends a variable depending on the length. + It fills the bytes between the size of the destination and + the length with appropriate padding. + This code is ENDIAN DEPENDENT but dependent only + on host endianness, not object file endianness. + The memcpy args are the issue. +*/ +#define SIGN_EXTEND(dest, length) \ + do {if (*(Dwarf_Sbyte *)((char *)&dest + (length-1)) < 0) {\ + memcpy((char *)&dest+length, \ + "\xff\xff\xff\xff\xff\xff\xff\xff", \ + sizeof(dest) - length); \ + } \ + } while (0) + +#endif /* ! LITTLE_ENDIAN */ + + + +/* + READ_AREA LENGTH reads the length (the older way + of pure 32 or 64 bit + or the new proposed dwarfv2.1 64bit-extension way) + + It reads the bits from where rw_src_data_p points to + and updates the rw_src_data_p to point past what was just read. + + It updates w_length_size (to the size of an offset, either 4 or 8) + and w_exten_size (set 0 unless this frame has the DWARF3,4 64bit + extension, in which case w_exten_size is set to 4). + + r_dbg is just the current dbg pointer. + w_target is the output length field. + r_targtype is the output type. Always Dwarf_Unsigned so far. + +*/ +/* This one handles the v2.1 64bit extension + and 32bit (and MIPS fixed 64 bit via the + dwarf_init-set r_dbg->de_length_size).. + It does not recognize any but the one distingushed value + (the only one with defined meaning). + It assumes that no CU will have a length + 0xffffffxx (32bit length) + or + 0xffffffxx xxxxxxxx (64bit length) + which makes possible auto-detection of the extension. + + This depends on knowing that only a non-zero length + is legitimate (AFAICT), and for IRIX non-standard -64 + dwarf that the first 32 bits of the 64bit offset will be + zero (because the compiler could not handle a truly large + value as of Jan 2003 and because no app has that much debug + info anyway, at least not in the IRIX case). + + At present not testing for '64bit elf' here as that + does not seem necessary (none of the 64bit length seems + appropriate unless it's ident[EI_CLASS] == ELFCLASS64). +*/ +# define READ_AREA_LENGTH(r_dbg,w_target,r_targtype, \ + rw_src_data_p,w_length_size,w_exten_size) \ +do { READ_UNALIGNED(r_dbg,w_target,r_targtype, \ + rw_src_data_p, ORIGINAL_DWARF_OFFSET_SIZE); \ + if(w_target == DISTINGUISHED_VALUE) { \ + /* dwarf3 64bit extension */ \ + w_length_size = DISTINGUISHED_VALUE_OFFSET_SIZE; \ + rw_src_data_p += ORIGINAL_DWARF_OFFSET_SIZE; \ + w_exten_size = ORIGINAL_DWARF_OFFSET_SIZE; \ + READ_UNALIGNED(r_dbg,w_target,r_targtype, \ + rw_src_data_p, DISTINGUISHED_VALUE_OFFSET_SIZE);\ + rw_src_data_p += DISTINGUISHED_VALUE_OFFSET_SIZE; \ + } else { \ + if(w_target == 0 && r_dbg->de_big_endian_object) { \ + /* IRIX 64 bit, big endian. This test */ \ + /* is not a truly precise test, a precise test */ \ + /* would check if the target was IRIX. */ \ + READ_UNALIGNED(r_dbg,w_target,r_targtype, \ + rw_src_data_p, DISTINGUISHED_VALUE_OFFSET_SIZE); \ + w_length_size = DISTINGUISHED_VALUE_OFFSET_SIZE; \ + rw_src_data_p += DISTINGUISHED_VALUE_OFFSET_SIZE; \ + w_exten_size = 0; \ + } else { \ + /* standard 32 bit dwarf2/dwarf3 */ \ + w_exten_size = 0; \ + w_length_size = ORIGINAL_DWARF_OFFSET_SIZE; \ + rw_src_data_p += w_length_size; \ + } \ + } } while(0) + +Dwarf_Unsigned +_dwarf_decode_u_leb128(Dwarf_Small * leb128, + Dwarf_Word * leb128_length); + +Dwarf_Signed +_dwarf_decode_s_leb128(Dwarf_Small * leb128, + Dwarf_Word * leb128_length); + +Dwarf_Unsigned +_dwarf_get_size_of_val(Dwarf_Debug dbg, + Dwarf_Unsigned form, + Dwarf_Half address_size, + Dwarf_Small * val_ptr, + int v_length_size); + +struct Dwarf_Hash_Table_Entry_s; +/* This single struct is the base for the hash table. + The intent is that once the total_abbrev_count across + all the entries is greater than 10*current_table_entry_count + one should build a new Dwarf_Hash_Table_Base_s, rehash + all the existing entries, and delete the old table and entries. + (10 is a heuristic, nothing magic about it, but once the + count gets to 30 or 40 times current_table_entry_count + things really slow down a lot. One (500MB) application had + 127000 abbreviations in one compilation unit) + The incoming 'code' is an abbrev number and those simply + increase linearly so the hashing is perfect always. +*/ +struct Dwarf_Hash_Table_s { + unsigned long tb_table_entry_count; + unsigned long tb_total_abbrev_count; + /* Each table entry is a list of abbreviations. */ + struct Dwarf_Hash_Table_Entry_s *tb_entries; +}; + +/* + This struct is used to build a hash table for the + abbreviation codes for a compile-unit. +*/ +struct Dwarf_Hash_Table_Entry_s { + Dwarf_Abbrev_List at_head; +}; + + + +Dwarf_Abbrev_List +_dwarf_get_abbrev_for_code(Dwarf_CU_Context cu_context, + Dwarf_Unsigned code); + + +/* return 1 if string ends before 'endptr' else +** return 0 meaning string is not properly terminated. +** Presumption is the 'endptr' pts to end of some dwarf section data. +*/ +int _dwarf_string_valid(void *startptr, void *endptr); + +Dwarf_Unsigned _dwarf_length_of_cu_header(Dwarf_Debug, + Dwarf_Unsigned offset); +Dwarf_Unsigned _dwarf_length_of_cu_header_simple(Dwarf_Debug); + +int _dwarf_load_debug_info(Dwarf_Debug dbg, Dwarf_Error *error); +void _dwarf_free_abbrev_hash_table_contents(Dwarf_Debug dbg, + struct Dwarf_Hash_Table_s* hash_table); +int _dwarf_get_address_size(Dwarf_Debug dbg, Dwarf_Die die); + +#endif /* DWARF_UTIL_H */ diff --git a/usr/src/lib/libdwarf/common/dwarf_vars.c b/usr/src/lib/libdwarf/common/dwarf_vars.c new file mode 100644 index 0000000000..24105289ba --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_vars.c @@ -0,0 +1,133 @@ +/* + + Copyright (C) 2000,2002,2004,2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include "dwarf_vars.h" +#include "dwarf_global.h" + +int +dwarf_get_vars(Dwarf_Debug dbg, + Dwarf_Var ** vars, + Dwarf_Signed * ret_var_count, Dwarf_Error * error) +{ + int res = _dwarf_load_section(dbg, &dbg->de_debug_varnames,error); + if (res != DW_DLV_OK) { + return res; + } + + return _dwarf_internal_get_pubnames_like_data(dbg, + dbg->de_debug_varnames.dss_data, + dbg->de_debug_varnames.dss_size, + (Dwarf_Global **) vars, /* Type punning for sections + with identical format. */ + ret_var_count, + error, + DW_DLA_VAR_CONTEXT, + DW_DLA_VAR, + DW_DLE_DEBUG_VARNAMES_LENGTH_BAD, + DW_DLE_DEBUG_VARNAMES_VERSION_ERROR); +} + +/* Deallocating fully requires deallocating the list + and all entries. But some internal data is + not exposed, so we need a function with internal knowledge. +*/ + +void +dwarf_vars_dealloc(Dwarf_Debug dbg, Dwarf_Var * dwgl, + Dwarf_Signed count) +{ + _dwarf_internal_globals_dealloc(dbg, (Dwarf_Global *) dwgl, + count, + DW_DLA_VAR_CONTEXT, + DW_DLA_VAR, DW_DLA_LIST); + return; +} + + +int +dwarf_varname(Dwarf_Var var_in, char **ret_varname, Dwarf_Error * error) +{ + Dwarf_Global var = (Dwarf_Global) var_in; + + if (var == NULL) { + _dwarf_error(NULL, error, DW_DLE_VAR_NULL); + return (DW_DLV_ERROR); + } + + *ret_varname = (char *) (var->gl_name); + return DW_DLV_OK; +} + + +int +dwarf_var_die_offset(Dwarf_Var var_in, + Dwarf_Off * returned_offset, Dwarf_Error * error) +{ + Dwarf_Global var = (Dwarf_Global) var_in; + + return dwarf_global_die_offset(var, returned_offset, error); + +} + + +int +dwarf_var_cu_offset(Dwarf_Var var_in, + Dwarf_Off * returned_offset, Dwarf_Error * error) +{ + Dwarf_Global var = (Dwarf_Global) var_in; + + return dwarf_global_cu_offset(var, returned_offset, error); +} + + +int +dwarf_var_name_offsets(Dwarf_Var var_in, + char **returned_name, + Dwarf_Off * die_offset, + Dwarf_Off * cu_offset, Dwarf_Error * error) +{ + Dwarf_Global var = (Dwarf_Global) var_in; + + return + dwarf_global_name_offsets(var, + returned_name, die_offset, cu_offset, + error); +} diff --git a/usr/src/lib/libdwarf/common/dwarf_vars.h b/usr/src/lib/libdwarf/common/dwarf_vars.h new file mode 100644 index 0000000000..bd5f967e48 --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_vars.h @@ -0,0 +1,41 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + + +typedef struct Dwarf_Var_Context_s *Dwarf_Var_Context; + +/* struct never completed: see dwarf_global.h */ diff --git a/usr/src/lib/libdwarf/common/dwarf_weaks.c b/usr/src/lib/libdwarf/common/dwarf_weaks.c new file mode 100644 index 0000000000..425916e62e --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_weaks.c @@ -0,0 +1,130 @@ +/* + + Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "dwarf_incl.h" +#include +#include "dwarf_weaks.h" +#include "dwarf_global.h" + +int +dwarf_get_weaks(Dwarf_Debug dbg, + Dwarf_Weak ** weaks, + Dwarf_Signed * ret_weak_count, Dwarf_Error * error) +{ + int res = _dwarf_load_section(dbg, &dbg->de_debug_weaknames,error); + if (res != DW_DLV_OK) { + return res; + } + + return _dwarf_internal_get_pubnames_like_data(dbg, + dbg->de_debug_weaknames.dss_data, + dbg->de_debug_weaknames.dss_size, + (Dwarf_Global **) weaks, /* Type punning for sections + with identical format. */ + ret_weak_count, + error, + DW_DLA_WEAK_CONTEXT, + DW_DLA_WEAK, + DW_DLE_DEBUG_WEAKNAMES_LENGTH_BAD, + DW_DLE_DEBUG_WEAKNAMES_VERSION_ERROR); +} + +/* Deallocating fully requires deallocating the list + and all entries. But some internal data is + not exposed, so we need a function with internal knowledge. +*/ + +void +dwarf_weaks_dealloc(Dwarf_Debug dbg, Dwarf_Weak * dwgl, + Dwarf_Signed count) +{ + _dwarf_internal_globals_dealloc(dbg, (Dwarf_Global *) dwgl, + count, + DW_DLA_WEAK_CONTEXT, + DW_DLA_WEAK, DW_DLA_LIST); + return; +} + + + +int +dwarf_weakname(Dwarf_Weak weak_in, char **ret_name, Dwarf_Error * error) +{ + Dwarf_Global weak = (Dwarf_Global) weak_in; + + if (weak == NULL) { + _dwarf_error(NULL, error, DW_DLE_WEAK_NULL); + return (DW_DLV_ERROR); + } + *ret_name = (char *) (weak->gl_name); + return DW_DLV_OK; +} + + +int +dwarf_weak_die_offset(Dwarf_Weak weak_in, + Dwarf_Off * weak_off, Dwarf_Error * error) +{ + Dwarf_Global weak = (Dwarf_Global) weak_in; + + return dwarf_global_die_offset(weak, weak_off, error); +} + + +int +dwarf_weak_cu_offset(Dwarf_Weak weak_in, + Dwarf_Off * weak_off, Dwarf_Error * error) +{ + Dwarf_Global weak = (Dwarf_Global) weak_in; + + return dwarf_global_cu_offset(weak, weak_off, error); +} + + +int +dwarf_weak_name_offsets(Dwarf_Weak weak_in, + char **weak_name, + Dwarf_Off * die_offset, + Dwarf_Off * cu_offset, Dwarf_Error * error) +{ + Dwarf_Global weak = (Dwarf_Global) weak_in; + + return dwarf_global_name_offsets(weak, + weak_name, die_offset, cu_offset, error); +} diff --git a/usr/src/lib/libdwarf/common/dwarf_weaks.h b/usr/src/lib/libdwarf/common/dwarf_weaks.h new file mode 100644 index 0000000000..d38f5f118a --- /dev/null +++ b/usr/src/lib/libdwarf/common/dwarf_weaks.h @@ -0,0 +1,41 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + + +typedef struct Dwarf_Weak_Context_s *Dwarf_Weak_Context; + +/* struct never completed: see dwarf_global.h */ diff --git a/usr/src/lib/libdwarf/common/libdwarf.h b/usr/src/lib/libdwarf/common/libdwarf.h new file mode 100644 index 0000000000..78627a96a6 --- /dev/null +++ b/usr/src/lib/libdwarf/common/libdwarf.h @@ -0,0 +1,2736 @@ +/* + + Copyright (C) 2000-2010 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2008-2010 David Anderson. All rights reserved. + Portions Copyright 2008-2010 Arxan Technologies, Inc. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + +#ifndef _LIBDWARF_H +#define _LIBDWARF_H +#ifdef __cplusplus +extern "C" { +#endif +/* + libdwarf.h + $Revision: #9 $ $Date: 2008/01/17 $ + + For libdwarf producers and consumers + + The interface is defined as having 8-byte signed and unsigned + values so it can handle 64-or-32bit target on 64-or-32bit host. + Addr is the native size: it represents pointers on + the host machine (not the target!). + + This contains declarations for types and all producer + and consumer functions. + + Function declarations are written on a single line each here + so one can use grep to each declaration in its entirety. + The declarations are a little harder to read this way, but... + +*/ + +struct Elf; +typedef struct Elf* dwarf_elf_handle; + +/* To enable printing with printf regardless of the + actual underlying data type, we define the DW_PR_xxx macros. */ +#if (_MIPS_SZLONG == 64) +/* Special case for MIPS, so -64 (LP64) build gets simple -long-. + Non-MIPS LP64 or ILP64 environments should probably ensure + _MIPS_SZLONG set to 64 everywhere this header is #included. +*/ +typedef int Dwarf_Bool; /* boolean type */ +typedef unsigned long Dwarf_Off; /* 4 or 8 byte file offset */ +typedef unsigned long Dwarf_Unsigned; /* 4 or 8 byte unsigned value */ +typedef unsigned short Dwarf_Half; /* 2 byte unsigned value */ +typedef unsigned char Dwarf_Small; /* 1 byte unsigned value */ +typedef signed long Dwarf_Signed; /* 4 or 8 byte signed value */ +typedef unsigned long Dwarf_Addr; /* target memory address */ +#define DW_PR_DUx "lx" +#define DW_PR_DSx "lx" +#define DW_PR_DUu "lu" +#define DW_PR_DSd "ld" + +#else /* 32-bit */ +/* This is for ILP32, allowing i/o of 64bit dwarf info. + Also should be fine for LP64 and ILP64 cases. +*/ +typedef int Dwarf_Bool; /* boolean type */ +typedef unsigned long long Dwarf_Off; /* 8 byte file offset */ +typedef unsigned long long Dwarf_Unsigned; /* 8 byte unsigned value*/ +typedef unsigned short Dwarf_Half; /* 2 byte unsigned value */ +typedef unsigned char Dwarf_Small; /* 1 byte unsigned value */ +typedef signed long long Dwarf_Signed; /* 8 byte signed value */ +typedef unsigned long long Dwarf_Addr; /* target memory address */ +#define DW_PR_DUx "llx" +#define DW_PR_DSx "llx" +#define DW_PR_DUu "llu" +#define DW_PR_DSd "lld" +#endif +#ifdef HAVE_NONSTANDARD_PRINTF_64_FORMAT +/* Windows does not use std C formatting, so allow it. */ +#undef DW_PR_DUx +#undef DW_PR_DSx +#undef DW_PR_DUu +#undef DW_PR_DSd +#define DW_PR_DUx "I64x" +#define DW_PR_DSx "I64x" +#define DW_PR_DUu "I64u" +#define DW_PR_DSd "I64d" +#endif /* HAVE_NONSTANDARD_FORMAT */ + +typedef void* Dwarf_Ptr; /* host machine pointer */ + +/* Used for DW_FORM_ref_sig8. It is not a string, it + is 8 bytes of a signature one would use to find + a type unit. See dwarf_formsig8() +*/ +typedef struct { + char signature[8]; +} Dwarf_Sig8; + +/* Contains info on an uninterpreted block of data +*/ +typedef struct { + Dwarf_Unsigned bl_len; /* length of block */ + Dwarf_Ptr bl_data; /* uninterpreted data */ + Dwarf_Small bl_from_loclist; /*non-0 if loclist, else debug_info*/ + Dwarf_Unsigned bl_section_offset; /* Section (not CU) offset + which 'data' comes from. */ +} Dwarf_Block; + + +/* location record +*/ +typedef struct { + Dwarf_Small lr_atom; /* location operation */ + Dwarf_Unsigned lr_number; /* operand */ + Dwarf_Unsigned lr_number2; /* for OP_BREGx */ + Dwarf_Unsigned lr_offset; /* offset in locexpr for OP_BRA etc */ +} Dwarf_Loc; + + +/* location description +*/ +typedef struct { + Dwarf_Addr ld_lopc; /* beginning of active range */ + Dwarf_Addr ld_hipc; /* end of active range */ + Dwarf_Half ld_cents; /* count of location records */ + Dwarf_Loc* ld_s; /* pointer to list of same */ + Dwarf_Small ld_from_loclist; + /* non-0 if loclist, else debug_info*/ + + Dwarf_Unsigned ld_section_offset; /* Section (not CU) offset + where loc-expr begins*/ +} Dwarf_Locdesc; + +/* First appears in DWARF3. + The dwr_addr1/addr2 data is either an offset (DW_RANGES_ENTRY) + or an address (dwr_addr2 in DW_RANGES_ADDRESS_SELECTION) or + both are zero (DW_RANGES_END). +*/ +enum Dwarf_Ranges_Entry_Type { DW_RANGES_ENTRY, + DW_RANGES_ADDRESS_SELECTION, + DW_RANGES_END }; +typedef struct { + Dwarf_Addr dwr_addr1; + Dwarf_Addr dwr_addr2; + enum Dwarf_Ranges_Entry_Type dwr_type; +} Dwarf_Ranges; + +/* Frame description instructions expanded. +*/ +typedef struct { + Dwarf_Small fp_base_op; + Dwarf_Small fp_extended_op; + Dwarf_Half fp_register; + + /* Value may be signed, depends on op. + Any applicable data_alignment_factor has + not been applied, this is the raw offset. */ + Dwarf_Unsigned fp_offset; + Dwarf_Off fp_instr_offset; +} Dwarf_Frame_Op; /* DWARF2 */ + +typedef struct { + Dwarf_Small fp_base_op; + Dwarf_Small fp_extended_op; + Dwarf_Half fp_register; + + /* Value may be signed, depends on op. + Any applicable data_alignment_factor has + not been applied, this is the raw offset. */ + Dwarf_Unsigned fp_offset_or_block_len; + Dwarf_Small *fp_expr_block; + + Dwarf_Off fp_instr_offset; +} Dwarf_Frame_Op3; /* DWARF3 and DWARF2 compatible */ + +/* ***IMPORTANT NOTE, TARGET DEPENDENCY **** + DW_REG_TABLE_SIZE must be at least as large as + the number of registers + (DW_FRAME_LAST_REG_NUM) as defined in dwarf.h + Preferably identical to DW_FRAME_LAST_REG_NUM. + Ensure [0-DW_REG_TABLE_SIZE] does not overlap + DW_FRAME_UNDEFINED_VAL or DW_FRAME_SAME_VAL. + Also ensure DW_FRAME_REG_INITIAL_VALUE is set to what + is appropriate to your cpu. + For various CPUs DW_FRAME_UNDEFINED_VAL is correct + as the value for DW_FRAME_REG_INITIAL_VALUE. + + For consumer apps, this can be set dynamically: see + dwarf_set_frame_rule_table_size(); + */ +#ifndef DW_REG_TABLE_SIZE +#define DW_REG_TABLE_SIZE 66 +#endif + +/* For MIPS, DW_FRAME_SAME_VAL is the correct default value + for a frame register value. For other CPUS another value + may be better, such as DW_FRAME_UNDEFINED_VAL. + See dwarf_set_frame_rule_table_size +*/ +#ifndef DW_FRAME_REG_INITIAL_VALUE +#define DW_FRAME_REG_INITIAL_VALUE DW_FRAME_SAME_VAL +#endif + +/* Taken as meaning 'undefined value', this is not + a column or register number. + Only present at libdwarf runtime in the consumer + interfaces. Never on disk. + DW_FRAME_* Values present on disk are in dwarf.h + Ensure this is > DW_REG_TABLE_SIZE (the reg table + size is changeable at runtime with the *reg3() interfaces, + and this value must be greater than the reg table size). +*/ +#define DW_FRAME_UNDEFINED_VAL 1034 + +/* Taken as meaning 'same value' as caller had, not a column + or register number. + Only present at libdwarf runtime in the consumer + interfaces. Never on disk. + DW_FRAME_* Values present on disk are in dwarf.h + Ensure this is > DW_REG_TABLE_SIZE (the reg table + size is changeable at runtime with the *reg3() interfaces, + and this value must be greater than the reg table size). +*/ +#define DW_FRAME_SAME_VAL 1035 + +/* For DWARF3 consumer interfaces, make the CFA a column with no + real table number. This is what should have been done + for the DWARF2 interfaces. This actually works for + both DWARF2 and DWARF3, but see the libdwarf documentation + on Dwarf_Regtable3 and dwarf_get_fde_info_for_reg3() + and dwarf_get_fde_info_for_all_regs3() + Do NOT use this with the older dwarf_get_fde_info_for_reg() + or dwarf_get_fde_info_for_all_regs() consumer interfaces. + Must be higher than any register count for *any* ABI + (ensures maximum applicability with minimum effort). + Ensure this is > DW_REG_TABLE_SIZE (the reg table + size is changeable at runtime with the *reg3() interfaces, + and this value must be greater than the reg table size). + Only present at libdwarf runtime in the consumer + interfaces. Never on disk. +*/ +#define DW_FRAME_CFA_COL3 1436 + +/* The following are all needed to evaluate DWARF3 register rules. +*/ +#define DW_EXPR_OFFSET 0 /* DWARF2 only sees this. */ +#define DW_EXPR_VAL_OFFSET 1 +#define DW_EXPR_EXPRESSION 2 +#define DW_EXPR_VAL_EXPRESSION 3 + +typedef struct Dwarf_Regtable_Entry_s { + /* For each index i (naming a hardware register with dwarf number + i) the following is true and defines the value of that register: + + If dw_regnum is Register DW_FRAME_UNDEFINED_VAL + it is not DWARF register number but + a place holder indicating the register has no defined value. + If dw_regnum is Register DW_FRAME_SAME_VAL + it is not DWARF register number but + a place holder indicating the register has the same + value in the previous frame. + DW_FRAME_UNDEFINED_VAL, DW_FRAME_SAME_VAL are + only present at libdwarf runtime. Never on disk. + DW_FRAME_* Values present on disk are in dwarf.h + + Otherwise: the register number is a DWARF register number + (see ABI documents for how this translates to hardware/ + software register numbers in the machine hardware) + and the following applies: + + if dw_value_type == DW_EXPR_OFFSET (the only case for dwarf2): + If dw_offset_relevant is non-zero, then + the value is stored at at the address CFA+N where + N is a signed offset. + Rule: Offset(N) + If dw_offset_relevant is zero, then the value of the register + is the value of (DWARF) register number dw_regnum. + Rule: register(F) + Other values of dw_value_type are an error. + */ + Dwarf_Small dw_offset_relevant; + + /* For DWARF2, always 0 */ + Dwarf_Small dw_value_type; + + Dwarf_Half dw_regnum; + + /* The data type here should the larger of Dwarf_Addr + and Dwarf_Unsigned and Dwarf_Signed. */ + Dwarf_Addr dw_offset; +} Dwarf_Regtable_Entry; + +typedef struct Dwarf_Regtable_s { + struct Dwarf_Regtable_Entry_s rules[DW_REG_TABLE_SIZE]; +} Dwarf_Regtable; + +/* opaque type. Functional interface shown later. */ +struct Dwarf_Reg_value3_s; +typedef struct Dwarf_Reg_value3_s Dwarf_Reg_Value3; + +typedef struct Dwarf_Regtable_Entry3_s { + /* For each index i (naming a hardware register with dwarf number + i) the following is true and defines the value of that register: + + If dw_regnum is Register DW_FRAME_UNDEFINED_VAL + it is not DWARF register number but + a place holder indicating the register has no defined value. + If dw_regnum is Register DW_FRAME_SAME_VAL + it is not DWARF register number but + a place holder indicating the register has the same + value in the previous frame. + DW_FRAME_UNDEFINED_VAL, DW_FRAME_SAME_VAL and + DW_FRAME_CFA_COL3 are only present at libdwarf runtime. + Never on disk. + DW_FRAME_* Values present on disk are in dwarf.h + Because DW_FRAME_SAME_VAL and DW_FRAME_UNDEFINED_VAL + and DW_FRAME_CFA_COL3 are defineable at runtime + consider the names symbolic in this comment, not absolute. + + Otherwise: the register number is a DWARF register number + (see ABI documents for how this translates to hardware/ + software register numbers in the machine hardware) + and the following applies: + + In a cfa-defining entry (rt3_cfa_rule) the regnum is the + CFA 'register number'. Which is some 'normal' register, + not DW_FRAME_CFA_COL3, nor DW_FRAME_SAME_VAL, nor + DW_FRAME_UNDEFINED_VAL. + + If dw_value_type == DW_EXPR_OFFSET (the only possible case for + dwarf2): + If dw_offset_relevant is non-zero, then + the value is stored at at the address + CFA+N where N is a signed offset. + dw_regnum is the cfa register rule which means + one ignores dw_regnum and uses the CFA appropriately. + So dw_offset_or_block_len is a signed value, really, + and must be printed/evaluated as such. + Rule: Offset(N) + If dw_offset_relevant is zero, then the value of the register + is the value of (DWARF) register number dw_regnum. + Rule: register(R) + If dw_value_type == DW_EXPR_VAL_OFFSET + the value of this register is CFA +N where N is a signed offset. + dw_regnum is the cfa register rule which means + one ignores dw_regnum and uses the CFA appropriately. + Rule: val_offset(N) + If dw_value_type == DW_EXPR_EXPRESSION + The value of the register is the value at the address + computed by evaluating the DWARF expression E. + Rule: expression(E) + The expression E byte stream is pointed to by dw_block_ptr. + The expression length in bytes is given by + dw_offset_or_block_len. + If dw_value_type == DW_EXPR_VAL_EXPRESSION + The value of the register is the value + computed by evaluating the DWARF expression E. + Rule: val_expression(E) + The expression E byte stream is pointed to by dw_block_ptr. + The expression length in bytes is given by + dw_offset_or_block_len. + Other values of dw_value_type are an error. + */ + Dwarf_Small dw_offset_relevant; + Dwarf_Small dw_value_type; + Dwarf_Half dw_regnum; + Dwarf_Unsigned dw_offset_or_block_len; + Dwarf_Ptr dw_block_ptr; + +}Dwarf_Regtable_Entry3; + +/* For the DWARF3 version, moved the DW_FRAME_CFA_COL + out of the array and into its own struct. + Having it part of the array is not very easy to work + with from a portability point of view: changing + the number for every architecture is a pain (if one fails + to set it correctly a register rule gets clobbered when + setting CFA). With MIPS it just happened to be easy to use + DW_FRAME_CFA_COL (it was wrong conceptually but it was easy...). + + rt3_rules and rt3_reg_table_size must be filled in before + calling libdwarf. Filled in with a pointer to an array + (pointer and array set up by the calling application) + of rt3_reg_table_size Dwarf_Regtable_Entry3_s structs. + libdwarf does not allocate or deallocate space for the + rules, you must do so. libdwarf will initialize the + contents rules array, you do not need to do so (though + if you choose to initialize the array somehow that is ok: + libdwarf will overwrite your initializations with its own). + +*/ +typedef struct Dwarf_Regtable3_s { + struct Dwarf_Regtable_Entry3_s rt3_cfa_rule; + + Dwarf_Half rt3_reg_table_size; + struct Dwarf_Regtable_Entry3_s * rt3_rules; +} Dwarf_Regtable3; + + +/* Use for DW_EPXR_STANDARD., DW_EXPR_VAL_OFFSET. + Returns DW_DLV_OK if the value is available. + If DW_DLV_OK returns the regnum and offset thru the pointers + (which the consumer must use appropriately). +*/ +int dwarf_frame_get_reg_register(struct Dwarf_Regtable_Entry3_s *reg_in, + Dwarf_Small *offset_relevant, + Dwarf_Half *regnum_out, + Dwarf_Signed *offset_out); + +/* Use for DW_EXPR_EXPRESSION, DW_EXPR_VAL_EXPRESSION. + Returns DW_DLV_OK if the value is available. + The caller must pass in the address of a valid + Dwarf_Block (the caller need not initialize it). +*/ +int dwarf_frame_get_reg_expression(struct Dwarf_Regtable_Entry3_s *reg_in, + Dwarf_Block *block_out); + + +/* For DW_DLC_SYMBOLIC_RELOCATIONS output to caller + v2, adding drd_length: some relocations are 4 and + some 8 bytes (pointers are 8, section offsets 4) in + some dwarf environments. (MIPS relocations are all one + size in any given ABI.) Changing drd_type to an unsigned char + to keep struct size down. +*/ +enum Dwarf_Rel_Type { + dwarf_drt_none, /* Should not get to caller */ + dwarf_drt_data_reloc, /* Simple normal relocation. */ + dwarf_drt_segment_rel, /* Special reloc, exceptions. */ + /* dwarf_drt_first_of_length_pair and drt_second + are for for the .word end - begin case. */ + dwarf_drt_first_of_length_pair, + dwarf_drt_second_of_length_pair +}; + +typedef struct Dwarf_P_Marker_s * Dwarf_P_Marker; +struct Dwarf_P_Marker_s { + Dwarf_Unsigned ma_marker; + Dwarf_Unsigned ma_offset; +}; + +typedef struct Dwarf_Relocation_Data_s * Dwarf_Relocation_Data; +struct Dwarf_Relocation_Data_s { + unsigned char drd_type; /* Cast to/from Dwarf_Rel_Type + to keep size small in struct. */ + unsigned char drd_length; /* Length in bytes of data being + relocated. 4 for 32bit data, + 8 for 64bit data. */ + Dwarf_Unsigned drd_offset; /* Where the data to reloc is. */ + Dwarf_Unsigned drd_symbol_index; +}; + +typedef struct Dwarf_P_String_Attr_s * Dwarf_P_String_Attr; +struct Dwarf_P_String_Attr_s { + Dwarf_Unsigned sa_offset; /* Offset of string attribute data */ + Dwarf_Unsigned sa_nbytes; +}; + + +/* Opaque types for Consumer Library. */ +typedef struct Dwarf_Debug_s* Dwarf_Debug; +typedef struct Dwarf_Die_s* Dwarf_Die; +typedef struct Dwarf_Line_s* Dwarf_Line; +typedef struct Dwarf_Global_s* Dwarf_Global; +typedef struct Dwarf_Func_s* Dwarf_Func; +typedef struct Dwarf_Type_s* Dwarf_Type; +typedef struct Dwarf_Var_s* Dwarf_Var; +typedef struct Dwarf_Weak_s* Dwarf_Weak; +typedef struct Dwarf_Error_s* Dwarf_Error; +typedef struct Dwarf_Attribute_s* Dwarf_Attribute; +typedef struct Dwarf_Abbrev_s* Dwarf_Abbrev; +typedef struct Dwarf_Fde_s* Dwarf_Fde; +typedef struct Dwarf_Cie_s* Dwarf_Cie; +typedef struct Dwarf_Arange_s* Dwarf_Arange; + +/* Opaque types for Producer Library. */ +typedef struct Dwarf_P_Debug_s* Dwarf_P_Debug; +typedef struct Dwarf_P_Die_s* Dwarf_P_Die; +typedef struct Dwarf_P_Attribute_s* Dwarf_P_Attribute; +typedef struct Dwarf_P_Fde_s* Dwarf_P_Fde; +typedef struct Dwarf_P_Expr_s* Dwarf_P_Expr; +typedef Dwarf_Unsigned Dwarf_Tag; + + +/* error handler function +*/ +typedef void (*Dwarf_Handler)(Dwarf_Error /*error*/, Dwarf_Ptr /*errarg*/); + + +/* Begin libdwarf Object File Interface declarations. + +As of February 2008 there are multiple dwarf_reader object access +initialization methods available: +The traditional dwarf_elf_init() and dwarf_init() and dwarf_finish() + which assume libelf and POSIX file access. +An object-file and library agnostic dwarf_object_init() and dwarf_object_finish() + which allow the coder to provide object access routines + abstracting away the elf interface. So there is no dependence in the + reader code on the object format and no dependence on libelf. + See the code in dwarf_elf_access.c and dwarf_original_elf_init.c + to see an example of initializing the structures mentioned below. + +Projects using dwarf_elf_init() or dwarf_init() can ignore +the Dwarf_Obj_Access* structures entirely as all these details +are completed for you. + +*/ + +typedef struct Dwarf_Obj_Access_Interface_s Dwarf_Obj_Access_Interface; +typedef struct Dwarf_Obj_Access_Methods_s Dwarf_Obj_Access_Methods; +typedef struct Dwarf_Obj_Access_Section_s Dwarf_Obj_Access_Section; + + +/* Used in the get_section interface function + in Dwarf_Obj_Access_Section_s. Since libdwarf + depends on standard DWARF section names an object + format that has no such names (but has some + method of setting up 'sections equivalents') + must arrange to return standard DWARF section + names in the 'name' field. libdwarf does + not free the strings in 'name'. */ +struct Dwarf_Obj_Access_Section_s { + Dwarf_Addr addr; + Dwarf_Unsigned size; + const char* name; + /* Set link to zero if it is meaningless. If non-zero + it should be a link to a rela section or from symtab + to strtab. In Elf it is sh_link. */ + Dwarf_Unsigned link; +}; + +/* Returned by the get_endianness function in + Dwarf_Obj_Access_Methods_s. */ +typedef enum { + DW_OBJECT_MSB, + DW_OBJECT_LSB +} Dwarf_Endianness; + +/* The functions we need to access object data from libdwarf are declared here. + + In these function pointer declarations + 'void *obj' is intended to be a pointer (the object field in + Dwarf_Obj_Access_Interface_s) + that hides the library-specific and object-specific data that makes + it possible to handle multiple object formats and multiple libraries. + It's not required that one handles multiple such in a single libdwarf + archive/shared-library (but not ruled out either). + See dwarf_elf_object_access_internals_t and dwarf_elf_access.c + for an example. + +*/ +struct Dwarf_Obj_Access_Methods_s { + /** + * get_section_info + * + * Get address, size, and name info about a section. + * + * Parameters + * section_index - Zero-based index. + * return_section - Pointer to a structure in which section info + * will be placed. Caller must provide a valid pointer to a + * structure area. The structure's contents will be overwritten + * by the call to get_section_info. + * error - A pointer to an integer in which an error code may be stored. + * + * Return + * DW_DLV_OK - Everything ok. + * DW_DLV_ERROR - Error occurred. Use 'error' to determine the + * libdwarf defined error. + * DW_DLV_NO_ENTRY - No such section. + */ + int (*get_section_info)(void* obj, Dwarf_Half section_index, + Dwarf_Obj_Access_Section* return_section, int* error); + /** + * get_byte_order + * + * Get whether the object file represented by this interface is big-endian + * (DW_OBJECT_MSB) or little endian (DW_OBJECT_LSB). + * + * Parameters + * obj - Equivalent to 'this' in OO languages. + * + * Return + * Endianness of object. Cannot fail. + */ + Dwarf_Endianness (*get_byte_order)(void* obj); + /** + * get_length_size + * + * Get the size of a length field in the underlying object file. + * libdwarf currently supports * 4 and 8 byte sizes, but may + * support larger in the future. + * Perhaps the return type should be an enumeration? + * + * Parameters + * obj - Equivalent to 'this' in OO languages. + * + * Return + * Size of length. Cannot fail. + */ + Dwarf_Small (*get_length_size)(void* obj); + /** + * get_pointer_size + * + * Get the size of a pointer field in the underlying object file. + * libdwarf currently supports 4 and 8 byte sizes. + * Perhaps the return type should be an enumeration? + + * Return + * Size of pointer. Cannot fail. + */ + Dwarf_Small (*get_pointer_size)(void* obj); + /** + * get_section_count + * + * Get the number of sections in the object file. + * + * Parameters + * + * Return + * Number of sections + */ + Dwarf_Unsigned (*get_section_count)(void* obj); + /** + * load_section + * + * Get a pointer to an array of bytes that represent the section. + * + * Parameters + * section_index - Zero-based index. + * return_data - The address of a pointer to which the section data block + * will be assigned. + * error - Pointer to an integer for returning libdwarf-defined + * error numbers. + * + * Return + * DW_DLV_OK - No error. + * DW_DLV_ERROR - Error. Use 'error' to indicate a libdwarf-defined + * error number. + * DW_DLV_NO_ENTRY - No such section. + */ + int (*load_section)(void* obj, Dwarf_Half section_index, + Dwarf_Small** return_data, int* error); + + /** + * relocate_a_section + * If relocations are not supported leave this pointer NULL. + * + * Get a pointer to an array of bytes that represent the section. + * + * Parameters + * section_index - Zero-based index of the section to be relocated. + * error - Pointer to an integer for returning libdwarf-defined + * error numbers. + * + * Return + * DW_DLV_OK - No error. + * DW_DLV_ERROR - Error. Use 'error' to indicate a libdwarf-defined + * error number. + * DW_DLV_NO_ENTRY - No such section. + */ + int (*relocate_a_section)(void* obj, Dwarf_Half section_index, + Dwarf_Debug dbg, + int* error); + +}; + + + +/* These structures are allocated and deallocated by your code + when you are using the libdwarf Object File Interface + [dwarf_object_init() and dwarf_object_finish()] directly. + dwarf_object_finish() does not free + struct Dwarf_Obj_Access_Interface_s or its content. + (libdwarf does record a pointer to this struct: you must + ensure that pointer remains valid for as long as + a libdwarf instance is open (meaning + after dwarf_init() and before dwarf_finish()). + + If you are reading Elf objects and libelf use dwarf_init() + or dwarf_elf_init() which take care of these details. +*/ +struct Dwarf_Obj_Access_Interface_s { + /* object is a void* as it hides the data the object access routines + need (which varies by library in use and object format). + */ + void* object; + const Dwarf_Obj_Access_Methods * methods; +}; + +/* End libdwarf Object File Interface */ + +/* + Dwarf_dealloc() alloc_type arguments. + Argument points to: +*/ +#define DW_DLA_STRING 0x01 /* char* */ +#define DW_DLA_LOC 0x02 /* Dwarf_Loc */ +#define DW_DLA_LOCDESC 0x03 /* Dwarf_Locdesc */ +#define DW_DLA_ELLIST 0x04 /* Dwarf_Ellist (not used)*/ +#define DW_DLA_BOUNDS 0x05 /* Dwarf_Bounds (not used) */ +#define DW_DLA_BLOCK 0x06 /* Dwarf_Block */ +#define DW_DLA_DEBUG 0x07 /* Dwarf_Debug */ +#define DW_DLA_DIE 0x08 /* Dwarf_Die */ +#define DW_DLA_LINE 0x09 /* Dwarf_Line */ +#define DW_DLA_ATTR 0x0a /* Dwarf_Attribute */ +#define DW_DLA_TYPE 0x0b /* Dwarf_Type (not used) */ +#define DW_DLA_SUBSCR 0x0c /* Dwarf_Subscr (not used) */ +#define DW_DLA_GLOBAL 0x0d /* Dwarf_Global */ +#define DW_DLA_ERROR 0x0e /* Dwarf_Error */ +#define DW_DLA_LIST 0x0f /* a list */ +#define DW_DLA_LINEBUF 0x10 /* Dwarf_Line* (not used) */ +#define DW_DLA_ARANGE 0x11 /* Dwarf_Arange */ +#define DW_DLA_ABBREV 0x12 /* Dwarf_Abbrev */ +#define DW_DLA_FRAME_OP 0x13 /* Dwarf_Frame_Op */ +#define DW_DLA_CIE 0x14 /* Dwarf_Cie */ +#define DW_DLA_FDE 0x15 /* Dwarf_Fde */ +#define DW_DLA_LOC_BLOCK 0x16 /* Dwarf_Loc Block (not used) */ +#define DW_DLA_FRAME_BLOCK 0x17 /* Dwarf_Frame Block (not used) */ +#define DW_DLA_FUNC 0x18 /* Dwarf_Func */ +#define DW_DLA_TYPENAME 0x19 /* Dwarf_Type */ +#define DW_DLA_VAR 0x1a /* Dwarf_Var */ +#define DW_DLA_WEAK 0x1b /* Dwarf_Weak */ +#define DW_DLA_ADDR 0x1c /* Dwarf_Addr sized entries */ +#define DW_DLA_RANGES 0x1d /* Dwarf_Ranges */ + +/* The augmenter string for CIE */ +#define DW_CIE_AUGMENTER_STRING_V0 "z" + +/* dwarf_init() access arguments +*/ +#define DW_DLC_READ 0 /* read only access */ +#define DW_DLC_WRITE 1 /* write only access */ +#define DW_DLC_RDWR 2 /* read/write access NOT SUPPORTED*/ + +/* pro_init() access flag modifiers + If HAVE_DWARF2_99_EXTENSION is defined at libdwarf build time + and DW_DLC_OFFSET_SIZE_64 is passed in pro_init() flags then the DWARF3 + 64 bit offset extension is used to generate 64 bit offsets. +*/ +#define DW_DLC_SIZE_64 0x40000000 /* 32-bit address-size target */ +#define DW_DLC_SIZE_32 0x20000000 /* 64-bit address-size target */ +#define DW_DLC_OFFSET_SIZE_64 0x10000000 /* 64-bit offset-size DWARF */ + +/* dwarf_pro_init() access flag modifiers +*/ +#define DW_DLC_ISA_MIPS 0x00000000 /* MIPS target */ +#define DW_DLC_ISA_IA64 0x01000000 /* IA64 target */ +#define DW_DLC_STREAM_RELOCATIONS 0x02000000 /* Old style binary relocs */ + + /* Usable with assembly output because it is up to the producer to + deal with locations in whatever manner the producer code wishes. + Possibly emitting text an assembler will recognize. */ +#define DW_DLC_SYMBOLIC_RELOCATIONS 0x04000000 + +#define DW_DLC_TARGET_BIGENDIAN 0x08000000 /* Big endian target */ +#define DW_DLC_TARGET_LITTLEENDIAN 0x00100000 /* Little endian target */ + +#if 0 + /* + The libdwarf producer interfaces jumble these two semantics together in + confusing ways. We *should* have flags like these... + But changing the code means a lot of diffs. So for now, + we leave things as they are + */ + #define DW_DLC_SUN_OFFSET32 0x00010000 /* use 32-bit sec offsets */ + #define DW_DLC_SUN_OFFSET64 0x00020000 /* use 64-bit sec offsets */ + #define DW_DLC_SUN_POINTER32 0x00040000 /* use 4 for address_size */ + #define DW_DLC_SUN_POINTER64 0x00080000 /* use 8 for address_size */ +#endif + +/* dwarf_pcline() slide arguments +*/ +#define DW_DLS_BACKWARD -1 /* slide backward to find line */ +#define DW_DLS_NOSLIDE 0 /* match exactly without sliding */ +#define DW_DLS_FORWARD 1 /* slide forward to find line */ + +/* libdwarf error numbers +*/ +#define DW_DLE_NE 0 /* no error */ +#define DW_DLE_VMM 1 /* dwarf format/library version mismatch */ +#define DW_DLE_MAP 2 /* memory map failure */ +#define DW_DLE_LEE 3 /* libelf error */ +#define DW_DLE_NDS 4 /* no debug section */ +#define DW_DLE_NLS 5 /* no line section */ +#define DW_DLE_ID 6 /* invalid descriptor for query */ +#define DW_DLE_IOF 7 /* I/O failure */ +#define DW_DLE_MAF 8 /* memory allocation failure */ +#define DW_DLE_IA 9 /* invalid argument */ +#define DW_DLE_MDE 10 /* mangled debugging entry */ +#define DW_DLE_MLE 11 /* mangled line number entry */ +#define DW_DLE_FNO 12 /* file not open */ +#define DW_DLE_FNR 13 /* file not a regular file */ +#define DW_DLE_FWA 14 /* file open with wrong access */ +#define DW_DLE_NOB 15 /* not an object file */ +#define DW_DLE_MOF 16 /* mangled object file header */ +#define DW_DLE_EOLL 17 /* end of location list entries */ +#define DW_DLE_NOLL 18 /* no location list section */ +#define DW_DLE_BADOFF 19 /* Invalid offset */ +#define DW_DLE_EOS 20 /* end of section */ +#define DW_DLE_ATRUNC 21 /* abbreviations section appears truncated*/ +#define DW_DLE_BADBITC 22 /* Address size passed to dwarf bad*/ + /* It is not an allowed size (64 or 32) */ + /* Error codes defined by the current Libdwarf Implementation. */ +#define DW_DLE_DBG_ALLOC 23 +#define DW_DLE_FSTAT_ERROR 24 +#define DW_DLE_FSTAT_MODE_ERROR 25 +#define DW_DLE_INIT_ACCESS_WRONG 26 +#define DW_DLE_ELF_BEGIN_ERROR 27 +#define DW_DLE_ELF_GETEHDR_ERROR 28 +#define DW_DLE_ELF_GETSHDR_ERROR 29 +#define DW_DLE_ELF_STRPTR_ERROR 30 +#define DW_DLE_DEBUG_INFO_DUPLICATE 31 +#define DW_DLE_DEBUG_INFO_NULL 32 +#define DW_DLE_DEBUG_ABBREV_DUPLICATE 33 +#define DW_DLE_DEBUG_ABBREV_NULL 34 +#define DW_DLE_DEBUG_ARANGES_DUPLICATE 35 +#define DW_DLE_DEBUG_ARANGES_NULL 36 +#define DW_DLE_DEBUG_LINE_DUPLICATE 37 +#define DW_DLE_DEBUG_LINE_NULL 38 +#define DW_DLE_DEBUG_LOC_DUPLICATE 39 +#define DW_DLE_DEBUG_LOC_NULL 40 +#define DW_DLE_DEBUG_MACINFO_DUPLICATE 41 +#define DW_DLE_DEBUG_MACINFO_NULL 42 +#define DW_DLE_DEBUG_PUBNAMES_DUPLICATE 43 +#define DW_DLE_DEBUG_PUBNAMES_NULL 44 +#define DW_DLE_DEBUG_STR_DUPLICATE 45 +#define DW_DLE_DEBUG_STR_NULL 46 +#define DW_DLE_CU_LENGTH_ERROR 47 +#define DW_DLE_VERSION_STAMP_ERROR 48 +#define DW_DLE_ABBREV_OFFSET_ERROR 49 +#define DW_DLE_ADDRESS_SIZE_ERROR 50 +#define DW_DLE_DEBUG_INFO_PTR_NULL 51 +#define DW_DLE_DIE_NULL 52 +#define DW_DLE_STRING_OFFSET_BAD 53 +#define DW_DLE_DEBUG_LINE_LENGTH_BAD 54 +#define DW_DLE_LINE_PROLOG_LENGTH_BAD 55 +#define DW_DLE_LINE_NUM_OPERANDS_BAD 56 +#define DW_DLE_LINE_SET_ADDR_ERROR 57 /* No longer used. */ +#define DW_DLE_LINE_EXT_OPCODE_BAD 58 +#define DW_DLE_DWARF_LINE_NULL 59 +#define DW_DLE_INCL_DIR_NUM_BAD 60 +#define DW_DLE_LINE_FILE_NUM_BAD 61 +#define DW_DLE_ALLOC_FAIL 62 +#define DW_DLE_NO_CALLBACK_FUNC 63 +#define DW_DLE_SECT_ALLOC 64 +#define DW_DLE_FILE_ENTRY_ALLOC 65 +#define DW_DLE_LINE_ALLOC 66 +#define DW_DLE_FPGM_ALLOC 67 +#define DW_DLE_INCDIR_ALLOC 68 +#define DW_DLE_STRING_ALLOC 69 +#define DW_DLE_CHUNK_ALLOC 70 +#define DW_DLE_BYTEOFF_ERR 71 +#define DW_DLE_CIE_ALLOC 72 +#define DW_DLE_FDE_ALLOC 73 +#define DW_DLE_REGNO_OVFL 74 +#define DW_DLE_CIE_OFFS_ALLOC 75 +#define DW_DLE_WRONG_ADDRESS 76 +#define DW_DLE_EXTRA_NEIGHBORS 77 +#define DW_DLE_WRONG_TAG 78 +#define DW_DLE_DIE_ALLOC 79 +#define DW_DLE_PARENT_EXISTS 80 +#define DW_DLE_DBG_NULL 81 +#define DW_DLE_DEBUGLINE_ERROR 82 +#define DW_DLE_DEBUGFRAME_ERROR 83 +#define DW_DLE_DEBUGINFO_ERROR 84 +#define DW_DLE_ATTR_ALLOC 85 +#define DW_DLE_ABBREV_ALLOC 86 +#define DW_DLE_OFFSET_UFLW 87 +#define DW_DLE_ELF_SECT_ERR 88 +#define DW_DLE_DEBUG_FRAME_LENGTH_BAD 89 +#define DW_DLE_FRAME_VERSION_BAD 90 +#define DW_DLE_CIE_RET_ADDR_REG_ERROR 91 +#define DW_DLE_FDE_NULL 92 +#define DW_DLE_FDE_DBG_NULL 93 +#define DW_DLE_CIE_NULL 94 +#define DW_DLE_CIE_DBG_NULL 95 +#define DW_DLE_FRAME_TABLE_COL_BAD 96 +#define DW_DLE_PC_NOT_IN_FDE_RANGE 97 +#define DW_DLE_CIE_INSTR_EXEC_ERROR 98 +#define DW_DLE_FRAME_INSTR_EXEC_ERROR 99 +#define DW_DLE_FDE_PTR_NULL 100 +#define DW_DLE_RET_OP_LIST_NULL 101 +#define DW_DLE_LINE_CONTEXT_NULL 102 +#define DW_DLE_DBG_NO_CU_CONTEXT 103 +#define DW_DLE_DIE_NO_CU_CONTEXT 104 +#define DW_DLE_FIRST_DIE_NOT_CU 105 +#define DW_DLE_NEXT_DIE_PTR_NULL 106 +#define DW_DLE_DEBUG_FRAME_DUPLICATE 107 +#define DW_DLE_DEBUG_FRAME_NULL 108 +#define DW_DLE_ABBREV_DECODE_ERROR 109 +#define DW_DLE_DWARF_ABBREV_NULL 110 +#define DW_DLE_ATTR_NULL 111 +#define DW_DLE_DIE_BAD 112 +#define DW_DLE_DIE_ABBREV_BAD 113 +#define DW_DLE_ATTR_FORM_BAD 114 +#define DW_DLE_ATTR_NO_CU_CONTEXT 115 +#define DW_DLE_ATTR_FORM_SIZE_BAD 116 +#define DW_DLE_ATTR_DBG_NULL 117 +#define DW_DLE_BAD_REF_FORM 118 +#define DW_DLE_ATTR_FORM_OFFSET_BAD 119 +#define DW_DLE_LINE_OFFSET_BAD 120 +#define DW_DLE_DEBUG_STR_OFFSET_BAD 121 +#define DW_DLE_STRING_PTR_NULL 122 +#define DW_DLE_PUBNAMES_VERSION_ERROR 123 +#define DW_DLE_PUBNAMES_LENGTH_BAD 124 +#define DW_DLE_GLOBAL_NULL 125 +#define DW_DLE_GLOBAL_CONTEXT_NULL 126 +#define DW_DLE_DIR_INDEX_BAD 127 +#define DW_DLE_LOC_EXPR_BAD 128 +#define DW_DLE_DIE_LOC_EXPR_BAD 129 +#define DW_DLE_ADDR_ALLOC 130 +#define DW_DLE_OFFSET_BAD 131 +#define DW_DLE_MAKE_CU_CONTEXT_FAIL 132 +#define DW_DLE_REL_ALLOC 133 +#define DW_DLE_ARANGE_OFFSET_BAD 134 +#define DW_DLE_SEGMENT_SIZE_BAD 135 +#define DW_DLE_ARANGE_LENGTH_BAD 136 +#define DW_DLE_ARANGE_DECODE_ERROR 137 +#define DW_DLE_ARANGES_NULL 138 +#define DW_DLE_ARANGE_NULL 139 +#define DW_DLE_NO_FILE_NAME 140 +#define DW_DLE_NO_COMP_DIR 141 +#define DW_DLE_CU_ADDRESS_SIZE_BAD 142 +#define DW_DLE_INPUT_ATTR_BAD 143 +#define DW_DLE_EXPR_NULL 144 +#define DW_DLE_BAD_EXPR_OPCODE 145 +#define DW_DLE_EXPR_LENGTH_BAD 146 +#define DW_DLE_MULTIPLE_RELOC_IN_EXPR 147 +#define DW_DLE_ELF_GETIDENT_ERROR 148 +#define DW_DLE_NO_AT_MIPS_FDE 149 +#define DW_DLE_NO_CIE_FOR_FDE 150 +#define DW_DLE_DIE_ABBREV_LIST_NULL 151 +#define DW_DLE_DEBUG_FUNCNAMES_DUPLICATE 152 +#define DW_DLE_DEBUG_FUNCNAMES_NULL 153 +#define DW_DLE_DEBUG_FUNCNAMES_VERSION_ERROR 154 +#define DW_DLE_DEBUG_FUNCNAMES_LENGTH_BAD 155 +#define DW_DLE_FUNC_NULL 156 +#define DW_DLE_FUNC_CONTEXT_NULL 157 +#define DW_DLE_DEBUG_TYPENAMES_DUPLICATE 158 +#define DW_DLE_DEBUG_TYPENAMES_NULL 159 +#define DW_DLE_DEBUG_TYPENAMES_VERSION_ERROR 160 +#define DW_DLE_DEBUG_TYPENAMES_LENGTH_BAD 161 +#define DW_DLE_TYPE_NULL 162 +#define DW_DLE_TYPE_CONTEXT_NULL 163 +#define DW_DLE_DEBUG_VARNAMES_DUPLICATE 164 +#define DW_DLE_DEBUG_VARNAMES_NULL 165 +#define DW_DLE_DEBUG_VARNAMES_VERSION_ERROR 166 +#define DW_DLE_DEBUG_VARNAMES_LENGTH_BAD 167 +#define DW_DLE_VAR_NULL 168 +#define DW_DLE_VAR_CONTEXT_NULL 169 +#define DW_DLE_DEBUG_WEAKNAMES_DUPLICATE 170 +#define DW_DLE_DEBUG_WEAKNAMES_NULL 171 +#define DW_DLE_DEBUG_WEAKNAMES_VERSION_ERROR 172 +#define DW_DLE_DEBUG_WEAKNAMES_LENGTH_BAD 173 +#define DW_DLE_WEAK_NULL 174 +#define DW_DLE_WEAK_CONTEXT_NULL 175 +#define DW_DLE_LOCDESC_COUNT_WRONG 176 +#define DW_DLE_MACINFO_STRING_NULL 177 +#define DW_DLE_MACINFO_STRING_EMPTY 178 +#define DW_DLE_MACINFO_INTERNAL_ERROR_SPACE 179 +#define DW_DLE_MACINFO_MALLOC_FAIL 180 +#define DW_DLE_DEBUGMACINFO_ERROR 181 +#define DW_DLE_DEBUG_MACRO_LENGTH_BAD 182 +#define DW_DLE_DEBUG_MACRO_MAX_BAD 183 +#define DW_DLE_DEBUG_MACRO_INTERNAL_ERR 184 +#define DW_DLE_DEBUG_MACRO_MALLOC_SPACE 185 +#define DW_DLE_DEBUG_MACRO_INCONSISTENT 186 +#define DW_DLE_DF_NO_CIE_AUGMENTATION 187 +#define DW_DLE_DF_REG_NUM_TOO_HIGH 188 +#define DW_DLE_DF_MAKE_INSTR_NO_INIT 189 +#define DW_DLE_DF_NEW_LOC_LESS_OLD_LOC 190 +#define DW_DLE_DF_POP_EMPTY_STACK 191 +#define DW_DLE_DF_ALLOC_FAIL 192 +#define DW_DLE_DF_FRAME_DECODING_ERROR 193 +#define DW_DLE_DEBUG_LOC_SECTION_SHORT 194 +#define DW_DLE_FRAME_AUGMENTATION_UNKNOWN 195 +#define DW_DLE_PUBTYPE_CONTEXT 196 /* Unused. */ +#define DW_DLE_DEBUG_PUBTYPES_LENGTH_BAD 197 +#define DW_DLE_DEBUG_PUBTYPES_VERSION_ERROR 198 +#define DW_DLE_DEBUG_PUBTYPES_DUPLICATE 199 +#define DW_DLE_FRAME_CIE_DECODE_ERROR 200 +#define DW_DLE_FRAME_REGISTER_UNREPRESENTABLE 201 +#define DW_DLE_FRAME_REGISTER_COUNT_MISMATCH 202 +#define DW_DLE_LINK_LOOP 203 +#define DW_DLE_STRP_OFFSET_BAD 204 +#define DW_DLE_DEBUG_RANGES_DUPLICATE 205 +#define DW_DLE_DEBUG_RANGES_OFFSET_BAD 206 +#define DW_DLE_DEBUG_RANGES_MISSING_END 207 +#define DW_DLE_DEBUG_RANGES_OUT_OF_MEM 208 +#define DW_DLE_DEBUG_SYMTAB_ERR 209 +#define DW_DLE_DEBUG_STRTAB_ERR 210 +#define DW_DLE_RELOC_MISMATCH_INDEX 211 +#define DW_DLE_RELOC_MISMATCH_RELOC_INDEX 212 +#define DW_DLE_RELOC_MISMATCH_STRTAB_INDEX 213 +#define DW_DLE_RELOC_SECTION_MISMATCH 214 +#define DW_DLE_RELOC_SECTION_MISSING_INDEX 215 +#define DW_DLE_RELOC_SECTION_LENGTH_ODD 216 +#define DW_DLE_RELOC_SECTION_PTR_NULL 217 +#define DW_DLE_RELOC_SECTION_MALLOC_FAIL 218 +#define DW_DLE_NO_ELF64_SUPPORT 219 +#define DW_DLE_MISSING_ELF64_SUPPORT 220 +#define DW_DLE_ORPHAN_FDE 221 +#define DW_DLE_DUPLICATE_INST_BLOCK 222 +#define DW_DLE_BAD_REF_SIG8_FORM 223 +#define DW_DLE_ATTR_EXPRLOC_FORM_BAD 224 +#define DW_DLE_FORM_SEC_OFFSET_LENGTH_BAD 225 +#define DW_DLE_NOT_REF_FORM 226 +#define DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE 227 + + + + /* DW_DLE_LAST MUST EQUAL LAST ERROR NUMBER */ +#define DW_DLE_LAST 227 +#define DW_DLE_LO_USER 0x10000 + + /* Taken as meaning 'undefined value', this is not + a column or register number. + Only present at libdwarf runtime. Never on disk. + DW_FRAME_* Values present on disk are in dwarf.h + */ +#define DW_FRAME_UNDEFINED_VAL 1034 + + /* Taken as meaning 'same value' as caller had, not a column + or register number + Only present at libdwarf runtime. Never on disk. + DW_FRAME_* Values present on disk are in dwarf.h + */ +#define DW_FRAME_SAME_VAL 1035 + + + +/* error return values +*/ +#define DW_DLV_BADADDR (~(Dwarf_Addr)0) + /* for functions returning target address */ + +#define DW_DLV_NOCOUNT ((Dwarf_Signed)-1) + /* for functions returning count */ + +#define DW_DLV_BADOFFSET (~(Dwarf_Off)0) + /* for functions returning offset */ + +/* standard return values for functions */ +#define DW_DLV_NO_ENTRY -1 +#define DW_DLV_OK 0 +#define DW_DLV_ERROR 1 + +/* Special values for offset_into_exception_table field of dwarf fde's. */ +/* The following value indicates that there is no Exception table offset + associated with a dwarf frame. */ +#define DW_DLX_NO_EH_OFFSET (-1LL) +/* The following value indicates that the producer was unable to analyse the + source file to generate Exception tables for this function. */ +#define DW_DLX_EH_OFFSET_UNAVAILABLE (-2LL) + + +/*===========================================================================*/ +/* Dwarf consumer interface initialization and termination operations */ + +/* Initialization based on Unix open fd (using libelf internally). */ +int dwarf_init(int /*fd*/, + Dwarf_Unsigned /*access*/, + Dwarf_Handler /*errhand*/, + Dwarf_Ptr /*errarg*/, + Dwarf_Debug* /*dbg*/, + Dwarf_Error* /*error*/); + +/* Initialization based on libelf/sgi-fastlibelf open pointer. */ +int dwarf_elf_init(dwarf_elf_handle /*elf*/, + Dwarf_Unsigned /*access*/, + Dwarf_Handler /*errhand*/, + Dwarf_Ptr /*errarg*/, + Dwarf_Debug* /*dbg*/, + Dwarf_Error* /*error*/); + +/* Undocumented function for memory allocator. */ +void dwarf_print_memory_stats(Dwarf_Debug /*dbg*/); + +int dwarf_get_elf(Dwarf_Debug /*dbg*/, + dwarf_elf_handle* /*return_elfptr*/, + Dwarf_Error* /*error*/); + +int dwarf_finish(Dwarf_Debug /*dbg*/, Dwarf_Error* /*error*/); + + +int dwarf_object_init(Dwarf_Obj_Access_Interface* /* obj */, + Dwarf_Handler /* errhand */, + Dwarf_Ptr /* errarg */, + Dwarf_Debug* /* dbg */, + Dwarf_Error* /* error */); + +int dwarf_object_finish(Dwarf_Debug /* dbg */, + Dwarf_Error* /* error */); + +/* die traversal operations */ +int dwarf_next_cu_header_b(Dwarf_Debug /*dbg*/, + Dwarf_Unsigned* /*cu_header_length*/, + Dwarf_Half* /*version_stamp*/, + Dwarf_Off* /*abbrev_offset*/, + Dwarf_Half* /*address_size*/, + Dwarf_Half* /*length_size*/, + Dwarf_Half* /*extension_size*/, + Dwarf_Unsigned* /*next_cu_header_offset*/, + Dwarf_Error* /*error*/); +/* The following is now obsolete, though supported. November 2009. */ +int dwarf_next_cu_header(Dwarf_Debug /*dbg*/, + Dwarf_Unsigned* /*cu_header_length*/, + Dwarf_Half* /*version_stamp*/, + Dwarf_Off* /*abbrev_offset*/, + Dwarf_Half* /*address_size*/, + Dwarf_Unsigned* /*next_cu_header_offset*/, + Dwarf_Error* /*error*/); + +int dwarf_siblingof(Dwarf_Debug /*dbg*/, + Dwarf_Die /*die*/, + Dwarf_Die* /*return_siblingdie*/, + Dwarf_Error* /*error*/); + +int dwarf_child(Dwarf_Die /*die*/, + Dwarf_Die* /*return_childdie*/, + Dwarf_Error* /*error*/); + +/* Finding die given global (not CU-relative) offset */ +int dwarf_offdie(Dwarf_Debug /*dbg*/, + Dwarf_Off /*offset*/, + Dwarf_Die* /*return_die*/, + Dwarf_Error* /*error*/); + +/* Higher level functions (Unimplemented) */ +int dwarf_pcfile(Dwarf_Debug /*dbg*/, + Dwarf_Addr /*pc*/, + Dwarf_Die* /*return_die*/, + Dwarf_Error* /*error*/); + +/* Unimplemented */ +int dwarf_pcsubr(Dwarf_Debug /*dbg*/, + Dwarf_Addr /*pc*/, + Dwarf_Die* /*return_die*/, + Dwarf_Error* /*error*/); + +/* Unimplemented */ +int dwarf_pcscope(Dwarf_Debug /*dbg*/, + Dwarf_Addr /*pc*/, + Dwarf_Die* /*return_die*/, + Dwarf_Error* /*error*/); + +/* operations on DIEs */ +int dwarf_tag(Dwarf_Die /*die*/, + Dwarf_Half* /*return_tag*/, + Dwarf_Error* /*error*/); + +/* utility? */ +/* dwarf_dieoffset returns the global debug_info + section offset, not the CU relative offset. */ +int dwarf_dieoffset(Dwarf_Die /*die*/, + Dwarf_Off* /*return_offset*/, + Dwarf_Error* /*error*/); + +/* dwarf_CU_dieoffset_given_die returns + the global debug_info section offset of the CU die + that is the CU containing the given_die + (the passed in DIE can be any DIE). + This information makes it possible for a consumer to + find and print CU context information for any die. + See also dwarf_get_cu_die_offset_given_cu_header_offset(). */ +int dwarf_CU_dieoffset_given_die(Dwarf_Die /*given_die*/, + Dwarf_Off* /*return_offset*/, + Dwarf_Error* /*error*/); + +/* dwarf_die_CU_offset returns the CU relative offset + not the global debug_info section offset, given + any DIE in the CU. See also dwarf_CU_dieoffset_given_die(). + */ +int dwarf_die_CU_offset(Dwarf_Die /*die*/, + Dwarf_Off* /*return_offset*/, + Dwarf_Error* /*error*/); + +int dwarf_die_CU_offset_range(Dwarf_Die /*die*/, + Dwarf_Off* /*return_CU_header_offset*/, + Dwarf_Off* /*return_CU_length_bytes*/, + Dwarf_Error* /*error*/); + +int dwarf_attr (Dwarf_Die /*die*/, + Dwarf_Half /*attr*/, + Dwarf_Attribute * /*returned_attr*/, + Dwarf_Error* /*error*/); + +int dwarf_diename(Dwarf_Die /*die*/, + char ** /*diename*/, + Dwarf_Error* /*error*/); + +/* Returns the abbrev code of the die. Cannot fail. */ +int dwarf_die_abbrev_code(Dwarf_Die /*die */); + + +/* convenience functions, alternative to using dwarf_attrlist() */ +int dwarf_hasattr(Dwarf_Die /*die*/, + Dwarf_Half /*attr*/, + Dwarf_Bool * /*returned_bool*/, + Dwarf_Error* /*error*/); + +/* dwarf_loclist_n preferred over dwarf_loclist */ +int dwarf_loclist_n(Dwarf_Attribute /*attr*/, + Dwarf_Locdesc*** /*llbuf*/, + Dwarf_Signed * /*locCount*/, + Dwarf_Error* /*error*/); + +int dwarf_loclist(Dwarf_Attribute /*attr*/, /* inflexible! */ + Dwarf_Locdesc** /*llbuf*/, + Dwarf_Signed * /*locCount*/, + Dwarf_Error* /*error*/); + +/* Extracts a dwarf expression from an expression byte stream. + Useful to get expressions from DW_CFA_def_cfa_expression + DW_CFA_expression DW_CFA_val_expression expression bytes. + 27 April 2009: dwarf_loclist_from_expr() interface with + no addr_size is obsolete but supported, + use dwarf_loclist_from_expr_a() instead. +*/ +int dwarf_loclist_from_expr(Dwarf_Debug dbg, + Dwarf_Ptr expression_in, + Dwarf_Unsigned expression_length, + Dwarf_Locdesc ** llbuf, + Dwarf_Signed * listlen, Dwarf_Error * error); + +/* dwarf_loclist_from_expr_a() new 27 Apr 2009: added addr_size argument. */ +int dwarf_loclist_from_expr_a(Dwarf_Debug dbg, + Dwarf_Ptr expression_in, + Dwarf_Unsigned expression_length, + Dwarf_Half addr_size, + Dwarf_Locdesc ** llbuf, + Dwarf_Signed * listlen, Dwarf_Error * error); + +/* Unimplemented */ +int dwarf_stringlen(Dwarf_Die /*die*/, + Dwarf_Locdesc ** /*returned_locdesc*/, + Dwarf_Error* /*error*/); + +/* Unimplemented */ +int dwarf_subscrcnt(Dwarf_Die /*die*/, + Dwarf_Signed * /*returned_count*/, + Dwarf_Error* /*error*/); + +/* Unimplemented */ +int dwarf_nthsubscr(Dwarf_Die /*die*/, + Dwarf_Unsigned /*ssndx*/, + Dwarf_Die * /*returned_die*/, + Dwarf_Error* /*error*/); + +int dwarf_lowpc(Dwarf_Die /*die*/, + Dwarf_Addr * /*returned_addr*/, + Dwarf_Error* /*error*/); + +int dwarf_highpc(Dwarf_Die /*die*/, + Dwarf_Addr * /*returned_addr*/, + Dwarf_Error* /*error*/); + +int dwarf_bytesize(Dwarf_Die /*die*/, + Dwarf_Unsigned * /*returned_size*/, + Dwarf_Error* /*error*/); + +/* Unimplemented */ +int dwarf_isbitfield(Dwarf_Die /*die*/, + Dwarf_Bool * /*returned_bool*/, + Dwarf_Error* /*error*/); + +int dwarf_bitsize(Dwarf_Die /*die*/, + Dwarf_Unsigned * /*returned_size*/, + Dwarf_Error* /*error*/); + +int dwarf_bitoffset(Dwarf_Die /*die*/, + Dwarf_Unsigned * /*returned_offset*/, + Dwarf_Error* /*error*/); + +int dwarf_srclang(Dwarf_Die /*die*/, + Dwarf_Unsigned * /*returned_lang*/, + Dwarf_Error* /*error*/); + +int dwarf_arrayorder(Dwarf_Die /*die*/, + Dwarf_Unsigned * /*returned_order*/, + Dwarf_Error* /*error*/); + +/* end of convenience function list */ + +/* this is the main interface to attributes of a DIE */ +int dwarf_attrlist(Dwarf_Die /*die*/, + Dwarf_Attribute** /*attrbuf*/, + Dwarf_Signed * /*attrcount*/, + Dwarf_Error* /*error*/); + +/* query operations for attributes */ +int dwarf_hasform(Dwarf_Attribute /*attr*/, + Dwarf_Half /*form*/, + Dwarf_Bool * /*returned_bool*/, + Dwarf_Error* /*error*/); + +int dwarf_whatform(Dwarf_Attribute /*attr*/, + Dwarf_Half * /*returned_form*/, + Dwarf_Error* /*error*/); + +int dwarf_whatform_direct(Dwarf_Attribute /*attr*/, + Dwarf_Half * /*returned_form*/, + Dwarf_Error* /*error*/); + +int dwarf_whatattr(Dwarf_Attribute /*attr*/, + Dwarf_Half * /*returned_attr_num*/, + Dwarf_Error* /*error*/); + +/* + The following are concerned with the Primary Interface: getting + the actual data values. One function per 'kind' of FORM. +*/ +/* dwarf_formref returns, thru return_offset, a CU-relative offset + and does not allow DW_FORM_ref_addr*/ +int dwarf_formref(Dwarf_Attribute /*attr*/, + Dwarf_Off* /*return_offset*/, + Dwarf_Error* /*error*/); +/* dwarf_global_formref returns, thru return_offset, + a debug_info-relative offset and does allow all reference forms*/ +int dwarf_global_formref(Dwarf_Attribute /*attr*/, + Dwarf_Off* /*return_offset*/, + Dwarf_Error* /*error*/); + +/* dwarf_formsig8 returns in the caller-provided 8 byte area + the 8 bytes of a DW_FORM_ref_sig8. Not a string. */ +int dwarf_formsig8(Dwarf_Attribute /*attr*/, + Dwarf_Sig8 * /*returned sig bytes*/, + Dwarf_Error* /*error*/); + +int dwarf_formaddr(Dwarf_Attribute /*attr*/, + Dwarf_Addr * /*returned_addr*/, + Dwarf_Error* /*error*/); + +int dwarf_formflag(Dwarf_Attribute /*attr*/, + Dwarf_Bool * /*returned_bool*/, + Dwarf_Error* /*error*/); + +int dwarf_formudata(Dwarf_Attribute /*attr*/, + Dwarf_Unsigned * /*returned_val*/, + Dwarf_Error* /*error*/); + +int dwarf_formsdata(Dwarf_Attribute /*attr*/, + Dwarf_Signed * /*returned_val*/, + Dwarf_Error* /*error*/); + +int dwarf_formblock(Dwarf_Attribute /*attr*/, + Dwarf_Block ** /*returned_block*/, + Dwarf_Error* /*error*/); + +int dwarf_formstring(Dwarf_Attribute /*attr*/, + char ** /*returned_string*/, + Dwarf_Error* /*error*/); + +int dwarf_formexprloc(Dwarf_Attribute /*attr*/, + Dwarf_Unsigned * /*return_exprlen*/, + Dwarf_Ptr * /*block_ptr*/, + Dwarf_Error * /*error*/); + + +/* end attribute query operations. */ + +/* line number operations */ +/* dwarf_srclines is the normal interface */ +int dwarf_srclines(Dwarf_Die /*die*/, + Dwarf_Line** /*linebuf*/, + Dwarf_Signed * /*linecount*/, + Dwarf_Error* /*error*/); + +/* dwarf_srclines_dealloc, created July 2005, is the new + method for deallocating what dwarf_srclines returns. + More complete free than using dwarf_dealloc directly. */ +void dwarf_srclines_dealloc(Dwarf_Debug /*dbg*/, + Dwarf_Line* /*linebuf*/, + Dwarf_Signed /*count */); + + +int dwarf_srcfiles(Dwarf_Die /*die*/, + char*** /*srcfiles*/, + Dwarf_Signed * /*filecount*/, + Dwarf_Error* /*error*/); + +/* Unimplemented. */ +int dwarf_dieline(Dwarf_Die /*die*/, + Dwarf_Line * /*returned_line*/, + Dwarf_Error * /*error*/); + +int dwarf_linebeginstatement(Dwarf_Line /*line*/, + Dwarf_Bool * /*returned_bool*/, + Dwarf_Error* /*error*/); + +int dwarf_lineendsequence(Dwarf_Line /*line*/, + Dwarf_Bool * /*returned_bool*/, + Dwarf_Error* /*error*/); + +int dwarf_lineno(Dwarf_Line /*line*/, + Dwarf_Unsigned * /*returned_lineno*/, + Dwarf_Error* /*error*/); + +int dwarf_line_srcfileno(Dwarf_Line /*line*/, + Dwarf_Unsigned * /*ret_fileno*/, + Dwarf_Error * /*error*/); + +int dwarf_lineaddr(Dwarf_Line /*line*/, + Dwarf_Addr * /*returned_addr*/, + Dwarf_Error* /*error*/); + +int dwarf_lineoff(Dwarf_Line /*line*/, + Dwarf_Signed * /*returned_lineoffset*/, + Dwarf_Error* /*error*/); + +int dwarf_linesrc(Dwarf_Line /*line*/, + char ** /*returned_name*/, + Dwarf_Error* /*error*/); + +int dwarf_lineblock(Dwarf_Line /*line*/, + Dwarf_Bool * /*returned_bool*/, + Dwarf_Error* /*error*/); + +/* tertiary interface to line info */ +/* Unimplemented */ +int dwarf_pclines(Dwarf_Debug /*dbg*/, + Dwarf_Addr /*pc*/, + Dwarf_Line** /*linebuf*/, + Dwarf_Signed * /*linecount*/, + Dwarf_Signed /*slide*/, + Dwarf_Error* /*error*/); +/* end line number operations */ + +/* global name space operations (.debug_pubnames access) */ +int dwarf_get_globals(Dwarf_Debug /*dbg*/, + Dwarf_Global** /*globals*/, + Dwarf_Signed * /*number_of_globals*/, + Dwarf_Error* /*error*/); +void dwarf_globals_dealloc(Dwarf_Debug /*dbg*/, + Dwarf_Global* /*globals*/, + Dwarf_Signed /*number_of_globals*/); + +int dwarf_globname(Dwarf_Global /*glob*/, + char ** /*returned_name*/, + Dwarf_Error* /*error*/); + +int dwarf_global_die_offset(Dwarf_Global /*global*/, + Dwarf_Off* /*return_offset*/, + Dwarf_Error * /*error*/); + +/* This returns the CU die global offset if one knows the + CU header global offset. + See also dwarf_CU_dieoffset_given_die(). */ +int dwarf_get_cu_die_offset_given_cu_header_offset( + Dwarf_Debug /*dbg*/, + Dwarf_Off /*in_cu_header_offset*/, + Dwarf_Off * /*out_cu_die_offset*/, + Dwarf_Error * /*err*/); +#ifdef __sgi /* pragma is sgi MIPS only */ +#pragma optional dwarf_get_cu_die_offset_given_cu_header_offset +#endif + +int dwarf_global_cu_offset(Dwarf_Global /*global*/, + Dwarf_Off* /*return_offset*/, + Dwarf_Error* /*error*/); + +int dwarf_global_name_offsets(Dwarf_Global /*global*/, + char ** /*returned_name*/, + Dwarf_Off* /*die_offset*/, + Dwarf_Off* /*cu_offset*/, + Dwarf_Error* /*error*/); + +/* Static function name operations. */ +int dwarf_get_funcs(Dwarf_Debug /*dbg*/, + Dwarf_Func** /*funcs*/, + Dwarf_Signed * /*number_of_funcs*/, + Dwarf_Error* /*error*/); +void dwarf_funcs_dealloc(Dwarf_Debug /*dbg*/, + Dwarf_Func* /*funcs*/, + Dwarf_Signed /*number_of_funcs*/); + +int dwarf_funcname(Dwarf_Func /*func*/, + char ** /*returned_name*/, + Dwarf_Error* /*error*/); + +int dwarf_func_die_offset(Dwarf_Func /*func*/, + Dwarf_Off* /*return_offset*/, + Dwarf_Error* /*error*/); + +int dwarf_func_cu_offset(Dwarf_Func /*func*/, + Dwarf_Off* /*return_offset*/, + Dwarf_Error* /*error*/); + +int dwarf_func_name_offsets(Dwarf_Func /*func*/, + char ** /*returned_name*/, + Dwarf_Off* /*die_offset*/, + Dwarf_Off* /*cu_offset*/, + Dwarf_Error* /*error*/); + +/* User-defined type name operations, SGI IRIX .debug_typenames section. + Same content as DWARF3 .debug_pubtypes, but defined years before + .debug_pubtypes was defined. SGI IRIX only. */ +int dwarf_get_types(Dwarf_Debug /*dbg*/, + Dwarf_Type** /*types*/, + Dwarf_Signed * /*number_of_types*/, + Dwarf_Error* /*error*/); +void dwarf_types_dealloc(Dwarf_Debug /*dbg*/, + Dwarf_Type* /*types*/, + Dwarf_Signed /*number_of_types*/); + + +int dwarf_typename(Dwarf_Type /*type*/, + char ** /*returned_name*/, + Dwarf_Error* /*error*/); + +int dwarf_type_die_offset(Dwarf_Type /*type*/, + Dwarf_Off* /*return_offset*/, + Dwarf_Error* /*error*/); + +int dwarf_type_cu_offset(Dwarf_Type /*type*/, + Dwarf_Off* /*return_offset*/, + Dwarf_Error* /*error*/); + +int dwarf_type_name_offsets(Dwarf_Type /*type*/, + char ** /*returned_name*/, + Dwarf_Off* /*die_offset*/, + Dwarf_Off* /*cu_offset*/, + Dwarf_Error* /*error*/); + +/* User-defined type name operations, DWARF3 .debug_pubtypes section. +*/ +int dwarf_get_pubtypes(Dwarf_Debug /*dbg*/, + Dwarf_Type** /*types*/, + Dwarf_Signed * /*number_of_types*/, + Dwarf_Error* /*error*/); +void dwarf_pubtypes_dealloc(Dwarf_Debug /*dbg*/, + Dwarf_Type* /*pubtypes*/, + Dwarf_Signed /*number_of_pubtypes*/); + + +int dwarf_pubtypename(Dwarf_Type /*type*/, + char ** /*returned_name*/, + Dwarf_Error* /*error*/); + +int dwarf_pubtype_die_offset(Dwarf_Type /*type*/, + Dwarf_Off* /*return_offset*/, + Dwarf_Error* /*error*/); + +int dwarf_pubtype_cu_offset(Dwarf_Type /*type*/, + Dwarf_Off* /*return_offset*/, + Dwarf_Error* /*error*/); + +int dwarf_pubtype_name_offsets(Dwarf_Type /*type*/, + char ** /*returned_name*/, + Dwarf_Off* /*die_offset*/, + Dwarf_Off* /*cu_offset*/, + Dwarf_Error* /*error*/); + +/* File-scope static variable name operations. */ +int dwarf_get_vars(Dwarf_Debug /*dbg*/, + Dwarf_Var** /*vars*/, + Dwarf_Signed * /*number_of_vars*/, + Dwarf_Error* /*error*/); +void dwarf_vars_dealloc(Dwarf_Debug /*dbg*/, + Dwarf_Var* /*vars*/, + Dwarf_Signed /*number_of_vars*/); + + +int dwarf_varname(Dwarf_Var /*var*/, + char ** /*returned_name*/, + Dwarf_Error* /*error*/); + +int dwarf_var_die_offset(Dwarf_Var /*var*/, + Dwarf_Off* /*return_offset*/, + Dwarf_Error* /*error*/); + +int dwarf_var_cu_offset(Dwarf_Var /*var*/, + Dwarf_Off* /*return_offset*/, + Dwarf_Error* /*error*/); + +int dwarf_var_name_offsets(Dwarf_Var /*var*/, + char ** /*returned_name*/, + Dwarf_Off* /*die_offset*/, + Dwarf_Off* /*cu_offset*/, + Dwarf_Error* /*error*/); + +/* weak name operations. */ +int dwarf_get_weaks(Dwarf_Debug /*dbg*/, + Dwarf_Weak** /*weaks*/, + Dwarf_Signed * /*number_of_weaks*/, + Dwarf_Error* /*error*/); +void dwarf_weaks_dealloc(Dwarf_Debug /*dbg*/, + Dwarf_Weak* /*weaks*/, + Dwarf_Signed /*number_of_weaks*/); + + +int dwarf_weakname(Dwarf_Weak /*weak*/, + char ** /*returned_name*/, + Dwarf_Error* /*error*/); + +int dwarf_weak_die_offset(Dwarf_Weak /*weak*/, + Dwarf_Off* /*return_offset*/, + Dwarf_Error* /*error*/); + +int dwarf_weak_cu_offset(Dwarf_Weak /*weak*/, + Dwarf_Off* /*return_offset*/, + Dwarf_Error* /*error*/); + +int dwarf_weak_name_offsets(Dwarf_Weak /*weak*/, + char ** /*returned_name*/, + Dwarf_Off* /*die_offset*/, + Dwarf_Off* /*cu_offset*/, + Dwarf_Error* /*error*/); + +/* location list section operation. (.debug_loc access) */ +int dwarf_get_loclist_entry(Dwarf_Debug /*dbg*/, + Dwarf_Unsigned /*offset*/, + Dwarf_Addr* /*hipc*/, + Dwarf_Addr* /*lopc*/, + Dwarf_Ptr* /*data*/, + Dwarf_Unsigned* /*entry_len*/, + Dwarf_Unsigned* /*next_entry*/, + Dwarf_Error* /*error*/); + +/* abbreviation section operations */ +int dwarf_get_abbrev(Dwarf_Debug /*dbg*/, + Dwarf_Unsigned /*offset*/, + Dwarf_Abbrev * /*returned_abbrev*/, + Dwarf_Unsigned* /*length*/, + Dwarf_Unsigned* /*attr_count*/, + Dwarf_Error* /*error*/); + +int dwarf_get_abbrev_tag(Dwarf_Abbrev /*abbrev*/, + Dwarf_Half* /*return_tag_number*/, + Dwarf_Error* /*error*/); +int dwarf_get_abbrev_code(Dwarf_Abbrev /*abbrev*/, + Dwarf_Unsigned* /*return_code_number*/, + Dwarf_Error* /*error*/); + +int dwarf_get_abbrev_children_flag(Dwarf_Abbrev /*abbrev*/, + Dwarf_Signed* /*return_flag*/, + Dwarf_Error* /*error*/); + +int dwarf_get_abbrev_entry(Dwarf_Abbrev /*abbrev*/, + Dwarf_Signed /*index*/, + Dwarf_Half * /*returned_attr_num*/, + Dwarf_Signed* /*form*/, + Dwarf_Off* /*offset*/, + Dwarf_Error* /*error*/); + +/* consumer string section operation */ +int dwarf_get_str(Dwarf_Debug /*dbg*/, + Dwarf_Off /*offset*/, + char** /*string*/, + Dwarf_Signed * /*strlen_of_string*/, + Dwarf_Error* /*error*/); + +/* Consumer op on gnu .eh_frame info */ +int dwarf_get_fde_list_eh( + Dwarf_Debug /*dbg*/, + Dwarf_Cie** /*cie_data*/, + Dwarf_Signed* /*cie_element_count*/, + Dwarf_Fde** /*fde_data*/, + Dwarf_Signed* /*fde_element_count*/, + Dwarf_Error* /*error*/); + + +/* consumer operations on frame info: .debug_frame */ +int dwarf_get_fde_list(Dwarf_Debug /*dbg*/, + Dwarf_Cie** /*cie_data*/, + Dwarf_Signed* /*cie_element_count*/, + Dwarf_Fde** /*fde_data*/, + Dwarf_Signed* /*fde_element_count*/, + Dwarf_Error* /*error*/); + +/* Release storage gotten by dwarf_get_fde_list_eh() or + dwarf_get_fde_list() */ +void dwarf_fde_cie_list_dealloc(Dwarf_Debug dbg, + Dwarf_Cie *cie_data, + Dwarf_Signed cie_element_count, + Dwarf_Fde *fde_data, + Dwarf_Signed fde_element_count); + + + +int dwarf_get_fde_range(Dwarf_Fde /*fde*/, + Dwarf_Addr* /*low_pc*/, + Dwarf_Unsigned* /*func_length*/, + Dwarf_Ptr* /*fde_bytes*/, + Dwarf_Unsigned* /*fde_byte_length*/, + Dwarf_Off* /*cie_offset*/, + Dwarf_Signed* /*cie_index*/, + Dwarf_Off* /*fde_offset*/, + Dwarf_Error* /*error*/); + +/* Useful for IRIX only: see dwarf_get_cie_augmentation_data() + dwarf_get_fde_augmentation_data() for GNU .eh_frame. */ +int dwarf_get_fde_exception_info(Dwarf_Fde /*fde*/, + Dwarf_Signed* /* offset_into_exception_tables */, + Dwarf_Error* /*error*/); + + +int dwarf_get_cie_of_fde(Dwarf_Fde /*fde*/, + Dwarf_Cie * /*cie_returned*/, + Dwarf_Error* /*error*/); + +int dwarf_get_cie_info(Dwarf_Cie /*cie*/, + Dwarf_Unsigned * /*bytes_in_cie*/, + Dwarf_Small* /*version*/, + char ** /*augmenter*/, + Dwarf_Unsigned* /*code_alignment_factor*/, + Dwarf_Signed* /*data_alignment_factor*/, + Dwarf_Half* /*return_address_register_rule*/, + Dwarf_Ptr* /*initial_instructions*/, + Dwarf_Unsigned* /*initial_instructions_length*/, + Dwarf_Error* /*error*/); + +/* dwarf_get_cie_index new September 2009. */ +int dwarf_get_cie_index( + Dwarf_Cie /*cie*/, + Dwarf_Signed* /*index*/, + Dwarf_Error* /*error*/ ); + + +int dwarf_get_fde_instr_bytes(Dwarf_Fde /*fde*/, + Dwarf_Ptr * /*outinstrs*/, Dwarf_Unsigned * /*outlen*/, + Dwarf_Error * /*error*/); + +int dwarf_get_fde_info_for_all_regs(Dwarf_Fde /*fde*/, + Dwarf_Addr /*pc_requested*/, + Dwarf_Regtable* /*reg_table*/, + Dwarf_Addr* /*row_pc*/, + Dwarf_Error* /*error*/); + +int dwarf_get_fde_info_for_all_regs3(Dwarf_Fde /*fde*/, + Dwarf_Addr /*pc_requested*/, + Dwarf_Regtable3* /*reg_table*/, + Dwarf_Addr* /*row_pc*/, + Dwarf_Error* /*error*/); + +/* In this older interface DW_FRAME_CFA_COL is a meaningful + column (which does not work well with DWARF3 or + non-MIPS architectures). */ +int dwarf_get_fde_info_for_reg(Dwarf_Fde /*fde*/, + Dwarf_Half /*table_column*/, + Dwarf_Addr /*pc_requested*/, + Dwarf_Signed* /*offset_relevant*/, + Dwarf_Signed* /*register*/, + Dwarf_Signed* /*offset*/, + Dwarf_Addr* /*row_pc*/, + Dwarf_Error* /*error*/); + +/* See discussion of dw_value_type, libdwarf.h. + Use of DW_FRAME_CFA_COL is not meaningful in this interface. + See dwarf_get_fde_info_for_cfa_reg3(). +*/ +/* dwarf_get_fde_info_for_reg3 is useful on a single column, but + it is inefficient to iterate across all table_columns using this + function. Instead call dwarf_get_fde_info_for_all_regs3() and index + into the table it fills in. */ +int dwarf_get_fde_info_for_reg3(Dwarf_Fde /*fde*/, + Dwarf_Half /*table_column*/, + Dwarf_Addr /*pc_requested*/, + Dwarf_Small * /*value_type*/, + Dwarf_Signed * /*offset_relevant*/, + Dwarf_Signed* /*register*/, + Dwarf_Signed* /*offset_or_block_len*/, + Dwarf_Ptr * /*block_ptr */, + Dwarf_Addr* /*row_pc_out*/, + Dwarf_Error* /*error*/); + +/* Use this to get the cfa. */ +int dwarf_get_fde_info_for_cfa_reg3(Dwarf_Fde /*fde*/, + Dwarf_Addr /*pc_requested*/, + Dwarf_Small * /*value_type*/, + Dwarf_Signed * /*offset_relevant*/, + Dwarf_Signed* /*register*/, + Dwarf_Signed* /*offset_or_block_len*/, + Dwarf_Ptr * /*block_ptr */, + Dwarf_Addr* /*row_pc_out*/, + Dwarf_Error* /*error*/); + +int dwarf_get_fde_for_die(Dwarf_Debug /*dbg*/, + Dwarf_Die /*subr_die */, + Dwarf_Fde * /*returned_fde*/, + Dwarf_Error* /*error*/); + +int dwarf_get_fde_n(Dwarf_Fde* /*fde_data*/, + Dwarf_Unsigned /*fde_index*/, + Dwarf_Fde * /*returned_fde*/, + Dwarf_Error* /*error*/); + +int dwarf_get_fde_at_pc(Dwarf_Fde* /*fde_data*/, + Dwarf_Addr /*pc_of_interest*/, + Dwarf_Fde * /*returned_fde*/, + Dwarf_Addr* /*lopc*/, + Dwarf_Addr* /*hipc*/, + Dwarf_Error* /*error*/); + +/* GNU .eh_frame augmentation information, raw form, see + Linux Standard Base Core Specification version 3.0 . */ +int dwarf_get_cie_augmentation_data(Dwarf_Cie /* cie*/, + Dwarf_Small ** /* augdata */, + Dwarf_Unsigned * /* augdata_len */, + Dwarf_Error* /*error*/); +/* GNU .eh_frame augmentation information, raw form, see + Linux Standard Base Core Specification version 3.0 . */ +int dwarf_get_fde_augmentation_data(Dwarf_Fde /* fde*/, + Dwarf_Small ** /* augdata */, + Dwarf_Unsigned * /* augdata_len */, + Dwarf_Error* /*error*/); + +int dwarf_expand_frame_instructions(Dwarf_Cie /*cie*/, + Dwarf_Ptr /*instruction*/, + Dwarf_Unsigned /*i_length*/, + Dwarf_Frame_Op** /*returned_op_list*/, + Dwarf_Signed* /*op_count*/, + Dwarf_Error* /*error*/); + +/* Operations on .debug_aranges. */ +int dwarf_get_aranges(Dwarf_Debug /*dbg*/, + Dwarf_Arange** /*aranges*/, + Dwarf_Signed * /*arange_count*/, + Dwarf_Error* /*error*/); + + + +int dwarf_get_arange( + Dwarf_Arange* /*aranges*/, + Dwarf_Unsigned /*arange_count*/, + Dwarf_Addr /*address*/, + Dwarf_Arange * /*returned_arange*/, + Dwarf_Error* /*error*/); + +int dwarf_get_cu_die_offset( + Dwarf_Arange /*arange*/, + Dwarf_Off* /*return_offset*/, + Dwarf_Error* /*error*/); + +int dwarf_get_arange_cu_header_offset( + Dwarf_Arange /*arange*/, + Dwarf_Off* /*return_cu_header_offset*/, + Dwarf_Error* /*error*/); +#ifdef __sgi /* pragma is sgi MIPS only */ +#pragma optional dwarf_get_arange_cu_header_offset +#endif + +/* DWARF2,3 interface. No longer really adequate (it was never + right for segmented address spaces, please switch + to using dwarf_get_arange_info_b instead. + There is no effective difference between these + functions if the address space + of the target is not segmented. */ +int dwarf_get_arange_info( + Dwarf_Arange /*arange*/, + Dwarf_Addr* /*start*/, + Dwarf_Unsigned* /*length*/, + Dwarf_Off* /*cu_die_offset*/, + Dwarf_Error* /*error*/ ); + +/* New for DWARF4, entries may have segment information. + *segment is only meaningful if *segment_entry_size is non-zero. */ +int dwarf_get_arange_info_b( + Dwarf_Arange /*arange*/, + Dwarf_Unsigned* /*segment*/, + Dwarf_Unsigned* /*segment_entry_size*/, + Dwarf_Addr * /*start*/, + Dwarf_Unsigned* /*length*/, + Dwarf_Off * /*cu_die_offset*/, + Dwarf_Error * /*error*/ ); + + +/* consumer .debug_macinfo information interface. +*/ +struct Dwarf_Macro_Details_s { + Dwarf_Off dmd_offset; /* offset, in the section, + of this macro info */ + Dwarf_Small dmd_type; /* the type, DW_MACINFO_define etc*/ + Dwarf_Signed dmd_lineno; /* the source line number where + applicable and vend_def # if + vendor_extension op + */ + + Dwarf_Signed dmd_fileindex;/* the source file index: + applies to define undef start_file + */ + char * dmd_macro; /* macro name (with value for defineop) + string from vendor ext + */ +}; + +/* dwarf_print_lines is for use by dwarfdump: it prints + line info to stdout. + The _dwarf name is obsolete. Use dwarf_ instead. + Added extra argnument 2/2009 for better checking. +*/ +int _dwarf_print_lines(Dwarf_Die /*cu_die*/,Dwarf_Error * /*error*/); +int dwarf_print_lines(Dwarf_Die /*cu_die*/,Dwarf_Error * /*error*/, + int * /*error_count_out */); + +/* dwarf_check_lineheader lets dwarfdump get detailed messages + about some compiler errors we detect. + We return the count of detected errors throught the + pointer. +*/ +void dwarf_check_lineheader(Dwarf_Die /*cu_die*/,int *errcount_out); + +/* dwarf_ld_sort_lines helps SGI IRIX ld + rearrange lines in .debug_line in a .o created with a text + section per function. + -OPT:procedure_reorder=ON + where ld-cord (cord(1)ing by ld, + not by cord(1)) may have changed the function order. + The _dwarf name is obsolete. Use dwarf_ instead. +*/ +int _dwarf_ld_sort_lines( + void * /*orig_buffer*/, + unsigned long /* buffer_len*/, + int /*is_64_bit*/, + int * /*any_change*/, + int * /*err_code*/); +int dwarf_ld_sort_lines( + void * /*orig_buffer*/, + unsigned long /*buffer_len*/, + int /*is_64_bit*/, + int * /*any_change*/, + int * /*err_code*/); + +/* Used by dwarfdump -v to print fde offsets from debugging + info. + The _dwarf name is obsolete. Use dwarf_ instead. +*/ +int _dwarf_fde_section_offset(Dwarf_Debug dbg, + Dwarf_Fde /*in_fde*/, + Dwarf_Off * /*fde_off*/, + Dwarf_Off * /*cie_off*/, + Dwarf_Error * /*err*/); +int dwarf_fde_section_offset(Dwarf_Debug dbg, + Dwarf_Fde /*in_fde*/, + Dwarf_Off * /*fde_off*/, + Dwarf_Off * /*cie_off*/, + Dwarf_Error * /*err*/); + +/* Used by dwarfdump -v to print cie offsets from debugging + info. + The _dwarf name is obsolete. Use dwarf_ instead. +*/ +int dwarf_cie_section_offset(Dwarf_Debug /*dbg*/, + Dwarf_Cie /*in_cie*/, + Dwarf_Off * /*cie_off */, + Dwarf_Error * /*err*/); +int _dwarf_cie_section_offset(Dwarf_Debug /*dbg*/, + Dwarf_Cie /*in_cie*/, + Dwarf_Off * /*cie_off*/, + Dwarf_Error * /*err*/); + +typedef struct Dwarf_Macro_Details_s Dwarf_Macro_Details; + +int dwarf_get_macro(Dwarf_Debug /*dbg*/, + char * /*requested_macro_name*/, + Dwarf_Addr /*pc_of_request*/, + char ** /*returned_macro_value*/, + Dwarf_Error * /*error*/); + +int dwarf_get_all_defined_macros(Dwarf_Debug /*dbg*/, + Dwarf_Addr /*pc_of_request*/, + Dwarf_Signed * /*returned_count*/, + char *** /*returned_pointers_to_macros*/, + Dwarf_Error * /*error*/); + +char *dwarf_find_macro_value_start(char * /*macro_string*/); + +int dwarf_get_macro_details(Dwarf_Debug /*dbg*/, + Dwarf_Off /*macro_offset*/, + Dwarf_Unsigned /*maximum_count*/, + Dwarf_Signed * /*entry_count*/, + Dwarf_Macro_Details ** /*details*/, + Dwarf_Error * /*err*/); + + +int dwarf_get_address_size(Dwarf_Debug /*dbg*/, + Dwarf_Half * /*addr_size*/, + Dwarf_Error * /*error*/); +int dwarf_get_die_address_size(Dwarf_Die /*die*/, + Dwarf_Half * /*addr_size*/, + Dwarf_Error * /*error*/); + +/* The dwarf specification separates FORMs into +different classes. To do the seperation properly +requires 4 pieces of data as of DWARF4 (thus the +function arguments listed here). +The DWARF4 specification class definition suffices to +describe all DWARF versions. +See section 7.5.4, Attribute Encodings. +A return of DW_FORM_CLASS_UNKNOWN means we could not properly figure +out what form-class it is. + + DW_FORM_CLASS_FRAMEPTR is MIPS/IRIX only, and refers + to the DW_AT_MIPS_fde attribute (a reference to the + .debug_frame section). +*/ +enum Dwarf_Form_Class { + DW_FORM_CLASS_UNKNOWN, DW_FORM_CLASS_ADDRESS, + DW_FORM_CLASS_BLOCK, DW_FORM_CLASS_CONSTANT, + DW_FORM_CLASS_EXPRLOC, DW_FORM_CLASS_FLAG, + DW_FORM_CLASS_LINEPTR, DW_FORM_CLASS_LOCLISTPTR, + DW_FORM_CLASS_MACPTR, DW_FORM_CLASS_RANGELISTPTR, + DW_FORM_CLASS_REFERENCE, DW_FORM_CLASS_STRING, + DW_FORM_CLASS_FRAMEPTR +}; + +enum Dwarf_Form_Class dwarf_get_form_class( + Dwarf_Half /* dwversion */, + Dwarf_Half /* attrnum */, + Dwarf_Half /*offset_size */, + Dwarf_Half /*form*/); + +/* utility operations */ +Dwarf_Unsigned dwarf_errno(Dwarf_Error /*error*/); + +char* dwarf_errmsg(Dwarf_Error /*error*/); + +/* stringcheck zero is default and means do all +** string length validity checks. +** Call with parameter value 1 to turn off many such checks (and +** increase performance). +** Call with zero for safest running. +** Actual value saved and returned is only 8 bits! Upper bits +** ignored by libdwarf (and zero on return). +** Returns previous value. +*/ +int dwarf_set_stringcheck(int /*stringcheck*/); + +/* 'apply' defaults to 1 and means do all + * 'rela' relocations on reading in a dwarf object section with + * such relocations. + * Call with parameter value 0 to turn off application of + * such relocations. + * Since the static linker leaves 'bogus' data in object sections + * with a 'rela' relocation section such data cannot be read + * sensibly without processing the relocations. Such relocations + * do not exist in executables and shared objects (.so), the + * relocations only exist in plain .o relocatable object files. + * Actual value saved and returned is only 8 bits! Upper bits + * ignored by libdwarf (and zero on return). + * Returns previous value. + * */ +int dwarf_set_reloc_application(int /*apply*/); + + +/* Unimplemented */ +Dwarf_Handler dwarf_seterrhand(Dwarf_Debug /*dbg*/, Dwarf_Handler /*errhand*/); + +/* Unimplemented */ +Dwarf_Ptr dwarf_seterrarg(Dwarf_Debug /*dbg*/, Dwarf_Ptr /*errarg*/); + +void dwarf_dealloc(Dwarf_Debug /*dbg*/, void* /*space*/, + Dwarf_Unsigned /*type*/); + +/* DWARF Producer Interface */ + +typedef int (*Dwarf_Callback_Func)( + char* /*name*/, + int /*size*/, + Dwarf_Unsigned /*type*/, + Dwarf_Unsigned /*flags*/, + Dwarf_Unsigned /*link*/, + Dwarf_Unsigned /*info*/, + int* /*sect name index*/, + int* /*error*/); + +Dwarf_P_Debug dwarf_producer_init( + Dwarf_Unsigned /*creation_flags*/, + Dwarf_Callback_Func /*func*/, + Dwarf_Handler /*errhand*/, + Dwarf_Ptr /*errarg*/, + Dwarf_Error* /*error*/); + +typedef int (*Dwarf_Callback_Func_b)( + char* /*name*/, + int /*size*/, + Dwarf_Unsigned /*type*/, + Dwarf_Unsigned /*flags*/, + Dwarf_Unsigned /*link*/, + Dwarf_Unsigned /*info*/, + Dwarf_Unsigned* /*sect_name_index*/, + int* /*error*/); + + +Dwarf_P_Debug dwarf_producer_init_b( + Dwarf_Unsigned /*flags*/, + Dwarf_Callback_Func_b /*func*/, + Dwarf_Handler /*errhand*/, + Dwarf_Ptr /*errarg*/, + Dwarf_Error * /*error*/); + + +Dwarf_Signed dwarf_transform_to_disk_form(Dwarf_P_Debug /*dbg*/, + Dwarf_Error* /*error*/); + +Dwarf_Ptr dwarf_get_section_bytes(Dwarf_P_Debug /*dbg*/, + Dwarf_Signed /*dwarf_section*/, + Dwarf_Signed* /*elf_section_index*/, + Dwarf_Unsigned* /*length*/, + Dwarf_Error* /*error*/); + +int dwarf_get_relocation_info_count( + Dwarf_P_Debug /*dbg*/, + Dwarf_Unsigned * /*count_of_relocation_sections*/, + int * /*drd_buffer_version*/, + Dwarf_Error* /*error*/); + +int dwarf_get_relocation_info( + Dwarf_P_Debug /*dbg*/, + Dwarf_Signed * /*elf_section_index*/, + Dwarf_Signed * /*elf_section_index_link*/, + Dwarf_Unsigned * /*relocation_buffer_count*/, + Dwarf_Relocation_Data * /*reldata_buffer*/, + Dwarf_Error* /*error*/); + +/* v1: no drd_length field, enum explicit */ +/* v2: has the drd_length field, enum value in uchar member */ +#define DWARF_DRD_BUFFER_VERSION 2 + +/* Markers are not written to DWARF2/3/4, they are user + defined and may be used for any purpose. +*/ +Dwarf_Signed dwarf_get_die_markers( + Dwarf_P_Debug /*dbg*/, + Dwarf_P_Marker * /*marker_list*/, + Dwarf_Unsigned * /*marker_count*/, + Dwarf_Error * /*error*/); + +int dwarf_get_string_attributes_count(Dwarf_P_Debug, + Dwarf_Unsigned *, + int *, + Dwarf_Error *); + +int dwarf_get_string_attributes_info(Dwarf_P_Debug, + Dwarf_Signed *, + Dwarf_Unsigned *, + Dwarf_P_String_Attr *, + Dwarf_Error *); + +void dwarf_reset_section_bytes(Dwarf_P_Debug /*dbg*/); + +Dwarf_Unsigned dwarf_producer_finish(Dwarf_P_Debug /*dbg*/, + Dwarf_Error* /*error*/); + +/* Producer attribute addition functions. */ +Dwarf_P_Attribute dwarf_add_AT_targ_address(Dwarf_P_Debug /*dbg*/, + Dwarf_P_Die /*ownerdie*/, + Dwarf_Half /*attr*/, + Dwarf_Unsigned /*pc_value*/, + Dwarf_Signed /*sym_index*/, + Dwarf_Error* /*error*/); + +Dwarf_P_Attribute dwarf_add_AT_block(Dwarf_P_Debug /*dbg*/, + Dwarf_P_Die /*ownerdie*/, + Dwarf_Half /*attr*/, + Dwarf_Small* /*block_data*/, + Dwarf_Unsigned /*block_len*/, + Dwarf_Error* /*error*/); + +Dwarf_P_Attribute dwarf_add_AT_targ_address_b(Dwarf_P_Debug /*dbg*/, + Dwarf_P_Die /*ownerdie*/, + Dwarf_Half /*attr*/, + Dwarf_Unsigned /*pc_value*/, + Dwarf_Unsigned /*sym_index*/, + Dwarf_Error* /*error*/); + +Dwarf_P_Attribute dwarf_add_AT_ref_address(Dwarf_P_Debug /*dbg*/, + Dwarf_P_Die /*ownerdie*/, + Dwarf_Half /*attr*/, + Dwarf_Unsigned /*pc_value*/, + Dwarf_Unsigned /*sym_index*/, + Dwarf_Error* /*error*/); + +Dwarf_P_Attribute dwarf_add_AT_unsigned_const(Dwarf_P_Debug /*dbg*/, + Dwarf_P_Die /*ownerdie*/, + Dwarf_Half /*attr*/, + Dwarf_Unsigned /*value*/, + Dwarf_Error* /*error*/); + +Dwarf_P_Attribute dwarf_add_AT_signed_const(Dwarf_P_Debug /*dbg*/, + Dwarf_P_Die /*ownerdie*/, + Dwarf_Half /*attr*/, + Dwarf_Signed /*value*/, + Dwarf_Error* /*error*/); + +Dwarf_P_Attribute dwarf_add_AT_reference(Dwarf_P_Debug /*dbg*/, + Dwarf_P_Die /*ownerdie*/, + Dwarf_Half /*attr*/, + Dwarf_P_Die /*otherdie*/, + Dwarf_Error* /*error*/); + +Dwarf_P_Attribute dwarf_add_AT_dataref( + Dwarf_P_Debug /* dbg*/, + Dwarf_P_Die /*ownerdie*/, + Dwarf_Half /*attr*/, + Dwarf_Unsigned /*pcvalue*/, + Dwarf_Unsigned /*sym_index*/, + Dwarf_Error* /*error*/); + +Dwarf_P_Attribute dwarf_add_AT_const_value_string(Dwarf_P_Die /*ownerdie*/, + char* /*string_value*/, + Dwarf_Error* /*error*/); + +Dwarf_P_Attribute dwarf_add_AT_location_expr(Dwarf_P_Debug /*dbg*/, + Dwarf_P_Die /*ownerdie*/, + Dwarf_Half /*attr*/, + Dwarf_P_Expr /*loc_expr*/, + Dwarf_Error* /*error*/); + +Dwarf_P_Attribute dwarf_add_AT_string(Dwarf_P_Debug /*dbg*/, + Dwarf_P_Die /*ownerdie*/, + Dwarf_Half /*attr*/, + char* /*string*/, + Dwarf_Error* /*error*/); + +Dwarf_P_Attribute dwarf_add_AT_flag(Dwarf_P_Debug /*dbg*/, + Dwarf_P_Die /*ownerdie*/, + Dwarf_Half /*attr*/, + Dwarf_Small /*flag*/, + Dwarf_Error* /*error*/); + +Dwarf_P_Attribute dwarf_add_AT_producer(Dwarf_P_Die /*ownerdie*/, + char* /*producer_string*/, + Dwarf_Error* /*error*/); + +Dwarf_P_Attribute dwarf_add_AT_const_value_signedint(Dwarf_P_Die /*ownerdie*/, + Dwarf_Signed /*signed_value*/, + Dwarf_Error* /*error*/); + +Dwarf_P_Attribute dwarf_add_AT_const_value_unsignedint( + Dwarf_P_Die /*ownerdie*/, + Dwarf_Unsigned /*unsigned_value*/, + Dwarf_Error* /*error*/); + +Dwarf_P_Attribute dwarf_add_AT_comp_dir(Dwarf_P_Die /*ownerdie*/, + char* /*current_working_directory*/, + Dwarf_Error* /*error*/); + +Dwarf_P_Attribute dwarf_add_AT_name(Dwarf_P_Die /*die*/, + char* /*name*/, + Dwarf_Error* /*error*/); + +/* Producer line creation functions (.debug_line) */ +Dwarf_Unsigned dwarf_add_directory_decl(Dwarf_P_Debug /*dbg*/, + char* /*name*/, + Dwarf_Error* /*error*/); + +Dwarf_Unsigned dwarf_add_file_decl(Dwarf_P_Debug /*dbg*/, + char* /*name*/, + Dwarf_Unsigned /*dir_index*/, + Dwarf_Unsigned /*time_last_modified*/, + Dwarf_Unsigned /*length*/, + Dwarf_Error* /*error*/); + +Dwarf_Unsigned dwarf_add_line_entry(Dwarf_P_Debug /*dbg*/, + Dwarf_Unsigned /*file_index*/, + Dwarf_Addr /*code_address*/, + Dwarf_Unsigned /*lineno*/, + Dwarf_Signed /*column_number*/, + Dwarf_Bool /*is_source_stmt_begin*/, + Dwarf_Bool /*is_basic_block_begin*/, + Dwarf_Error* /*error*/); + +Dwarf_Unsigned dwarf_lne_set_address(Dwarf_P_Debug /*dbg*/, + Dwarf_Unsigned /*offset*/, + Dwarf_Unsigned /*symbol_index*/, + Dwarf_Error* /*error*/); + +Dwarf_Unsigned dwarf_lne_end_sequence(Dwarf_P_Debug /*dbg*/, + Dwarf_Addr /*end_address*/, + Dwarf_Error* /*error*/); + +/* Producer .debug_frame functions */ +Dwarf_Unsigned dwarf_add_frame_cie(Dwarf_P_Debug /*dbg*/, + char* /*augmenter*/, + Dwarf_Small /*code_alignent_factor*/, + Dwarf_Small /*data_alignment_factor*/, + Dwarf_Small /*return_address_reg*/, + Dwarf_Ptr /*initialization_bytes*/, + Dwarf_Unsigned /*init_byte_len*/, + Dwarf_Error* /*error*/); + +Dwarf_Unsigned dwarf_add_frame_fde( + Dwarf_P_Debug /*dbg*/, + Dwarf_P_Fde /*fde*/, + Dwarf_P_Die /*corresponding subprogram die*/, + Dwarf_Unsigned /*cie_to_use*/, + Dwarf_Unsigned /*virt_addr_of_described_code*/, + Dwarf_Unsigned /*length_of_code*/, + Dwarf_Unsigned /*symbol_index*/, + Dwarf_Error* /*error*/); + +Dwarf_Unsigned dwarf_add_frame_fde_b( + Dwarf_P_Debug /*dbg*/, + Dwarf_P_Fde /*fde*/, + Dwarf_P_Die /*die*/, + Dwarf_Unsigned /*cie*/, + Dwarf_Addr /*virt_addr*/, + Dwarf_Unsigned /*code_len*/, + Dwarf_Unsigned /*sym_idx*/, + Dwarf_Unsigned /*sym_idx_of_end*/, + Dwarf_Addr /*offset_from_end_sym*/, + Dwarf_Error* /*error*/); + +Dwarf_Unsigned dwarf_add_frame_info_b( + Dwarf_P_Debug dbg /*dbg*/, + Dwarf_P_Fde /*fde*/, + Dwarf_P_Die /*die*/, + Dwarf_Unsigned /*cie*/, + Dwarf_Addr /*virt_addr*/, + Dwarf_Unsigned /*code_len*/, + Dwarf_Unsigned /*symidx*/, + Dwarf_Unsigned /*end_symbol */, + Dwarf_Addr /*offset_from_end_symbol */, + Dwarf_Signed /*offset_into_exception_tables*/, + Dwarf_Unsigned /*exception_table_symbol*/, + Dwarf_Error* /*error*/); + +Dwarf_Unsigned dwarf_add_frame_info( + Dwarf_P_Debug dbg /*dbg*/, + Dwarf_P_Fde /*fde*/, + Dwarf_P_Die /*die*/, + Dwarf_Unsigned /*cie*/, + Dwarf_Addr /*virt_addr*/, + Dwarf_Unsigned /*code_len*/, + Dwarf_Unsigned /*symidx*/, + Dwarf_Signed /*offset_into_exception_tables*/, + Dwarf_Unsigned /*exception_table_symbol*/, + Dwarf_Error* /*error*/); + +Dwarf_P_Fde dwarf_add_fde_inst( + Dwarf_P_Fde /*fde*/, + Dwarf_Small /*op*/, + Dwarf_Unsigned /*val1*/, + Dwarf_Unsigned /*val2*/, + Dwarf_Error* /*error*/); + +/* New September 17, 2009 */ +int dwarf_insert_fde_inst_bytes( + Dwarf_P_Debug /*dbg*/, + Dwarf_P_Fde /*fde*/, + Dwarf_Unsigned /*len*/, + Dwarf_Ptr /*ibytes*/, + Dwarf_Error* /*error*/); + + +Dwarf_P_Fde dwarf_new_fde(Dwarf_P_Debug /*dbg*/, Dwarf_Error* /*error*/); + +Dwarf_P_Fde dwarf_fde_cfa_offset( + Dwarf_P_Fde /*fde*/, + Dwarf_Unsigned /*register_number*/, + Dwarf_Signed /*offset*/, + Dwarf_Error* /*error*/); + +/* die creation & addition routines */ +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*/); + +Dwarf_Unsigned dwarf_add_die_to_debug( + Dwarf_P_Debug /*dbg*/, + Dwarf_P_Die /*die*/, + Dwarf_Error* /*error*/); + +/* Markers are not written to DWARF2/3/4, they are user + defined and may be used for any purpose. +*/ +Dwarf_Unsigned dwarf_add_die_marker( + Dwarf_P_Debug /*dbg*/, + Dwarf_P_Die /*die*/, + Dwarf_Unsigned /*marker*/, + Dwarf_Error * /*error*/); + +Dwarf_Unsigned dwarf_get_die_marker( + Dwarf_P_Debug /*dbg*/, + Dwarf_P_Die /*die*/, + Dwarf_Unsigned * /*marker*/, + Dwarf_Error * /*error*/); + +Dwarf_P_Die dwarf_die_link( + Dwarf_P_Die /*die*/, + Dwarf_P_Die /*parent*/, + Dwarf_P_Die /*child*/, + Dwarf_P_Die /*left*/, + Dwarf_P_Die /*right*/, + Dwarf_Error* /*error*/); + +void dwarf_dealloc_compressed_block( + Dwarf_P_Debug, + void * +); + +/* Call this passing in return value from dwarf_uncompress_integer_block() + * to free the space the decompression allocated. */ +void dwarf_dealloc_uncompressed_block( + Dwarf_Debug, + void * +); + +void * dwarf_compress_integer_block( + Dwarf_P_Debug, /* dbg */ + Dwarf_Bool, /* signed==true (or unsigned) */ + Dwarf_Small, /* size of integer units: 8, 16, 32, 64 */ + void*, /* data */ + Dwarf_Unsigned, /* number of elements */ + Dwarf_Unsigned*, /* number of bytes in output block */ + Dwarf_Error* /* error */ +); + +/* Decode an array of signed leb integers (so of course the + * array is not composed of fixed length values, but is instead + * a sequence of sleb values). + * Returns a DW_DLV_BADADDR on error. + * Otherwise returns a pointer to an array of 32bit integers. + * The signed argument must be non-zero (the decode + * assumes sleb integers in the input data) at this time. + * Size of integer units must be 32 (32 bits each) at this time. + * Number of bytes in block is a byte count (not array count). + * Returns number of units in output block (ie, number of elements + * of the array that the return value points to) thru the argument. + */ +void * dwarf_uncompress_integer_block( + Dwarf_Debug, /* dbg */ + Dwarf_Bool, /* signed==true (or unsigned) */ + Dwarf_Small, /* size of integer units: 8, 16, 32, 64 */ + void*, /* input data */ + Dwarf_Unsigned, /* number of bytes in input */ + Dwarf_Unsigned*, /* number of units in output block */ + Dwarf_Error* /* error */ +); + +/* Operations to create location expressions. */ +Dwarf_P_Expr dwarf_new_expr(Dwarf_P_Debug /*dbg*/, Dwarf_Error* /*error*/); + +void dwarf_expr_reset( + Dwarf_P_Expr /*expr*/, + Dwarf_Error* /*error*/); + +Dwarf_Unsigned dwarf_add_expr_gen( + Dwarf_P_Expr /*expr*/, + Dwarf_Small /*opcode*/, + Dwarf_Unsigned /*val1*/, + Dwarf_Unsigned /*val2*/, + Dwarf_Error* /*error*/); + +Dwarf_Unsigned dwarf_add_expr_addr( + Dwarf_P_Expr /*expr*/, + Dwarf_Unsigned /*addr*/, + Dwarf_Signed /*sym_index*/, + Dwarf_Error* /*error*/); + +Dwarf_Unsigned dwarf_add_expr_addr_b( + Dwarf_P_Expr /*expr*/, + Dwarf_Unsigned /*addr*/, + Dwarf_Unsigned /*sym_index*/, + Dwarf_Error* /*error*/); + +Dwarf_Unsigned dwarf_expr_current_offset( + Dwarf_P_Expr /*expr*/, + Dwarf_Error* /*error*/); + +Dwarf_Addr dwarf_expr_into_block( + Dwarf_P_Expr /*expr*/, + Dwarf_Unsigned* /*length*/, + Dwarf_Error* /*error*/); + +Dwarf_Unsigned dwarf_add_arange(Dwarf_P_Debug /*dbg*/, + Dwarf_Addr /*begin_address*/, + Dwarf_Unsigned /*length*/, + Dwarf_Signed /*symbol_index*/, + Dwarf_Error* /*error*/); + +Dwarf_Unsigned dwarf_add_arange_b( + Dwarf_P_Debug /*dbg*/, + Dwarf_Addr /*begin_address*/, + Dwarf_Unsigned /*length*/, + Dwarf_Unsigned /*symbol_index*/, + Dwarf_Unsigned /*end_symbol_index*/, + Dwarf_Addr /*offset_from_end_symbol*/, + Dwarf_Error * /*error*/); + +Dwarf_Unsigned dwarf_add_pubname( + Dwarf_P_Debug /*dbg*/, + Dwarf_P_Die /*die*/, + char* /*pubname_name*/, + Dwarf_Error* /*error*/); + +Dwarf_Unsigned dwarf_add_funcname( + Dwarf_P_Debug /*dbg*/, + Dwarf_P_Die /*die*/, + char* /*func_name*/, + Dwarf_Error* /*error*/); + +Dwarf_Unsigned dwarf_add_typename( + Dwarf_P_Debug /*dbg*/, + Dwarf_P_Die /*die*/, + char* /*type_name*/, + Dwarf_Error* /*error*/); + +Dwarf_Unsigned dwarf_add_varname( + Dwarf_P_Debug /*dbg*/, + Dwarf_P_Die /*die*/, + char* /*var_name*/, + Dwarf_Error* /*error*/); + +Dwarf_Unsigned dwarf_add_weakname( + Dwarf_P_Debug /*dbg*/, + Dwarf_P_Die /*die*/, + char* /*weak_name*/, + Dwarf_Error* /*error*/); + +/* .debug_macinfo producer functions + Functions must be called in right order: the section is output + In the order these are presented. +*/ +int dwarf_def_macro(Dwarf_P_Debug /*dbg*/, + Dwarf_Unsigned /*line*/, + char * /*macname, with (arglist), no space before (*/, + char * /*macvalue*/, + Dwarf_Error* /*error*/); + +int dwarf_undef_macro(Dwarf_P_Debug /*dbg*/, + Dwarf_Unsigned /*line*/, + char * /*macname, no arglist, of course*/, + Dwarf_Error* /*error*/); + +int dwarf_start_macro_file(Dwarf_P_Debug /*dbg*/, + Dwarf_Unsigned /*fileindex*/, + Dwarf_Unsigned /*linenumber*/, + Dwarf_Error* /*error*/); + +int dwarf_end_macro_file(Dwarf_P_Debug /*dbg*/, + Dwarf_Error* /*error*/); + +int dwarf_vendor_ext(Dwarf_P_Debug /*dbg*/, + Dwarf_Unsigned /*constant*/, + char * /*string*/, + Dwarf_Error* /*error*/); + +/* end macinfo producer functions */ + +int dwarf_attr_offset(Dwarf_Die /*die*/, + Dwarf_Attribute /*attr of above die*/, + Dwarf_Off * /*returns offset thru this ptr */, + Dwarf_Error * /*error*/); + +/* This is a hack so clients can verify offsets. + Added April 2005 so that debugger can detect broken offsets + (which happened in an IRIX executable larger than 2GB + with MIPSpro 7.3.1.3 toolchain.). +*/ +int +dwarf_get_section_max_offsets(Dwarf_Debug /*dbg*/, + Dwarf_Unsigned * /*debug_info_size*/, + Dwarf_Unsigned * /*debug_abbrev_size*/, + Dwarf_Unsigned * /*debug_line_size*/, + Dwarf_Unsigned * /*debug_loc_size*/, + Dwarf_Unsigned * /*debug_aranges_size*/, + Dwarf_Unsigned * /*debug_macinfo_size*/, + Dwarf_Unsigned * /*debug_pubnames_size*/, + Dwarf_Unsigned * /*debug_str_size*/, + Dwarf_Unsigned * /*debug_frame_size*/, + Dwarf_Unsigned * /*debug_ranges_size*/, + Dwarf_Unsigned * /*debug_pubtypes_size*/); + +/* Multiple releases spelled 'initial' as 'inital' . + The 'inital' spelling should not be used. */ +Dwarf_Half dwarf_set_frame_rule_inital_value(Dwarf_Debug /*dbg*/, + Dwarf_Half /*value*/); +/* Additional interface with correct 'initial' spelling. */ +/* It is likely you will want to call the following 5 functions + before accessing any frame information. All are useful + to tailor handling of pseudo-registers needed to turn + frame operation references into simpler forms and to + reflect ABI specific data. Of course altering libdwarf.h + and dwarf.h allow the same capabilities, but such header changes + do not let one change these values at runtime. */ +Dwarf_Half dwarf_set_frame_rule_initial_value(Dwarf_Debug /*dbg*/, + Dwarf_Half /*value*/); +Dwarf_Half dwarf_set_frame_rule_table_size(Dwarf_Debug /*dbg*/, + Dwarf_Half /*value*/); +Dwarf_Half dwarf_set_frame_cfa_value(Dwarf_Debug /*dbg*/, + Dwarf_Half /*value*/); +Dwarf_Half dwarf_set_frame_same_value(Dwarf_Debug /*dbg*/, + Dwarf_Half /*value*/); +Dwarf_Half dwarf_set_frame_undefined_value(Dwarf_Debug /*dbg*/, + Dwarf_Half /*value*/); + +/* As of April 27, 2009, this version with no diepointer is + obsolete though supported. Use dwarf_get_ranges_a() instead. */ +int dwarf_get_ranges(Dwarf_Debug /*dbg*/, + Dwarf_Off /*rangesoffset*/, + Dwarf_Ranges ** /*rangesbuf*/, + Dwarf_Signed * /*listlen*/, + Dwarf_Unsigned * /*bytecount*/, + Dwarf_Error * /*error*/); + +/* This adds the address_size argument. New April 27, 2009 */ +int dwarf_get_ranges_a(Dwarf_Debug /*dbg*/, + Dwarf_Off /*rangesoffset*/, + Dwarf_Die /* diepointer */, + Dwarf_Ranges ** /*rangesbuf*/, + Dwarf_Signed * /*listlen*/, + Dwarf_Unsigned * /*bytecount*/, + Dwarf_Error * /*error*/); + +void dwarf_ranges_dealloc(Dwarf_Debug /*dbg*/, + Dwarf_Ranges * /*rangesbuf*/, + Dwarf_Signed /*rangecount*/); + +/* The harmless error list is a circular buffer of + errors we note but which do not stop us from processing + the object. Created so dwarfdump or other tools + can report such inconsequential errors without causing + anything to stop early. */ +#define DW_HARMLESS_ERROR_CIRCULAR_LIST_DEFAULT_SIZE 4 +#define DW_HARMLESS_ERROR_MSG_STRING_SIZE 200 +/* User code supplies size of array of pointers errmsg_ptrs_array + in count and the array of pointers (the pointers themselves + need not be initialized). + The pointers returned in the array of pointers + are invalidated by ANY call to libdwarf. + Use them before making another libdwarf call! + The array of string pointers passed in always has + a final null pointer, so if there are N pointers the + and M actual strings, then MIN(M,N-1) pointers are + set to point to error strings. The array of pointers + to strings always terminates with a NULL pointer. + If 'count' is passed in zero then errmsg_ptrs_array + is not touched. + + The function returns DW_DLV_NO_ENTRY if no harmless errors + were noted so far. Returns DW_DLV_OK if there are errors. + Never returns DW_DLV_ERROR. + + Each call empties the error list (discarding all current entries). + If newerr_count is non-NULL the count of harmless errors + since the last call is returned through the pointer + (some may have been discarded or not returned, it is a circular + list...). + If DW_DLV_NO_ENTRY is returned none of the arguments + here are touched or used. + */ +int dwarf_get_harmless_error_list(Dwarf_Debug /*dbg*/, + unsigned /*count*/, + const char ** /*errmsg_ptrs_array*/, + unsigned * /*newerr_count*/); + +/* Insertion is only for testing the harmless error code, it is not + necessarily useful otherwise. */ +void dwarf_insert_harmless_error(Dwarf_Debug /*dbg*/, + char * /*newerror*/); + +/* The size of the circular list of strings may be set + and reset as needed. If it is shortened excess + messages are simply dropped. It returns the previous + size. If zero passed in the size is unchanged + and it simply returns the current size */ +unsigned dwarf_set_harmless_error_list_size(Dwarf_Debug /*dbg*/, + unsigned /*maxcount*/); +/* The harmless error strings (if any) are freed when the dbg + is dwarf_finish()ed. */ + +/* When the val_in is known these dwarf_get_TAG_name (etc) + functions return the string corresponding to the val_in passed in + through the pointer s_out and the value returned is DW_DLV_OK. + The strings are in static storage + and must not be freed. + If DW_DLV_NO_ENTRY is returned the val_in is not known and + *s_out is not set. DW_DLV_ERROR is never returned.*/ + +extern int dwarf_get_TAG_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_children_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_FORM_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_AT_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_OP_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_ATE_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_DS_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_END_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_ATCF_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_ACCESS_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_VIS_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_VIRTUALITY_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_LANG_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_ID_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_CC_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_INL_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_ORD_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_DSC_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_LNS_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_LNE_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_MACINFO_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_CFA_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_EH_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_FRAME_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_CHILDREN_name(unsigned int /*val_in*/, const char ** /*s_out */); +extern int dwarf_get_ADDR_name(unsigned int /*val_in*/, const char ** /*s_out */); + +#ifdef __cplusplus +} +#endif +#endif /* _LIBDWARF_H */ + + diff --git a/usr/src/lib/libdwarf/common/libdwarfdefs.h b/usr/src/lib/libdwarf/common/libdwarfdefs.h new file mode 100644 index 0000000000..a564655b23 --- /dev/null +++ b/usr/src/lib/libdwarf/common/libdwarfdefs.h @@ -0,0 +1,91 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + +/* libdwarfdefs.h +*/ + +#ifndef LIBDWARFDEFS_H +#define LIBDWARFDEFS_H + +/* We want __uint32_t and __uint64_t and __int32_t __int64_t + properly defined but not duplicated, since duplicate typedefs + are not legal C. +*/ +/* + HAVE___UINT32_T + HAVE___UINT64_T will be set by configure if + our 4 types are predefined in compiler +*/ + + +#if (!defined(HAVE___UINT32_T)) && defined(HAVE___UINT32_T_IN_SGIDEFS_H) +#include /* sgidefs.h defines them */ +#define HAVE___UINT32_T 1 +#endif + +#if (!defined(HAVE___UINT64_T)) && defined(HAVE___UINT64_T_IN_SGIDEFS_H) +#include /* sgidefs.h defines them */ +#define HAVE___UINT64_T 1 +#endif + + +#if (!defined(HAVE___UINT32_T)) && \ + defined(HAVE_SYS_TYPES_H) && \ + defined(HAVE___UINT32_T_IN_SYS_TYPES_H) +# include +#define HAVE___UINT32_T 1 +#endif + +#if (!defined(HAVE___UINT64_T)) && \ + defined(HAVE_SYS_TYPES_H) && \ + defined(HAVE___UINT64_T_IN_SYS_TYPES_H) +# include +#define HAVE___UINT64_T 1 +#endif + +#ifndef HAVE___UINT32_T +typedef int __int32_t; +typedef unsigned __uint32_t; +#define HAVE___UINT32_T 1 +#endif + +#ifndef HAVE___UINT64_T +typedef long long __int64_t; +typedef unsigned long long __uint64_t; +#define HAVE___UINT64_T 1 +#endif + +#endif /* LIBDWARFDEFS_H */ diff --git a/usr/src/lib/libdwarf/common/malloc_check.c b/usr/src/lib/libdwarf/common/malloc_check.c new file mode 100644 index 0000000000..1c6e7738e4 --- /dev/null +++ b/usr/src/lib/libdwarf/common/malloc_check.c @@ -0,0 +1,339 @@ +/* + + Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +/* malloc_check.c For checking dealloc completeness. + + This code is as simple as possible and works ok for + reasonable size allocation counts. + + It treats allocation as global, and so will not + work very well if an application opens more than one + Dwarf_Debug. + +*/ + +#include +#include /* for exit() and various malloc + prototypes */ +#include "config.h" +#include "dwarf_incl.h" +#include "malloc_check.h" +#ifdef WANT_LIBBDWARF_MALLOC_CHECK + +/* To turn off printing every entry, just change the define + to set PRINT_MALLOC_DETAILS 0. +*/ +#define PRINT_MALLOC_DETAILS 0 + +#define MC_TYPE_UNKNOWN 0 +#define MC_TYPE_ALLOC 1 +#define MC_TYPE_DEALLOC 2 + +struct mc_data_s { + struct mc_data_s *mc_prev; + unsigned long mc_address; /* Assumes this is large enough to hold + a pointer! */ + + long mc_alloc_number; /* Assigned in order by when record + created. */ + unsigned char mc_alloc_code; /* Allocation code, libdwarf. */ + unsigned char mc_type; + unsigned char mc_dealloc_noted; /* Used on an ALLOC node. */ + unsigned char mc_dealloc_noted_count; /* Used on an ALLOC + node. */ +}; + +/* + + +*/ +#define HASH_TABLE_SIZE 10501 +static struct mc_data_s *mc_data_hash[HASH_TABLE_SIZE]; +static long mc_data_list_size = 0; + +static char *alloc_type_name[MAX_DW_DLA + 1] = { + "", + "DW_DLA_STRING", + "DW_DLA_LOC", + "DW_DLA_LOCDESC", + "DW_DLA_ELLIST", + "DW_DLA_BOUNDS", + "DW_DLA_BLOCK", + "DW_DLA_DEBUG", + "DW_DLA_DIE", + "DW_DLA_LINE", + "DW_DLA_ATTR", + "DW_DLA_TYPE", + "DW_DLA_SUBSCR", + "DW_DLA_GLOBAL", + "DW_DLA_ERROR", + "DW_DLA_LIST", + "DW_DLA_LINEBUF", + "DW_DLA_ARANGE", + "DW_DLA_ABBREV", + "DW_DLA_FRAME_OP", + "DW_DLA_CIE", + "DW_DLA_FDE", + "DW_DLA_LOC_BLOCK", + "DW_DLA_FRAME_BLOCK", + "DW_DLA_FUNC", + "DW_DLA_TYPENAME", + "DW_DLA_VAR", + "DW_DLA_WEAK", + "DW_DLA_ADDR", + "DW_DLA_ABBREV_LIST", + "DW_DLA_CHAIN", + "DW_DLA_CU_CONTEXT", + "DW_DLA_FRAME", + "DW_DLA_GLOBAL_CONTEXT", + "DW_DLA_FILE_ENTRY", + "DW_DLA_LINE_CONTEXT", + "DW_DLA_LOC_CHAIN", + "DW_DLA_HASH_TABLE", + "DW_DLA_FUNC_CONTEXT", + "DW_DLA_TYPENAME_CONTEXT", + "DW_DLA_VAR_CONTEXT", + "DW_DLA_WEAK_CONTEXT", + "DW_DLA_PUBTYPES_CONTEXT" + /* Don't forget to expand this list if the list of codes + expands. */ +}; + +static unsigned +hash_address(unsigned long addr) +{ + unsigned long a = addr >> 2; + + return a % HASH_TABLE_SIZE; +} + +#if PRINT_MALLOC_DETAILS +static void +print_alloc_dealloc_detail(unsigned long addr, + int code, char *whichisit) +{ + fprintf(stderr, + "%s addr 0x%lx code %d (%s) entry %ld\n", + whichisit, addr, code, alloc_type_name[code], + mc_data_list_size); +} +#else +#define print_alloc_dealloc_detail(a,b,c) /* nothing */ +#endif + +/* Create a zeroed struct or die. */ +static void * +newone(void) +{ + struct mc_data_s *newd = malloc(sizeof(struct mc_data_s)); + + if (newd == 0) { + fprintf(stderr, "out of memory , # %ld\n", mc_data_list_size); + exit(1); + } + memset(newd, 0, sizeof(struct mc_data_s)); + return newd; +} + +/* Notify checker that get_alloc has allocated user data. */ +void +dwarf_malloc_check_alloc_data(void *addr_in, unsigned char code) +{ + struct mc_data_s *newd = newone(); + unsigned long addr = (unsigned long) addr_in; + struct mc_data_s **base = &mc_data_hash[hash_address(addr)]; + + print_alloc_dealloc_detail(addr, code, "alloc "); + newd->mc_address = addr; + newd->mc_alloc_code = code; + newd->mc_type = MC_TYPE_ALLOC; + newd->mc_alloc_number = mc_data_list_size; + newd->mc_prev = *base; + *base = newd; + newd->mc_alloc_number = mc_data_list_size; + mc_data_list_size += 1; +} + +static void +print_entry(char *msg, struct mc_data_s *data) +{ + fprintf(stderr, + "%s: 0x%08lx code %2d (%s) type %s dealloc noted %u ct %u\n", + msg, + (long) data->mc_address, + data->mc_alloc_code, + alloc_type_name[data->mc_alloc_code], + (data->mc_type == MC_TYPE_ALLOC) ? "alloc " : + (data->mc_type == MC_TYPE_DEALLOC) ? "dealloc" : "unknown", + (unsigned) data->mc_dealloc_noted, + (unsigned) data->mc_dealloc_noted_count); +} + +/* newd is a 'dealloc'. +*/ +static long +balanced_by_alloc_p(struct mc_data_s *newd, + long *addr_match_num, + struct mc_data_s **addr_match, + struct mc_data_s *base) +{ + struct mc_data_s *cur = base; + + for (; cur; cur = cur->mc_prev) { + if (cur->mc_address == newd->mc_address) { + if (cur->mc_type == MC_TYPE_ALLOC) { + if (cur->mc_alloc_code == newd->mc_alloc_code) { + *addr_match = cur; + *addr_match_num = cur->mc_alloc_number; + return cur->mc_alloc_number; + } else { + /* code mismatch */ + *addr_match = cur; + *addr_match_num = cur->mc_alloc_number; + return -1; + } + } else { + /* Unbalanced new/del */ + *addr_match = cur; + *addr_match_num = cur->mc_alloc_number; + return -1; + } + } + } + return -1; +} + +/* A dealloc is to take place. Ensure it balances an alloc. +*/ +void +dwarf_malloc_check_dealloc_data(void *addr_in, unsigned char code) +{ + struct mc_data_s *newd = newone(); + long prev; + long addr_match_num = -1; + struct mc_data_s *addr_match = 0; + unsigned long addr = (unsigned long) addr_in; + struct mc_data_s **base = &mc_data_hash[hash_address(addr)]; + + + print_alloc_dealloc_detail(addr, code, "dealloc "); + newd->mc_address = (unsigned long) addr; + newd->mc_alloc_code = code; + newd->mc_type = MC_TYPE_DEALLOC; + newd->mc_prev = *base; + prev = + balanced_by_alloc_p(newd, &addr_match_num, &addr_match, *base); + if (prev < 0) { + fprintf(stderr, + "Unbalanced dealloc at index %ld\n", mc_data_list_size); + print_entry("new", newd); + fprintf(stderr, "addr-match_num? %ld\n", addr_match_num); + if (addr_match) { + print_entry("prev entry", addr_match); + if (addr_match->mc_dealloc_noted > 1) { + fprintf(stderr, "Above is Duplicate dealloc!\n"); + } + } + abort(); + exit(3); + } + addr_match->mc_dealloc_noted = 1; + addr_match->mc_dealloc_noted_count += 1; + if (addr_match->mc_dealloc_noted_count > 1) { + fprintf(stderr, "Double dealloc entry %ld\n", addr_match_num); + print_entry("new dealloc entry", newd); + print_entry("bad alloc entry", addr_match); + } + *base = newd; + mc_data_list_size += 1; +} + +/* Final check for leaks. +*/ +void +dwarf_malloc_check_complete(char *msg) +{ + long i = 0; + long total = mc_data_list_size; + long hash_slots_used = 0; + long max_chain_length = 0; + + fprintf(stderr, "Run complete, %s. %ld entries\n", msg, total); + for (; i < HASH_TABLE_SIZE; ++i) { + struct mc_data_s *cur = mc_data_hash[i]; + long cur_chain_length = 0; + + if (cur == 0) + continue; + ++hash_slots_used; + for (; cur; cur = cur->mc_prev) { + ++cur_chain_length; + if (cur->mc_type == MC_TYPE_ALLOC) { + if (cur->mc_dealloc_noted) { + if (cur->mc_dealloc_noted > 1) { + fprintf(stderr, + " Duplicate dealloc! entry %ld\n", + cur->mc_alloc_number); + print_entry("duplicate dealloc", cur); + + } + continue; + } else { + fprintf(stderr, "malloc no dealloc, entry %ld\n", + cur->mc_alloc_number); + print_entry("dangle", cur); + } + } else { + /* mc_type is MC_TYPE_DEALLOC, already checked */ + + } + } + if (cur_chain_length > max_chain_length) { + max_chain_length = cur_chain_length; + } + } + fprintf(stderr, "mc hash table slots=%ld, " + "used=%ld, maxchain=%ld\n", + (long) HASH_TABLE_SIZE, hash_slots_used, max_chain_length); + return; +} + +#else + +extern void *libdwarf_an_unused_function_so_not_empty_c_file(); + +#endif /* WANT_LIBBDWARF_MALLOC_CHECK */ diff --git a/usr/src/lib/libdwarf/common/malloc_check.h b/usr/src/lib/libdwarf/common/malloc_check.h new file mode 100644 index 0000000000..ba1ad3da71 --- /dev/null +++ b/usr/src/lib/libdwarf/common/malloc_check.h @@ -0,0 +1,62 @@ +/* + + Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved. + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + +/* malloc_check.h */ + +/* A simple libdwarf-aware malloc checker. + define WANT_LIBBDWARF_MALLOC_CHECK and rebuild libdwarf + do make a checking-for-alloc-mistakes libdwarf. + NOT recommended for production use. + + When defined, also add malloc_check.c to the list of + files in Makefile. +*/ + +#undef WANT_LIBBDWARF_MALLOC_CHECK +/*#define WANT_LIBBDWARF_MALLOC_CHECK 1 */ + +#ifdef WANT_LIBBDWARF_MALLOC_CHECK + +void dwarf_malloc_check_alloc_data(void * addr,unsigned char code); +void dwarf_malloc_check_dealloc_data(void * addr,unsigned char code); +void dwarf_malloc_check_complete(char *wheremsg); /* called at exit of app */ + +#else /* !WANT_LIBBDWARF_MALLOC_CHECK */ + +#define dwarf_malloc_check_alloc_data(a,b) /* nothing */ +#define dwarf_malloc_check_dealloc_data(a,b) /* nothing */ +#define dwarf_malloc_check_complete(a) /* nothing */ + +#endif /* WANT_LIBBDWARF_MALLOC_CHECK */ diff --git a/usr/src/lib/libdwarf/common/mapfile-vers b/usr/src/lib/libdwarf/common/mapfile-vers new file mode 100644 index 0000000000..c1a652a591 --- /dev/null +++ b/usr/src/lib/libdwarf/common/mapfile-vers @@ -0,0 +1,302 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2011, Richard Lowe. +# + +# +# MAPFILE HEADER START +# +# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. +# Object versioning must comply with the rules detailed in +# +# usr/src/lib/README.mapfiles +# +# You should not be making modifications here until you've read the most current +# copy of that file. If you need help, contact a gatekeeper for guidance. +# +# MAPFILE HEADER END +# + +$mapfile_version 2 + +SYMBOL_VERSION ILLUMOSprivate_1.1 { + global: + dwarf_add_arange; + dwarf_add_arange_b; + dwarf_add_AT_block; + dwarf_add_AT_comp_dir; + dwarf_add_AT_const_value_signedint; + dwarf_add_AT_const_value_string; + dwarf_add_AT_const_value_unsignedint; + dwarf_add_AT_dataref; + dwarf_add_AT_flag; + dwarf_add_AT_location_expr; + dwarf_add_AT_name; + dwarf_add_AT_producer; + dwarf_add_AT_ref_address; + dwarf_add_AT_reference; + dwarf_add_AT_signed_const; + dwarf_add_AT_string; + dwarf_add_AT_targ_address; + dwarf_add_AT_targ_address_b; + dwarf_add_AT_unsigned_const; + dwarf_add_die_marker; + dwarf_add_die_to_debug; + dwarf_add_directory_decl; + dwarf_add_expr_addr; + dwarf_add_expr_addr_b; + dwarf_add_expr_gen; + dwarf_add_fde_inst; + dwarf_add_file_decl; + dwarf_add_frame_cie; + dwarf_add_frame_fde; + dwarf_add_frame_fde_b; + dwarf_add_frame_info; + dwarf_add_frame_info_b; + dwarf_add_funcname; + dwarf_add_line_entry; + dwarf_add_pubname; + dwarf_add_typename; + dwarf_add_varname; + dwarf_add_weakname; + dwarf_arrayorder; + dwarf_attr; + dwarf_attr_offset; + dwarf_attrlist; + dwarf_bitoffset; + dwarf_bitsize; + dwarf_bytesize; + dwarf_check_lineheader; + dwarf_child; + dwarf_cie_section_offset; + dwarf_compress_integer_block; + dwarf_create_cie_from_after_start; + dwarf_create_fde_from_after_start; + dwarf_CU_dieoffset_given_die; + dwarf_dealloc; + dwarf_dealloc_compressed_block; + dwarf_dealloc_uncompressed_block; + dwarf_def_macro; + dwarf_die_abbrev_code; + dwarf_die_CU_offset; + dwarf_die_CU_offset_range; + dwarf_die_link; + dwarf_diename; + dwarf_dieoffset; + dwarf_elf_init; + dwarf_elf_object_access_finish; + dwarf_elf_object_access_init; + dwarf_end_macro_file; + dwarf_errmsg; + dwarf_errno; + dwarf_expand_frame_instructions; + dwarf_expr_current_offset; + dwarf_expr_into_block; + dwarf_expr_reset; + dwarf_fde_cfa_offset; + dwarf_fde_cie_list_dealloc; + dwarf_fde_section_offset; + dwarf_find_macro_value_start; + dwarf_finish; + dwarf_formaddr; + dwarf_formblock; + dwarf_formexprloc; + dwarf_formflag; + dwarf_formref; + dwarf_formsdata; + dwarf_formsig8; + dwarf_formstring; + dwarf_formudata; + dwarf_free_line_table_prefix; + dwarf_func_cu_offset; + dwarf_func_die_offset; + dwarf_func_name_offsets; + dwarf_funcname; + dwarf_funcs_dealloc; + dwarf_get_abbrev; + dwarf_get_abbrev_children_flag; + dwarf_get_abbrev_code; + dwarf_get_abbrev_entry; + dwarf_get_abbrev_tag; + dwarf_get_ACCESS_name; + dwarf_get_ADDR_name; + dwarf_get_address_size; + dwarf_get_arange; + dwarf_get_arange_cu_header_offset; + dwarf_get_arange_info; + dwarf_get_arange_info_b; + dwarf_get_aranges; + dwarf_get_AT_name; + dwarf_get_ATCF_name; + dwarf_get_ATE_name; + dwarf_get_CC_name; + dwarf_get_CFA_name; + dwarf_get_children_name; + dwarf_get_CHILDREN_name; + dwarf_get_cie_augmentation_data; + dwarf_get_cie_index; + dwarf_get_cie_info; + dwarf_get_cie_of_fde; + dwarf_get_cu_die_offset; + dwarf_get_cu_die_offset_given_cu_header_offset; + dwarf_get_die_address_size; + dwarf_get_die_marker; + dwarf_get_die_markers; + dwarf_get_DS_name; + dwarf_get_DSC_name; + dwarf_get_EH_name; + dwarf_get_elf; + dwarf_get_END_name; + dwarf_get_fde_at_pc; + dwarf_get_fde_augmentation_data; + dwarf_get_fde_exception_info; + dwarf_get_fde_for_die; + dwarf_get_fde_info_for_all_regs; + dwarf_get_fde_info_for_all_regs3; + dwarf_get_fde_info_for_cfa_reg3; + dwarf_get_fde_info_for_reg; + dwarf_get_fde_info_for_reg3; + dwarf_get_fde_instr_bytes; + dwarf_get_fde_list; + dwarf_get_fde_list_eh; + dwarf_get_fde_n; + dwarf_get_fde_range; + dwarf_get_form_class; + dwarf_get_FORM_name; + dwarf_get_FRAME_name; + dwarf_get_funcs; + dwarf_get_globals; + dwarf_get_harmless_error_list; + dwarf_get_ID_name; + dwarf_get_INL_name; + dwarf_get_ISA_name; + dwarf_get_LANG_name; + dwarf_get_LNE_name; + dwarf_get_LNS_name; + dwarf_get_loclist_entry; + dwarf_get_MACINFO_name; + dwarf_get_macro_details; + dwarf_get_OP_name; + dwarf_get_ORD_name; + dwarf_get_pubtypes; + dwarf_get_ranges; + dwarf_get_ranges_a; + dwarf_get_relocation_info; + dwarf_get_relocation_info_count; + dwarf_get_section_bytes; + dwarf_get_section_max_offsets; + dwarf_get_str; + dwarf_get_string_attributes_count; + dwarf_get_string_attributes_info; + dwarf_get_TAG_name; + dwarf_get_types; + dwarf_get_vars; + dwarf_get_VIRTUALITY_name; + dwarf_get_VIS_name; + dwarf_get_weaks; + dwarf_global_cu_offset; + dwarf_global_die_offset; + dwarf_global_formref; + dwarf_global_name_offsets; + dwarf_globals_dealloc; + dwarf_globname; + dwarf_harmless_cleanout; + dwarf_harmless_init; + dwarf_hasattr; + dwarf_hasform; + dwarf_highpc; + dwarf_init; + dwarf_init_line_table_prefix; + dwarf_insert_fde_inst_bytes; + dwarf_insert_harmless_error; + dwarf_ld_sort_lines; + dwarf_line_srcfileno; + dwarf_lineaddr; + dwarf_linebeginstatement; + dwarf_lineblock; + dwarf_lineendsequence; + dwarf_lineno; + dwarf_lineoff; + dwarf_linesrc; + dwarf_lne_end_sequence; + dwarf_lne_set_address; + dwarf_loclist; + dwarf_loclist_from_expr; + dwarf_loclist_from_expr_a; + dwarf_loclist_n; + dwarf_lowpc; + dwarf_new_die; + dwarf_new_expr; + dwarf_new_fde; + dwarf_next_cu_header; + dwarf_next_cu_header_b; + dwarf_nextglob; + dwarf_object_finish; + dwarf_object_init; + dwarf_offdie; + dwarf_p_dealloc; + dwarf_print_lines; + dwarf_print_memory_stats; + dwarf_producer_finish; + dwarf_producer_init; + dwarf_producer_init_b; + dwarf_pubtype_cu_offset; + dwarf_pubtype_name_offsets; + dwarf_pubtype_type_die_offset; + dwarf_pubtypename; + dwarf_pubtypes_dealloc; + dwarf_ranges_dealloc; + dwarf_read_cie_fde_prefix; + dwarf_read_line_table_prefix; + dwarf_reset_section_bytes; + dwarf_set_frame_cfa_value; + dwarf_set_frame_rule_inital_value; + dwarf_set_frame_rule_initial_value; + dwarf_set_frame_rule_table_size; + dwarf_set_frame_same_value; + dwarf_set_frame_undefined_value; + dwarf_set_harmless_error_list_size; + dwarf_set_reloc_application; + dwarf_set_stringcheck; + dwarf_siblingof; + dwarf_srcfiles; + dwarf_srclang; + dwarf_srclines; + dwarf_srclines_dealloc; + dwarf_start_macro_file; + dwarf_tag; + dwarf_transform_to_disk_form; + dwarf_type_cu_offset; + dwarf_type_die_offset; + dwarf_type_name_offsets; + dwarf_typename; + dwarf_types_dealloc; + dwarf_uncompress_integer_block; + dwarf_undef_macro; + dwarf_var_cu_offset; + dwarf_var_die_offset; + dwarf_var_name_offsets; + dwarf_varname; + dwarf_vars_dealloc; + dwarf_vendor_ext; + dwarf_weak_cu_offset; + dwarf_weak_die_offset; + dwarf_weak_name_offsets; + dwarf_weakname; + dwarf_weaks_dealloc; + dwarf_whatattr; + dwarf_whatform; + dwarf_whatform_direct; + local: + *; +}; diff --git a/usr/src/lib/libdwarf/common/pro_alloc.c b/usr/src/lib/libdwarf/common/pro_alloc.c new file mode 100644 index 0000000000..1ca7806239 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_alloc.c @@ -0,0 +1,188 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "pro_incl.h" +#ifdef HAVE_STDLIB_H +#include +#endif /* HAVE_STDLIB_H */ +#ifdef HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ +#include + +/* + When each block is allocated, there is a two-word structure + allocated at the beginning so the block can go on a list. + The address returned is the address *after* the two pointers + at the start. But this allows us to be given a pointer to + a generic block, and go backwards to find the list-node. Then + we can remove this block from it's list without the need to search + through a linked list in order to remove the node. It also allows + us to 'delete' a memory block without needing the dbg structure. + We still need the dbg structure on allocation so that we know which + linked list to add the block to. + + Only the allocation of the dbg structure itself cannot use _dwarf_p_get_alloc. + That structure should be set up by hand, and the two list pointers + should be initialized to point at the node itself. That initializes + the doubly linked list. +*/ + +#define LIST_TO_BLOCK(lst) ((void*) (((char *)lst) + sizeof(memory_list_t))) +#define BLOCK_TO_LIST(blk) ((memory_list_t*) (((char*)blk) - sizeof(memory_list_t))) + + +/* + dbg should be NULL only when allocating dbg itself. In that + case we initialize it to an empty circular doubly-linked list. +*/ + +Dwarf_Ptr +_dwarf_p_get_alloc(Dwarf_P_Debug dbg, Dwarf_Unsigned size) +{ + void *sp; + memory_list_t *lp = NULL; + memory_list_t *dbglp = NULL; + memory_list_t *nextblock = NULL; + + /* alloc control struct and data block together for performance reasons */ + lp = (memory_list_t *) malloc(size + sizeof(memory_list_t)); + if (lp == NULL) { + /* should throw an error */ + return NULL; + } + + /* point to 'size' bytes just beyond lp struct */ + sp = LIST_TO_BLOCK(lp); + memset(sp, 0, size); + + if (dbg == NULL) { + lp->next = lp->prev = lp; + } else { + /* I always have to draw a picture to understand this part. */ + + dbglp = BLOCK_TO_LIST(dbg); + nextblock = dbglp->next; + + /* Insert between dbglp and nextblock */ + dbglp->next = lp; + lp->prev = dbglp; + lp->next = nextblock; + nextblock->prev = lp; + } + + return sp; +} + +/* + This routine is only here in case a caller of an older version of the + library is calling this for some reason. + We will clean up any stray blocks when the session is closed. + No need to remove this block. In theory the user might be + depending on the fact that we used to just 'free' this. + In theory they might also be + passing a block that they got from libdwarf. So we don't know if we + should try to remove this block from our global list. Safest just to + do nothing at this point. + + !!! + This function is deprecated! Don't call it inside libdwarf or outside of it. + !!! +*/ + +void +dwarf_p_dealloc(Dwarf_Small * ptr) +{ + return; +} + +/* + The dbg structure is not needed here anymore. +*/ + +void +_dwarf_p_dealloc(Dwarf_P_Debug dbg, Dwarf_Small * ptr) /* ARGSUSED */ +{ + memory_list_t *lp; + lp = BLOCK_TO_LIST(ptr); + + /* + Remove from a doubly linked, circular list. + Read carefully, use a white board if necessary. + If this is an empty list, the following statements are no-ops, and + will write to the same memory location they read from. + This should only happen when we deallocate the dbg structure itself. + */ + + lp->prev->next = lp->next; + lp->next->prev = lp->prev; + + free((void*)lp); +} + + +/* + This routine deallocates all the nodes on the dbg list, + and then deallocates the dbg structure itself. +*/ + +void +_dwarf_p_dealloc_all(Dwarf_P_Debug dbg) +{ + memory_list_t *dbglp; + + if (dbg == NULL) { + /* should throw an error */ + return; + } + + dbglp = BLOCK_TO_LIST(dbg); + while (dbglp->next != dbglp) { + _dwarf_p_dealloc(dbg, LIST_TO_BLOCK(dbglp->next)); + } + if (dbglp->next != dbglp || + dbglp->prev != dbglp) { + + /* should throw error */ + /* For some reason we couldn't free all the blocks? */ + return; + } + _dwarf_p_dealloc(NULL, (void*)dbg); +} + diff --git a/usr/src/lib/libdwarf/common/pro_alloc.h b/usr/src/lib/libdwarf/common/pro_alloc.h new file mode 100644 index 0000000000..b4da65325f --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_alloc.h @@ -0,0 +1,42 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +Dwarf_Ptr _dwarf_p_get_alloc(Dwarf_P_Debug, Dwarf_Unsigned); + +void _dwarf_p_dealloc(Dwarf_P_Debug dbg, Dwarf_Small * ptr); + +void _dwarf_p_dealloc_all(Dwarf_P_Debug dbg); diff --git a/usr/src/lib/libdwarf/common/pro_arange.c b/usr/src/lib/libdwarf/common/pro_arange.c new file mode 100644 index 0000000000..4e5c37795c --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_arange.c @@ -0,0 +1,337 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include +#include +#ifdef HAVE_ELFACCESS_H +#include +#endif +#include "pro_incl.h" +#include "pro_arange.h" +#include "pro_section.h" +#include "pro_reloc.h" + + + +/* + This function adds another address range + to the list of address ranges for the + given Dwarf_P_Debug. It returns 0 on error, + and 1 otherwise. +*/ +Dwarf_Unsigned +dwarf_add_arange(Dwarf_P_Debug dbg, + Dwarf_Addr begin_address, + Dwarf_Unsigned length, + Dwarf_Signed symbol_index, Dwarf_Error * error) +{ + return dwarf_add_arange_b(dbg, begin_address, length, symbol_index, + /* end_symbol_index */ 0, + /* offset_from_end_sym */ 0, + error); +} + +/* + This function adds another address range + to the list of address ranges for the + given Dwarf_P_Debug. It returns 0 on error, + and 1 otherwise. +*/ +Dwarf_Unsigned +dwarf_add_arange_b(Dwarf_P_Debug dbg, + Dwarf_Addr begin_address, + Dwarf_Unsigned length, + Dwarf_Unsigned symbol_index, + Dwarf_Unsigned end_symbol_index, + Dwarf_Addr offset_from_end_sym, Dwarf_Error * error) +{ + Dwarf_P_Arange arange; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return (0); + } + + arange = (Dwarf_P_Arange) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Arange_s)); + if (arange == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (0); + } + + arange->ag_begin_address = begin_address; + arange->ag_length = length; + arange->ag_symbol_index = symbol_index; + arange->ag_end_symbol_index = end_symbol_index; + arange->ag_end_symbol_offset = offset_from_end_sym; + + if (dbg->de_arange == NULL) + dbg->de_arange = dbg->de_last_arange = arange; + else { + dbg->de_last_arange->ag_next = arange; + dbg->de_last_arange = arange; + } + dbg->de_arange_count++; + + return (1); +} + + +int +_dwarf_transform_arange_to_disk(Dwarf_P_Debug dbg, Dwarf_Error * error) +{ + /* Total num of bytes in .debug_aranges section. */ + Dwarf_Unsigned arange_num_bytes; + + /* + Adjustment to align the start of the actual address ranges on a + boundary aligned with twice the address size. */ + Dwarf_Small remainder; + + /* Total number of bytes excluding the length field. */ + Dwarf_Unsigned adjusted_length; + + /* Points to first byte of .debug_aranges buffer. */ + Dwarf_Small *arange; + + /* Fills in the .debug_aranges buffer. */ + Dwarf_Small *arange_ptr; + + /* Scans the list of address ranges provided by user. */ + Dwarf_P_Arange given_arange; + + /* Used to fill in 0. */ + const Dwarf_Signed big_zero = 0; + + int extension_word_size = dbg->de_64bit_extension ? 4 : 0; + int uword_size = dbg->de_offset_size; + int upointer_size = dbg->de_pointer_size; + int res; + + + /* ***** BEGIN CODE ***** */ + + /* Size of the .debug_aranges section header. */ + arange_num_bytes = extension_word_size + uword_size + /* Size + of + length + field. + */ + sizeof(Dwarf_Half) + /* Size of version field. */ + uword_size + /* Size of .debug_info offset. */ + sizeof(Dwarf_Small) + /* Size of address size field. */ + sizeof(Dwarf_Small); /* Size of segment size field. */ + + /* + Adjust the size so that the set of aranges begins on a boundary + that aligned with twice the address size. This is a Libdwarf + requirement. */ + remainder = arange_num_bytes % (2 * upointer_size); + if (remainder != 0) + arange_num_bytes += (2 * upointer_size) - remainder; + + + /* Add the bytes for the actual address ranges. */ + arange_num_bytes += upointer_size * 2 * (dbg->de_arange_count + 1); + + GET_CHUNK(dbg, dbg->de_elf_sects[DEBUG_ARANGES], + arange, (unsigned long) arange_num_bytes, error); + arange_ptr = arange; + if (arange == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (0); + } + if (extension_word_size) { + Dwarf_Word x = DISTINGUISHED_VALUE; + + WRITE_UNALIGNED(dbg, (void *) arange_ptr, + (const void *) &x, + sizeof(x), extension_word_size); + arange_ptr += extension_word_size; + } + + /* Write the total length of .debug_aranges section. */ + adjusted_length = arange_num_bytes - uword_size + - extension_word_size; + { + Dwarf_Unsigned du = adjusted_length; + + WRITE_UNALIGNED(dbg, (void *) arange_ptr, + (const void *) &du, sizeof(du), uword_size); + arange_ptr += uword_size; + } + + /* Write the version as 2 bytes. */ + { + Dwarf_Half verstamp = CURRENT_VERSION_STAMP; + + WRITE_UNALIGNED(dbg, (void *) arange_ptr, + (const void *) &verstamp, + sizeof(verstamp), sizeof(Dwarf_Half)); + arange_ptr += sizeof(Dwarf_Half); + } + + + /* Write the .debug_info offset. This is always 0. */ + WRITE_UNALIGNED(dbg, (void *) arange_ptr, + (const void *) &big_zero, + sizeof(big_zero), uword_size); + arange_ptr += uword_size; + + { + unsigned long count = dbg->de_arange_count + 1; + int res; + + if (dbg->de_reloc_pair) { + count = (3 * dbg->de_arange_count) + 1; + } + /* the following is a small optimization: not needed for + correctness */ + res = _dwarf_pro_pre_alloc_n_reloc_slots(dbg, + DEBUG_ARANGES, count); + if (res != DW_DLV_OK) { + { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (0); + } + } + } + + /* reloc for .debug_info */ + res = dbg->de_reloc_name(dbg, + DEBUG_ARANGES, + extension_word_size + + uword_size + sizeof(Dwarf_Half), + dbg->de_sect_name_idx[DEBUG_INFO], + dwarf_drt_data_reloc, uword_size); + + /* Write the size of addresses. */ + *arange_ptr = dbg->de_pointer_size; + arange_ptr++; + + /* + Write the size of segment addresses. This is zero for MIPS + architectures. */ + *arange_ptr = 0; + arange_ptr++; + + /* + Skip over the padding to align the start of the actual address + ranges to twice the address size. */ + if (remainder != 0) + arange_ptr += (2 * upointer_size) - remainder; + + + + + + /* The arange address, length are pointer-size fields of the target + machine. */ + for (given_arange = dbg->de_arange; given_arange != NULL; + given_arange = given_arange->ag_next) { + + /* Write relocation record for beginning of address range. */ + res = dbg->de_reloc_name(dbg, DEBUG_ARANGES, arange_ptr - arange, /* r_offset + */ + (long) given_arange->ag_symbol_index, + dwarf_drt_data_reloc, upointer_size); + if (res != DW_DLV_OK) { + { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (0); + } + } + + /* Copy beginning address of range. */ + WRITE_UNALIGNED(dbg, (void *) arange_ptr, + (const void *) &given_arange->ag_begin_address, + sizeof(given_arange->ag_begin_address), + upointer_size); + arange_ptr += upointer_size; + + if (dbg->de_reloc_pair && + given_arange->ag_end_symbol_index != 0 && + given_arange->ag_length == 0) { + /* symbolic reloc, need reloc for length What if we really + know the length? If so, should use the other part of + 'if'. */ + Dwarf_Unsigned val; + + res = dbg->de_reloc_pair(dbg, DEBUG_ARANGES, arange_ptr - arange, /* r_offset + */ + given_arange->ag_symbol_index, + given_arange->ag_end_symbol_index, + dwarf_drt_first_of_length_pair, + upointer_size); + if (res != DW_DLV_OK) { + { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (0); + } + } + + /* arrange pre-calc so assem text can do .word end - begin + + val (gets val from stream) */ + val = given_arange->ag_end_symbol_offset - + given_arange->ag_begin_address; + WRITE_UNALIGNED(dbg, (void *) arange_ptr, + (const void *) &val, + sizeof(val), upointer_size); + arange_ptr += upointer_size; + + } else { + /* plain old length to copy, no relocation at all */ + WRITE_UNALIGNED(dbg, (void *) arange_ptr, + (const void *) &given_arange->ag_length, + sizeof(given_arange->ag_length), + upointer_size); + arange_ptr += upointer_size; + } + } + + WRITE_UNALIGNED(dbg, (void *) arange_ptr, + (const void *) &big_zero, + sizeof(big_zero), upointer_size); + + arange_ptr += upointer_size; + WRITE_UNALIGNED(dbg, (void *) arange_ptr, + (const void *) &big_zero, + sizeof(big_zero), upointer_size); + return (int) dbg->de_n_debug_sect; +} diff --git a/usr/src/lib/libdwarf/common/pro_arange.h b/usr/src/lib/libdwarf/common/pro_arange.h new file mode 100644 index 0000000000..f0e7e84dff --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_arange.h @@ -0,0 +1,62 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + +/* + If ag_end_symbol_index is zero, + ag_length must be known and non-zero. + + + Deals with length being known costant or fr + assembler output, not known. + +*/ + +struct Dwarf_P_Arange_s { + Dwarf_Addr ag_begin_address; /* known address or for + symbolic assem output, + offset of symbol */ + Dwarf_Addr ag_length; /* zero or address or offset */ + Dwarf_Unsigned ag_symbol_index; + + Dwarf_P_Arange ag_next; + + Dwarf_Unsigned ag_end_symbol_index; /* zero or index/id of end + symbol */ + Dwarf_Addr ag_end_symbol_offset; /* known address or for + symbolic assem output, + offset of end symbol */ + +}; diff --git a/usr/src/lib/libdwarf/common/pro_die.c b/usr/src/lib/libdwarf/common/pro_die.c new file mode 100644 index 0000000000..948b641146 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_die.c @@ -0,0 +1,442 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include +#include +#include "pro_incl.h" +#include "pro_die.h" + +#ifndef R_MIPS_NONE +#define R_MIPS_NONE 0 +#endif + +/* adds an attribute to a die */ +void _dwarf_pro_add_at_to_die(Dwarf_P_Die die, Dwarf_P_Attribute attr); + +/*---------------------------------------------------------------------------- + This function creates a new die. + tag: tag of the new die to be created + parent,child,left,right: specify neighbors of the new die. Only + one of these may be non-null +-----------------------------------------------------------------------------*/ +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) +{ + Dwarf_P_Die ret_die = 0; + + Dwarf_P_Die new_die = (Dwarf_P_Die) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Die_s)); + if (new_die == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_ALLOC, + (Dwarf_P_Die) DW_DLV_BADADDR); + } + new_die->di_parent = NULL; + new_die->di_left = NULL; + new_die->di_right = NULL; + new_die->di_child = NULL; + new_die->di_last_child = NULL; + new_die->di_tag = tag; + new_die->di_dbg = dbg; + new_die->di_marker = 0; + ret_die = + dwarf_die_link(new_die, parent, child, left, right, error); + return ret_die; +} + +/*---------------------------------------------------------------------------- + This function links up a die to specified neighbors + parent,child,left,right: specify neighbors of the new die. Only + one of these may be non-null +-----------------------------------------------------------------------------*/ +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) +{ + /* Count the # of non null neighbors. */ + int n_nulls = 0; + + if (parent != NULL) { + n_nulls++; + if (new_die->di_parent != NULL) { + DWARF_P_DBG_ERROR(NULL, DW_DLE_LINK_LOOP, + (Dwarf_P_Die) DW_DLV_BADADDR); + } + new_die->di_parent = parent; + if (parent->di_child) { + + /* di_last_child identifies the last sibling, the + die we want to attach new_die to. */ + /* ASSERT: if di_child is set so is di_last_child. */ + Dwarf_P_Die former_lastchild = parent->di_last_child; + parent->di_last_child = new_die; + /* Attach to the new die to end of the sibling list. */ + former_lastchild->di_right = new_die; + new_die->di_left = former_lastchild; + } else { + parent->di_child = new_die; + parent->di_last_child = new_die; + } + } + if (child != NULL) { + n_nulls++; + new_die->di_child = child; + new_die->di_last_child = child; + if (child->di_parent) { + DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS, + (Dwarf_P_Die) DW_DLV_BADADDR); + } else { + child->di_parent = new_die; + } + } + if (left != NULL) { + n_nulls++; + new_die->di_left = left; + if (left->di_right) { + /* There's already a right sibling of left, + insert the new die in the list. */ + new_die->di_right = left->di_right; + left->di_right->di_left = new_die; + } + left->di_right = new_die; + if (new_die->di_parent) { + DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS, + (Dwarf_P_Die) DW_DLV_BADADDR); + } else { + new_die->di_parent = left->di_parent; + } + } + if (right != NULL) { + n_nulls++; + new_die->di_right = right; + if (right->di_left) { + /* There is already a left sibling of the right die, + insert the new die in the list. */ + new_die->di_left = right->di_left; + right->di_left->di_right = new_die; + } + right->di_left = new_die; + if (new_die->di_parent) { + DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS, + (Dwarf_P_Die) DW_DLV_BADADDR); + } else { + new_die->di_parent = right->di_parent; + } + } + if (n_nulls > 1) { + /* Multiple neighbors! error! */ + DWARF_P_DBG_ERROR(NULL, DW_DLE_EXTRA_NEIGHBORS, + (Dwarf_P_Die) DW_DLV_BADADDR); + } + return new_die; + +} + +Dwarf_Unsigned +dwarf_add_die_marker(Dwarf_P_Debug dbg, + Dwarf_P_Die die, + Dwarf_Unsigned marker, + Dwarf_Error * error) +{ + if (die == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, DW_DLV_NOCOUNT); + } + die->di_marker = marker; + return 0; +} + + +Dwarf_Unsigned +dwarf_get_die_marker(Dwarf_P_Debug dbg, + Dwarf_P_Die die, + Dwarf_Unsigned * marker, + Dwarf_Error * error) +{ + if (die == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, DW_DLV_NOCOUNT); + } + *marker = die->di_marker; + return 0; +} + + +/*---------------------------------------------------------------------------- + This function adds a die to dbg struct. It should be called using + the root of all the dies. +-----------------------------------------------------------------------------*/ +Dwarf_Unsigned +dwarf_add_die_to_debug(Dwarf_P_Debug dbg, + Dwarf_P_Die first_die, Dwarf_Error * error) +{ + if (first_die == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, DW_DLV_NOCOUNT); + } + if (first_die->di_tag != DW_TAG_compile_unit) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_WRONG_TAG, DW_DLV_NOCOUNT); + } + dbg->de_dies = first_die; + return 0; +} + +int +_dwarf_pro_add_AT_stmt_list(Dwarf_P_Debug dbg, + Dwarf_P_Die first_die, Dwarf_Error * error) +{ + Dwarf_P_Attribute new_attr; + int uwordb_size = dbg->de_offset_size; + + /* Add AT_stmt_list attribute */ + new_attr = (Dwarf_P_Attribute) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); + if (new_attr == NULL) { + DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, DW_DLV_NOCOUNT); + } + + new_attr->ar_attribute = DW_AT_stmt_list; + new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form; + new_attr->ar_rel_type = dbg->de_offset_reloc; + + new_attr->ar_nbytes = uwordb_size; + new_attr->ar_next = NULL; + new_attr->ar_reloc_len = uwordb_size; + new_attr->ar_data = (char *) + _dwarf_p_get_alloc(dbg, uwordb_size); + if (new_attr->ar_data == NULL) { + DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT); + } + { + Dwarf_Unsigned du = 0; + + WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, + (const void *) &du, sizeof(du), uwordb_size); + } + + _dwarf_pro_add_at_to_die(first_die, new_attr); + return 0; +} + +/*----------------------------------------------------------------------------- + Add AT_name attribute to die +------------------------------------------------------------------------------*/ +Dwarf_P_Attribute +dwarf_add_AT_name(Dwarf_P_Die die, char *name, Dwarf_Error * error) +{ + Dwarf_P_Attribute new_attr; + + if (die == NULL) { + DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, + (Dwarf_P_Attribute) DW_DLV_BADADDR); + } + new_attr = (Dwarf_P_Attribute) + _dwarf_p_get_alloc(die->di_dbg,sizeof(struct Dwarf_P_Attribute_s)); + if (new_attr == NULL) { + DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, + (Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + /* fill in the information */ + new_attr->ar_attribute = DW_AT_name; + /* assume that form is string, no debug_str yet */ + new_attr->ar_attribute_form = DW_FORM_string; + new_attr->ar_nbytes = strlen(name) + 1; + new_attr->ar_next = NULL; + new_attr->ar_reloc_len = 0; + new_attr->ar_data = (char *) + _dwarf_p_get_alloc(die->di_dbg, strlen(name)+1); + if (new_attr->ar_data == NULL) { + DWARF_P_DBG_ERROR(NULL, DW_DLE_STRING_ALLOC, + (Dwarf_P_Attribute) DW_DLV_BADADDR); + } + strcpy(new_attr->ar_data, name); + + new_attr->ar_rel_type = R_MIPS_NONE; + + /* add attribute to the die */ + _dwarf_pro_add_at_to_die(die, new_attr); + return new_attr; +} + + +/*----------------------------------------------------------------------------- + Add AT_comp_dir attribute to die +------------------------------------------------------------------------------*/ +Dwarf_P_Attribute +dwarf_add_AT_comp_dir(Dwarf_P_Die ownerdie, + char *current_working_directory, + Dwarf_Error * error) +{ + Dwarf_P_Attribute new_attr; + + if (ownerdie == NULL) { + DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, + (Dwarf_P_Attribute) DW_DLV_BADADDR); + } + new_attr = (Dwarf_P_Attribute) + _dwarf_p_get_alloc(ownerdie->di_dbg, + sizeof(struct Dwarf_P_Attribute_s)); + if (new_attr == NULL) { + DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, + (Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + /* fill in the information */ + new_attr->ar_attribute = DW_AT_comp_dir; + /* assume that form is string, no debug_str yet */ + new_attr->ar_attribute_form = DW_FORM_string; + new_attr->ar_nbytes = strlen(current_working_directory) + 1; + new_attr->ar_next = NULL; + new_attr->ar_reloc_len = 0; + new_attr->ar_data = (char *) + _dwarf_p_get_alloc(ownerdie->di_dbg, + strlen(current_working_directory)+1); + if (new_attr->ar_data == NULL) { + DWARF_P_DBG_ERROR(NULL, DW_DLE_STRING_ALLOC, + (Dwarf_P_Attribute) DW_DLV_BADADDR); + } + strcpy(new_attr->ar_data, current_working_directory); + + new_attr->ar_rel_type = R_MIPS_NONE; + + /* add attribute to the die */ + _dwarf_pro_add_at_to_die(ownerdie, new_attr); + return new_attr; +} + +int +_dwarf_pro_add_AT_fde(Dwarf_P_Debug dbg, + Dwarf_P_Die die, + Dwarf_Unsigned offset, Dwarf_Error * error) +{ + Dwarf_P_Attribute new_attr; + int uwordb_size = dbg->de_offset_size; + + if (die == NULL) { + DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, -1); + } + new_attr = (Dwarf_P_Attribute) + _dwarf_p_get_alloc(dbg,sizeof(struct Dwarf_P_Attribute_s)); + if (new_attr == NULL) { + DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, -1); + } + + /* fill in the information */ + new_attr->ar_attribute = DW_AT_MIPS_fde; + new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form;; + new_attr->ar_rel_type = dbg->de_offset_reloc; + new_attr->ar_nbytes = uwordb_size; + new_attr->ar_next = NULL; + new_attr->ar_reloc_len = uwordb_size; + new_attr->ar_data = (char *) + _dwarf_p_get_alloc(dbg, uwordb_size); + if (new_attr->ar_data == NULL) { + DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT); + } + { + Dwarf_Unsigned du = offset; + + WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, + (const void *) &du, sizeof(du), uwordb_size); + } + + _dwarf_pro_add_at_to_die(die, new_attr); + + return 0; +} + +int +_dwarf_pro_add_AT_macro_info(Dwarf_P_Debug dbg, + Dwarf_P_Die die, + Dwarf_Unsigned offset, Dwarf_Error * error) +{ + Dwarf_P_Attribute new_attr; + int uwordb_size = dbg->de_offset_size; + + if (die == NULL) { + DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, -1); + } + new_attr = (Dwarf_P_Attribute) + _dwarf_p_get_alloc(dbg,sizeof(struct Dwarf_P_Attribute_s)); + if (new_attr == NULL) { + DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, -1); + } + + /* fill in the information */ + new_attr->ar_attribute = DW_AT_macro_info; + new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form; + new_attr->ar_rel_type = dbg->de_offset_reloc; + + new_attr->ar_nbytes = uwordb_size; + new_attr->ar_next = NULL; + new_attr->ar_reloc_len = uwordb_size; + new_attr->ar_data = (char *) + _dwarf_p_get_alloc(dbg, uwordb_size); + if (new_attr->ar_data == NULL) { + DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT); + } + { + Dwarf_Unsigned du = offset; + + WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, + (const void *) &du, sizeof(du), uwordb_size); + } + + _dwarf_pro_add_at_to_die(die, new_attr); + + return 0; +} + + +void +_dwarf_pro_add_at_to_die(Dwarf_P_Die die, Dwarf_P_Attribute attr) +{ + if (die->di_last_attr) { + die->di_last_attr->ar_next = attr; + die->di_last_attr = attr; + die->di_n_attr++; + } else { + die->di_n_attr = 1; + die->di_attrs = die->di_last_attr = attr; + } +} diff --git a/usr/src/lib/libdwarf/common/pro_die.h b/usr/src/lib/libdwarf/common/pro_die.h new file mode 100644 index 0000000000..01c00e79bd --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_die.h @@ -0,0 +1,68 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + + +/* + This struct holds the abbreviation table, before they are written + on disk. Holds a linked list of abbreviations, each consisting of + a bitmap for attributes and a bitmap for forms +*/ +typedef struct Dwarf_P_Abbrev_s *Dwarf_P_Abbrev; + +struct Dwarf_P_Abbrev_s { + Dwarf_Unsigned abb_idx; /* index of abbreviation */ + Dwarf_Tag abb_tag; /* tag of die */ + Dwarf_Ubyte abb_children; /* if children are present */ + Dwarf_ufixed *abb_attrs; /* holds names of attrs */ + Dwarf_ufixed *abb_forms; /* forms of attributes */ + int abb_n_attr; /* num of attrs = # of forms */ + Dwarf_P_Abbrev abb_next; +}; + +/* used in pro_section.c */ + +int _dwarf_pro_add_AT_fde(Dwarf_P_Debug dbg, Dwarf_P_Die die, + Dwarf_Unsigned offset, Dwarf_Error * error); + +int _dwarf_pro_add_AT_stmt_list(Dwarf_P_Debug dbg, + Dwarf_P_Die first_die, + Dwarf_Error * error); + +int _dwarf_pro_add_AT_macro_info(Dwarf_P_Debug dbg, + Dwarf_P_Die first_die, + Dwarf_Unsigned offset, + Dwarf_Error * error); diff --git a/usr/src/lib/libdwarf/common/pro_encode_nm.c b/usr/src/lib/libdwarf/common/pro_encode_nm.c new file mode 100644 index 0000000000..d6215dc56b --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_encode_nm.c @@ -0,0 +1,123 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include +#include "pro_incl.h" + +#define MORE_BYTES 0x80 +#define DATA_MASK 0x7f +#define DIGIT_WIDTH 7 +#define SIGN_BIT 0x40 + + +/*------------------------------------------------------------- + Encode val as a leb128. This encodes it as an unsigned + number. +---------------------------------------------------------------*/ +/* return DW_DLV_ERROR or DW_DLV_OK. +** space to write leb number is provided by caller, with caller +** passing length. +** number of bytes used returned thru nbytes arg +*/ +int +_dwarf_pro_encode_leb128_nm(Dwarf_Unsigned val, int *nbytes, + char *space, int splen) +{ + char *a; + char *end = space + splen; + + a = space; + do { + unsigned char uc; + + if (a >= end) { + return DW_DLV_ERROR; + } + uc = val & DATA_MASK; + val >>= DIGIT_WIDTH; + if (val != 0) { + uc |= MORE_BYTES; + } + *a = uc; + a++; + } while (val); + *nbytes = a - space; + return DW_DLV_OK; +} + +/* return DW_DLV_ERROR or DW_DLV_OK. +** space to write leb number is provided by caller, with caller +** passing length. +** number of bytes used returned thru nbytes arg +** encodes a signed number. +*/ +int +_dwarf_pro_encode_signed_leb128_nm(Dwarf_Signed value, int *nbytes, + char *space, int splen) +{ + char *str; + Dwarf_Signed sign = -(value < 0); + int more = 1; + char *end = space + splen; + + str = space; + + do { + unsigned char byte = value & DATA_MASK; + + value >>= DIGIT_WIDTH; + + if (str >= end) { + return DW_DLV_ERROR; + } + /* + * Remaining chunks would just contain the sign bit, and this chunk + * has already captured at least one sign bit. + */ + if (value == sign && ((byte & SIGN_BIT) == (sign & SIGN_BIT))) { + more = 0; + } else { + byte |= MORE_BYTES; + } + *str = byte; + str++; + } while (more); + *nbytes = str - space; + return DW_DLV_OK; +} diff --git a/usr/src/lib/libdwarf/common/pro_encode_nm.h b/usr/src/lib/libdwarf/common/pro_encode_nm.h new file mode 100644 index 0000000000..d08e4d5148 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_encode_nm.h @@ -0,0 +1,48 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +/* Bytes needed to encode a number. + Not a tight bound, just a reasonable bound. +*/ +#define ENCODE_SPACE_NEEDED (2*sizeof(Dwarf_Unsigned)) + + +int _dwarf_pro_encode_leb128_nm(Dwarf_Unsigned val, int *nbytes, + char *space, int splen); + +int _dwarf_pro_encode_signed_leb128_nm(Dwarf_Signed value, int *nbytes, + char *space, int splen); diff --git a/usr/src/lib/libdwarf/common/pro_error.c b/usr/src/lib/libdwarf/common/pro_error.c new file mode 100644 index 0000000000..d408a391e2 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_error.c @@ -0,0 +1,97 @@ +/* + + Copyright (C) 2000,2002,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#ifdef HAVE_ELF_H +#include +#endif + +#include +#include +#include +#include +#include "pro_incl.h" + +extern char *_dwarf_errmsgs[]; + +/* + This function performs error handling as described in the + libdwarf consumer document section 3. Dbg is the Dwarf_P_debug + structure being processed. Error is a pointer to the pointer + to the error descriptor that will be returned. Errval is an + error code listed in dwarf_error.h. +*/ +void +_dwarf_p_error(Dwarf_P_Debug dbg, + Dwarf_Error * error, Dwarf_Word errval) +{ + Dwarf_Error errptr; + + /* Allow NULL dbg on entry, since sometimes that can happen and we + want to report the upper-level error, not this one. */ + if ((Dwarf_Sword) errval < 0) + printf("ERROR VALUE: %ld - %s\n", + (long) errval, _dwarf_errmsgs[-errval - 1]); + if (error != NULL) { + errptr = (Dwarf_Error) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_Error_s)); + if (errptr == NULL) { + fprintf(stderr, + "Could not allocate Dwarf_Error structure\n"); + abort(); + } + errptr->er_errval = (Dwarf_Sword) errval; + *error = errptr; + return; + } + + if (dbg != NULL && dbg->de_errhand != NULL) { + errptr = (Dwarf_Error) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_Error_s)); + if (errptr == NULL) { + fprintf(stderr, + "Could not allocate Dwarf_Error structure\n"); + abort(); + } + errptr->er_errval = (Dwarf_Sword) errval; + dbg->de_errhand(errptr, dbg->de_errarg); + return; + } + + abort(); +} diff --git a/usr/src/lib/libdwarf/common/pro_error.h b/usr/src/lib/libdwarf/common/pro_error.h new file mode 100644 index 0000000000..c37035301b --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_error.h @@ -0,0 +1,52 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + + +/* Handle error passing in the name of the Dwarf_P_Debug + User must supply {} around the macro. + Putting the {} here leads to macro uses that don't look like C. + The error argument to dwarf_error is hard coded here as 'error' +*/ +#define DWARF_P_DBG_ERROR(dbg,errval,retval) \ + _dwarf_p_error(dbg,error,errval); return(retval); + +struct Dwarf_Error_s { + Dwarf_Sword er_errval; +}; + +void _dwarf_p_error(Dwarf_P_Debug dbg, Dwarf_Error * error, + Dwarf_Word errval); diff --git a/usr/src/lib/libdwarf/common/pro_expr.c b/usr/src/lib/libdwarf/common/pro_expr.c new file mode 100644 index 0000000000..ad40eb762a --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_expr.c @@ -0,0 +1,597 @@ +/* + + Copyright (C) 2000,2004,2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include +#include +#include +#include "pro_incl.h" +#include "pro_expr.h" + +/* + This function creates a new expression + struct that can be used to build up a + location expression. +*/ +Dwarf_P_Expr +dwarf_new_expr(Dwarf_P_Debug dbg, Dwarf_Error * error) +{ + Dwarf_P_Expr ret_expr; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return (NULL); + } + + ret_expr = (Dwarf_P_Expr) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Expr_s)); + if (ret_expr == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (NULL); + } + + ret_expr->ex_dbg = dbg; + + return (ret_expr); +} + + +Dwarf_Unsigned +dwarf_add_expr_gen(Dwarf_P_Expr expr, + Dwarf_Small opcode, + Dwarf_Unsigned val1, + Dwarf_Unsigned val2, Dwarf_Error * error) +{ + char encode_buffer[2 * ENCODE_SPACE_NEEDED]; /* 2* since + used to + concatenate + 2 leb's + below */ + char encode_buffer2[ENCODE_SPACE_NEEDED]; + int res; + Dwarf_P_Debug dbg = expr->ex_dbg; + + /* + Give the buffer where the operands are first going to be + assembled the largest alignment. */ + Dwarf_Unsigned operand_buffer[10]; + + /* + Size of the byte stream buffer that needs to be memcpy-ed. */ + int operand_size; + + /* + Points to the byte stream for the first operand, and finally to + the buffer that is memcp-ed into the Dwarf_P_Expr_s struct. */ + Dwarf_Small *operand; + + /* Size of the byte stream for second operand. */ + int operand2_size; + + /* Points to next byte to be written in Dwarf_P_Expr_s struct. */ + Dwarf_Small *next_byte_ptr; + + /* Offset past the last byte written into Dwarf_P_Expr_s. */ + int next_byte_offset; + + /* ***** BEGIN CODE ***** */ + + if (expr == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); + return (DW_DLV_NOCOUNT); + } + + if (expr->ex_dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_NOCOUNT); + } + + operand = NULL; + operand_size = 0; + + switch (opcode) { + case DW_OP_reg0: + case DW_OP_reg1: + case DW_OP_reg2: + case DW_OP_reg3: + case DW_OP_reg4: + case DW_OP_reg5: + case DW_OP_reg6: + case DW_OP_reg7: + case DW_OP_reg8: + case DW_OP_reg9: + case DW_OP_reg10: + case DW_OP_reg11: + case DW_OP_reg12: + case DW_OP_reg13: + case DW_OP_reg14: + case DW_OP_reg15: + case DW_OP_reg16: + case DW_OP_reg17: + case DW_OP_reg18: + case DW_OP_reg19: + case DW_OP_reg20: + case DW_OP_reg21: + case DW_OP_reg22: + case DW_OP_reg23: + case DW_OP_reg24: + case DW_OP_reg25: + case DW_OP_reg26: + case DW_OP_reg27: + case DW_OP_reg28: + case DW_OP_reg29: + case DW_OP_reg30: + case DW_OP_reg31: + break; + + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + res = _dwarf_pro_encode_signed_leb128_nm(val1, + &operand_size, + encode_buffer, + sizeof(encode_buffer)); + if (res != DW_DLV_OK) { + _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); + return (DW_DLV_NOCOUNT); + } + operand = (Dwarf_Small *) encode_buffer; + break; + + case DW_OP_regx: + res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, + encode_buffer, + sizeof(encode_buffer)); + if (res != DW_DLV_OK) { + _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); + return (DW_DLV_NOCOUNT); + } + operand = (Dwarf_Small *) encode_buffer; + break; + + case DW_OP_lit0: + case DW_OP_lit1: + case DW_OP_lit2: + case DW_OP_lit3: + case DW_OP_lit4: + case DW_OP_lit5: + case DW_OP_lit6: + case DW_OP_lit7: + case DW_OP_lit8: + case DW_OP_lit9: + case DW_OP_lit10: + case DW_OP_lit11: + case DW_OP_lit12: + case DW_OP_lit13: + case DW_OP_lit14: + case DW_OP_lit15: + case DW_OP_lit16: + case DW_OP_lit17: + case DW_OP_lit18: + case DW_OP_lit19: + case DW_OP_lit20: + case DW_OP_lit21: + case DW_OP_lit22: + case DW_OP_lit23: + case DW_OP_lit24: + case DW_OP_lit25: + case DW_OP_lit26: + case DW_OP_lit27: + case DW_OP_lit28: + case DW_OP_lit29: + case DW_OP_lit30: + case DW_OP_lit31: + break; + + case DW_OP_addr: + _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE); + return (DW_DLV_NOCOUNT); + + case DW_OP_const1u: + case DW_OP_const1s: + operand = (Dwarf_Small *) & operand_buffer[0]; + WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 1); + operand_size = 1; + break; + + case DW_OP_const2u: + case DW_OP_const2s: + operand = (Dwarf_Small *) & operand_buffer[0]; + WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 2); + operand_size = 2; + break; + + case DW_OP_const4u: + case DW_OP_const4s: + operand = (Dwarf_Small *) & operand_buffer[0]; + WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 4); + operand_size = 4; + break; + + case DW_OP_const8u: + case DW_OP_const8s: + operand = (Dwarf_Small *) & operand_buffer[0]; + WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 8); + operand_size = 8; + break; + + case DW_OP_constu: + res = _dwarf_pro_encode_leb128_nm(val1, + &operand_size, + encode_buffer, + sizeof(encode_buffer)); + if (res != DW_DLV_OK) { + _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); + return (DW_DLV_NOCOUNT); + } + operand = (Dwarf_Small *) encode_buffer; + break; + + case DW_OP_consts: + res = _dwarf_pro_encode_signed_leb128_nm(val1, + &operand_size, + encode_buffer, + sizeof(encode_buffer)); + if (res != DW_DLV_OK) { + _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); + return (DW_DLV_NOCOUNT); + } + operand = (Dwarf_Small *) encode_buffer; + break; + + case DW_OP_fbreg: + res = _dwarf_pro_encode_signed_leb128_nm(val1, + &operand_size, + encode_buffer, + sizeof(encode_buffer)); + if (res != DW_DLV_OK) { + _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); + return (DW_DLV_NOCOUNT); + } + operand = (Dwarf_Small *) encode_buffer; + break; + + case DW_OP_bregx: + res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, + encode_buffer, + sizeof(encode_buffer)); + if (res != DW_DLV_OK) { + _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); + return (DW_DLV_NOCOUNT); + } + operand = (Dwarf_Small *) encode_buffer; + /* put this one directly into 'operand' at tail of prev value */ + res = _dwarf_pro_encode_signed_leb128_nm(val2, &operand2_size, + ((char *) operand) + + operand_size, + sizeof + (encode_buffer2)); + if (res != DW_DLV_OK) { + _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); + return (DW_DLV_NOCOUNT); + } + operand_size += operand2_size; + + case DW_OP_dup: + case DW_OP_drop: + break; + + case DW_OP_pick: + operand = (Dwarf_Small *) & operand_buffer[0]; + WRITE_UNALIGNED(dbg, operand, (const void *) &val1, + sizeof(val1), 1); + operand_size = 1; + break; + + case DW_OP_over: + case DW_OP_swap: + case DW_OP_rot: + case DW_OP_deref: + case DW_OP_xderef: + break; + + case DW_OP_deref_size: + case DW_OP_xderef_size: + operand = (Dwarf_Small *) & operand_buffer[0]; + WRITE_UNALIGNED(dbg, operand, (const void *) &val1, + sizeof(val1), 1); + operand_size = 1; + break; + + case DW_OP_abs: + case DW_OP_and: + case DW_OP_div: + case DW_OP_minus: + case DW_OP_mod: + case DW_OP_mul: + case DW_OP_neg: + case DW_OP_not: + case DW_OP_or: + case DW_OP_plus: + break; + + case DW_OP_plus_uconst: + res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, + encode_buffer, + sizeof(encode_buffer)); + if (res != DW_DLV_OK) { + _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); + return (DW_DLV_NOCOUNT); + } + operand = (Dwarf_Small *) encode_buffer; + break; + + case DW_OP_shl: + case DW_OP_shr: + case DW_OP_shra: + case DW_OP_xor: + break; + + case DW_OP_le: + case DW_OP_ge: + case DW_OP_eq: + case DW_OP_lt: + case DW_OP_gt: + case DW_OP_ne: + break; + + case DW_OP_skip: + case DW_OP_bra: + /* FIX: unhandled! OP_bra, OP_skip! */ + _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE); + return (DW_DLV_NOCOUNT); + + case DW_OP_piece: + res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, + encode_buffer, + sizeof(encode_buffer)); + if (res != DW_DLV_OK) { + _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); + return (DW_DLV_NOCOUNT); + } + operand = (Dwarf_Small *) encode_buffer; + break; + + case DW_OP_nop: + break; + case DW_OP_push_object_address: /* DWARF3 */ + break; + case DW_OP_call2: /* DWARF3 */ + operand = (Dwarf_Small *) & operand_buffer[0]; + WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 2); + operand_size = 2; + break; + + case DW_OP_call4: /* DWARF3 */ + operand = (Dwarf_Small *) & operand_buffer[0]; + WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 4); + operand_size = 4; + break; + + case DW_OP_call_ref: /* DWARF3 */ + operand = (Dwarf_Small *) & operand_buffer[0]; + WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), + dbg->de_offset_size); + operand_size = dbg->de_offset_size; + break; + case DW_OP_form_tls_address: /* DWARF3f */ + break; + case DW_OP_call_frame_cfa: /* DWARF3f */ + break; + case DW_OP_bit_piece: /* DWARF3f */ + res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, + encode_buffer, + sizeof(encode_buffer)); + if (res != DW_DLV_OK) { + _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); + return (DW_DLV_NOCOUNT); + } + operand = (Dwarf_Small *) encode_buffer; + /* put this one directly into 'operand' at tail of prev value */ + res = _dwarf_pro_encode_leb128_nm(val2, &operand2_size, + ((char *) operand) + + operand_size, + sizeof(encode_buffer2)); + if (res != DW_DLV_OK) { + _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); + return (DW_DLV_NOCOUNT); + } + operand_size += operand2_size; + break; + + default: + _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE); + return (DW_DLV_NOCOUNT); + } + + next_byte_offset = expr->ex_next_byte_offset + operand_size + 1; + + if (next_byte_offset > MAXIMUM_LOC_EXPR_LENGTH) { + _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); + return (DW_DLV_NOCOUNT); + } + + next_byte_ptr = + &(expr->ex_byte_stream[0]) + expr->ex_next_byte_offset; + + *next_byte_ptr = opcode; + next_byte_ptr++; + memcpy(next_byte_ptr, operand, operand_size); + + expr->ex_next_byte_offset = next_byte_offset; + return (next_byte_offset); +} + +Dwarf_Unsigned +dwarf_add_expr_addr_b(Dwarf_P_Expr expr, + Dwarf_Unsigned addr, + Dwarf_Unsigned sym_index, Dwarf_Error * error) +{ + Dwarf_P_Debug dbg; + Dwarf_Small *next_byte_ptr; + Dwarf_Unsigned next_byte_offset; + int upointer_size; + + if (expr == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); + return (DW_DLV_NOCOUNT); + } + + dbg = expr->ex_dbg; + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_NOCOUNT); + } + + upointer_size = dbg->de_pointer_size; + next_byte_offset = expr->ex_next_byte_offset + upointer_size + 1; + if (next_byte_offset > MAXIMUM_LOC_EXPR_LENGTH) { + _dwarf_p_error(dbg, error, DW_DLE_EXPR_LENGTH_BAD); + return (DW_DLV_NOCOUNT); + } + + next_byte_ptr = + &(expr->ex_byte_stream[0]) + expr->ex_next_byte_offset; + + *next_byte_ptr = DW_OP_addr; + next_byte_ptr++; + WRITE_UNALIGNED(dbg, next_byte_ptr, (const void *) &addr, + sizeof(addr), upointer_size); + + if (expr->ex_reloc_offset != 0) { + _dwarf_p_error(dbg, error, DW_DLE_MULTIPLE_RELOC_IN_EXPR); + return (DW_DLV_NOCOUNT); + } + + expr->ex_reloc_sym_index = sym_index; + expr->ex_reloc_offset = expr->ex_next_byte_offset + 1; + + expr->ex_next_byte_offset = next_byte_offset; + return (next_byte_offset); +} + +Dwarf_Unsigned +dwarf_add_expr_addr(Dwarf_P_Expr expr, + Dwarf_Unsigned addr, + Dwarf_Signed sym_index, Dwarf_Error * error) +{ + return + dwarf_add_expr_addr_b(expr, addr, (Dwarf_Unsigned) sym_index, + error); +} + + +Dwarf_Unsigned +dwarf_expr_current_offset(Dwarf_P_Expr expr, Dwarf_Error * error) +{ + if (expr == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); + return (DW_DLV_NOCOUNT); + } + + if (expr->ex_dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_NOCOUNT); + } + + return (expr->ex_next_byte_offset); +} + +void +dwarf_expr_reset(Dwarf_P_Expr expr, Dwarf_Error * error) +{ + if (expr == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); + return; + } + expr->ex_next_byte_offset=0; +} + + +Dwarf_Addr +dwarf_expr_into_block(Dwarf_P_Expr expr, + Dwarf_Unsigned * length, Dwarf_Error * error) +{ + if (expr == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); + return (DW_DLV_BADADDR); + } + + if (expr->ex_dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_BADADDR); + } + + if (length != NULL) + *length = expr->ex_next_byte_offset; + /* The following cast from pointer to integer is ok as long as + Dwarf_Addr is at least as large as a pointer. Which is a + requirement of libdwarf so must be satisfied (some compilers + emit a warning about the following line). */ + return ((Dwarf_Addr)(uintptr_t) &(expr->ex_byte_stream[0])); +} diff --git a/usr/src/lib/libdwarf/common/pro_expr.h b/usr/src/lib/libdwarf/common/pro_expr.h new file mode 100644 index 0000000000..202f2d30d5 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_expr.h @@ -0,0 +1,45 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + +#define MAXIMUM_LOC_EXPR_LENGTH 20 + +struct Dwarf_P_Expr_s { + Dwarf_Small ex_byte_stream[MAXIMUM_LOC_EXPR_LENGTH]; + Dwarf_P_Debug ex_dbg; + Dwarf_Unsigned ex_next_byte_offset; + Dwarf_Unsigned ex_reloc_sym_index; + Dwarf_Unsigned ex_reloc_offset; +}; diff --git a/usr/src/lib/libdwarf/common/pro_finish.c b/usr/src/lib/libdwarf/common/pro_finish.c new file mode 100644 index 0000000000..bc43a5f0f4 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_finish.c @@ -0,0 +1,57 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include "pro_incl.h" + +/*--------------------------------------------------------------- + This routine deallocates all memory, and does some + finishing up +-----------------------------------------------------------------*/ + /*ARGSUSED*/ Dwarf_Unsigned +dwarf_producer_finish(Dwarf_P_Debug dbg, Dwarf_Error * error) +{ + if (dbg->de_version_magic_number != PRO_VERSION_MAGIC) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, DW_DLV_NOCOUNT); + } + + /* this frees all blocks, then frees dbg. */ + _dwarf_p_dealloc_all(dbg); + return 0; +} diff --git a/usr/src/lib/libdwarf/common/pro_forms.c b/usr/src/lib/libdwarf/common/pro_forms.c new file mode 100644 index 0000000000..fec9a39c60 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_forms.c @@ -0,0 +1,1182 @@ +/* + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2007-2010 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include +#include +#include +#include "pro_incl.h" +#include "pro_expr.h" + +#ifndef R_MIPS_NONE +#define R_MIPS_NONE 0 +#endif + + + /* Indicates no relocation needed. */ +#define NO_ELF_SYM_INDEX 0 + + +/* adds an attribute to a die */ +extern void _dwarf_pro_add_at_to_die(Dwarf_P_Die die, + Dwarf_P_Attribute attr); + +/* + This function adds an attribute whose value is + a target address to the given die. The attribute + is given the name provided by attr. The address + is given in pc_value. +*/ + +static Dwarf_P_Attribute +local_add_AT_address(Dwarf_P_Debug dbg, + Dwarf_P_Die ownerdie, + Dwarf_Half attr, + Dwarf_Signed form, + Dwarf_Unsigned pc_value, + Dwarf_Unsigned sym_index, + Dwarf_Error * error); + +/* old interface */ +Dwarf_P_Attribute +dwarf_add_AT_targ_address(Dwarf_P_Debug dbg, + Dwarf_P_Die ownerdie, + Dwarf_Half attr, + Dwarf_Unsigned pc_value, + Dwarf_Signed sym_index, Dwarf_Error * error) +{ + return + dwarf_add_AT_targ_address_b(dbg, + ownerdie, + attr, + pc_value, + (Dwarf_Unsigned) sym_index, error); +} + +/* New interface, replacing dwarf_add_AT_targ_address. + Essentially just makes sym_index a Dwarf_Unsigned + so for symbolic relocations it can be a full address. +*/ +Dwarf_P_Attribute +dwarf_add_AT_targ_address_b(Dwarf_P_Debug dbg, + Dwarf_P_Die ownerdie, + Dwarf_Half attr, + Dwarf_Unsigned pc_value, + Dwarf_Unsigned sym_index, + Dwarf_Error * error) +{ + switch (attr) { + case DW_AT_low_pc: + case DW_AT_high_pc: + + /* added to support location lists */ + /* no way to check that this is a loclist-style address though */ + case DW_AT_location: + case DW_AT_string_length: + case DW_AT_return_addr: + case DW_AT_frame_base: + case DW_AT_segment: + case DW_AT_static_link: + case DW_AT_use_location: + case DW_AT_vtable_elem_location: + case DW_AT_const_value: /* Gcc can generate this as address. */ + case DW_AT_entry_pc: + break; + default: + if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) { + _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + break; + } + + return local_add_AT_address(dbg, ownerdie, attr, DW_FORM_addr, + pc_value, sym_index, error); +} + +Dwarf_P_Attribute +dwarf_add_AT_ref_address(Dwarf_P_Debug dbg, + Dwarf_P_Die ownerdie, + Dwarf_Half attr, + Dwarf_Unsigned pc_value, + Dwarf_Unsigned sym_index, + Dwarf_Error * error) +{ + switch (attr) { + case DW_AT_type: + case DW_AT_import: + break; + + default: + if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) { + _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + break; + } + + return local_add_AT_address(dbg, ownerdie, attr, DW_FORM_ref_addr, + pc_value, sym_index, error); +} + + +/* Make sure attribute types are checked before entering here. */ +static Dwarf_P_Attribute +local_add_AT_address(Dwarf_P_Debug dbg, + Dwarf_P_Die ownerdie, + Dwarf_Half attr, + Dwarf_Signed form, + Dwarf_Unsigned pc_value, + Dwarf_Unsigned sym_index, + Dwarf_Error * error) +{ + Dwarf_P_Attribute new_attr; + int upointer_size = dbg->de_pointer_size; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + if (ownerdie == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + /* attribute types have already been checked */ + /* switch (attr) { ... } */ + + new_attr = (Dwarf_P_Attribute) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); + if (new_attr == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + new_attr->ar_attribute = attr; + new_attr->ar_attribute_form = form; + new_attr->ar_nbytes = upointer_size; + new_attr->ar_rel_symidx = sym_index; + new_attr->ar_reloc_len = upointer_size; + new_attr->ar_next = 0; + if (sym_index != NO_ELF_SYM_INDEX) + new_attr->ar_rel_type = dbg->de_ptr_reloc; + else + new_attr->ar_rel_type = R_MIPS_NONE; + + new_attr->ar_data = (char *) + _dwarf_p_get_alloc(dbg, upointer_size); + if (new_attr->ar_data == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + WRITE_UNALIGNED(dbg, new_attr->ar_data, + (const void *) &pc_value, + sizeof(pc_value), upointer_size); + + /* add attribute to the die */ + _dwarf_pro_add_at_to_die(ownerdie, new_attr); + return new_attr; +} + +/* + * Functions to compress and uncompress data from normal + * arrays of integral types into arrays of LEB128 numbers. + * Extend these functions as needed to handle wider input + * variety. Return values should be freed with _dwarf_p_dealloc + * after they aren't needed any more. + */ + +/* return value points to an array of LEB number */ + +void * +dwarf_compress_integer_block( + Dwarf_P_Debug dbg, + Dwarf_Bool unit_is_signed, + Dwarf_Small unit_length_in_bits, + void* input_block, + Dwarf_Unsigned input_length_in_units, + Dwarf_Unsigned* output_length_in_bytes_ptr, + Dwarf_Error* error +) +{ + Dwarf_Unsigned output_length_in_bytes = 0; + char * output_block = 0; + char encode_buffer[ENCODE_SPACE_NEEDED]; + int i = 0; + char * ptr = 0; + int remain = 0; + int result = 0; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return((void *)DW_DLV_BADADDR); + } + + if (unit_is_signed == false || + unit_length_in_bits != 32 || + input_block == NULL || + input_length_in_units == 0 || + output_length_in_bytes_ptr == NULL) { + + _dwarf_p_error(NULL, error, DW_DLE_BADBITC); + return ((void *) DW_DLV_BADADDR); + } + + /* At this point we assume the format is: signed 32 bit */ + + /* first compress everything to find the total size. */ + + output_length_in_bytes = 0; + for (i=0; ide_ar_data_attribute_form is data4 or data8 + and dwarf4 changes the definition for such on DW_AT_high_pc. + DWARF 3: the FORM here has no defined meaning for dwarf3. + DWARF 4: the FORM here means that for DW_AT_high_pc the value + is not a high address but is instead an offset + from a (separate) DW_AT_low_pc. + The intent for DWARF4 is that this is not a relocated + address at all. Instead a simple offset. + But this should NOT be called for a simple non-relocated offset. + So do not call this with an attr of DW_AT_high_pc. + Use dwarf_add_AT_unsigned_const() (for example) instead of + dwarf_add_AT_dataref when the value is a simple offset . +*/ +Dwarf_P_Attribute +dwarf_add_AT_dataref( + Dwarf_P_Debug dbg, + Dwarf_P_Die ownerdie, + Dwarf_Half attr, + Dwarf_Unsigned pc_value, + Dwarf_Unsigned sym_index, + Dwarf_Error * error) +{ + /* TODO: Add checking here */ + return local_add_AT_address(dbg, ownerdie, attr, + dbg->de_ar_data_attribute_form, + pc_value, + sym_index, + error); +} + + + +Dwarf_P_Attribute +dwarf_add_AT_block( + Dwarf_P_Debug dbg, + Dwarf_P_Die ownerdie, + Dwarf_Half attr, + Dwarf_Small *block_data, + Dwarf_Unsigned block_size, + Dwarf_Error *error +) +{ + Dwarf_P_Attribute new_attr; + int result; + char encode_buffer[ENCODE_SPACE_NEEDED]; + int len_size; + char * attrdata; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return((Dwarf_P_Attribute)DW_DLV_BADADDR); + } + + if (ownerdie == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); + return((Dwarf_P_Attribute)DW_DLV_BADADDR); + } + + /* I don't mess with block1, block2, block4, not worth the effort */ + + /* So, encode the length into LEB128 */ + result = _dwarf_pro_encode_leb128_nm(block_size, &len_size, + encode_buffer,sizeof(encode_buffer)); + if (result != DW_DLV_OK) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return((Dwarf_P_Attribute)DW_DLV_BADADDR); + } + + /* Allocate the new attribute */ + new_attr = (Dwarf_P_Attribute) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); + if (new_attr == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return((Dwarf_P_Attribute)DW_DLV_BADADDR); + } + + /* Fill in the attribute */ + new_attr->ar_attribute = attr; + new_attr->ar_attribute_form = DW_FORM_block; + new_attr->ar_nbytes = len_size + block_size; + new_attr->ar_next = 0; + + new_attr->ar_data = attrdata = (char *) + _dwarf_p_get_alloc(dbg, len_size + block_size); + if (new_attr->ar_data == NULL) { + /* free the block we got earlier */ + _dwarf_p_dealloc(dbg, (unsigned char *) new_attr); + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return((Dwarf_P_Attribute)DW_DLV_BADADDR); + } + + /* write length and data to attribute data buffer */ + memcpy(attrdata, encode_buffer, len_size); + attrdata += len_size; + memcpy(attrdata, block_data, block_size); + + /* add attribute to the die */ + _dwarf_pro_add_at_to_die(ownerdie, new_attr); + + return new_attr; +} + + +/* + This function adds attributes whose value + is an unsigned constant. It determines the + size of the value field from the value of + the constant. +*/ +Dwarf_P_Attribute +dwarf_add_AT_unsigned_const(Dwarf_P_Debug dbg, + Dwarf_P_Die ownerdie, + Dwarf_Half attr, + Dwarf_Unsigned value, Dwarf_Error * error) +{ + Dwarf_P_Attribute new_attr; + Dwarf_Half attr_form; + Dwarf_Small size; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + if (ownerdie == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + switch (attr) { + case DW_AT_ordering: + case DW_AT_byte_size: + case DW_AT_bit_offset: + case DW_AT_bit_size: + case DW_AT_inline: + case DW_AT_language: + case DW_AT_visibility: + case DW_AT_virtuality: + case DW_AT_accessibility: + case DW_AT_address_class: + case DW_AT_calling_convention: + case DW_AT_encoding: + case DW_AT_identifier_case: + case DW_AT_MIPS_loop_unroll_factor: + case DW_AT_MIPS_software_pipeline_depth: + break; + + case DW_AT_decl_column: + case DW_AT_decl_file: + case DW_AT_decl_line: + case DW_AT_const_value: + case DW_AT_start_scope: + case DW_AT_stride_size: + case DW_AT_count: + case DW_AT_associated: + case DW_AT_allocated: + case DW_AT_upper_bound: + case DW_AT_lower_bound: + case DW_AT_call_file: + case DW_AT_call_line: + break; + + default: { + if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) { + _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + break; + } + } + + /* + Compute the number of bytes needed to hold constant. */ + if (value <= UCHAR_MAX) { + attr_form = DW_FORM_data1; + size = 1; + } else if (value <= USHRT_MAX) { + attr_form = DW_FORM_data2; + size = 2; + } else if (value <= UINT_MAX) { + attr_form = DW_FORM_data4; + size = 4; + } else { + attr_form = DW_FORM_data8; + size = 8; + } + + new_attr = (Dwarf_P_Attribute) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); + if (new_attr == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + new_attr->ar_attribute = attr; + new_attr->ar_attribute_form = attr_form; + new_attr->ar_rel_type = R_MIPS_NONE; + new_attr->ar_reloc_len = 0; /* irrelevant: unused with R_MIPS_NONE */ + new_attr->ar_nbytes = size; + new_attr->ar_next = 0; + + new_attr->ar_data = (char *) + _dwarf_p_get_alloc(dbg, size); + if (new_attr->ar_data == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + WRITE_UNALIGNED(dbg, new_attr->ar_data, + (const void *) &value, sizeof(value), size); + + /* add attribute to the die */ + _dwarf_pro_add_at_to_die(ownerdie, new_attr); + return new_attr; +} + + +/* + This function adds attributes whose value + is an signed constant. It determines the + size of the value field from the value of + the constant. +*/ +Dwarf_P_Attribute +dwarf_add_AT_signed_const(Dwarf_P_Debug dbg, + Dwarf_P_Die ownerdie, + Dwarf_Half attr, + Dwarf_Signed value, Dwarf_Error * error) +{ + Dwarf_P_Attribute new_attr; + Dwarf_Half attr_form; + Dwarf_Small size; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + if (ownerdie == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + switch (attr) { + case DW_AT_lower_bound: + case DW_AT_upper_bound: + case DW_AT_const_value: + case DW_AT_bit_offset: + case DW_AT_bit_size: + case DW_AT_byte_size: + case DW_AT_count: + case DW_AT_byte_stride: + case DW_AT_bit_stride: + case DW_AT_allocated: + case DW_AT_associated: + break; + + default:{ + if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) { + _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + } + break; + } + + /* + Compute the number of bytes needed to hold constant. */ + if (value >= SCHAR_MIN && value <= SCHAR_MAX) { + attr_form = DW_FORM_data1; + size = 1; + } else if (value >= SHRT_MIN && value <= SHRT_MAX) { + attr_form = DW_FORM_data2; + size = 2; + } else if (value >= INT_MIN && value <= INT_MAX) { + attr_form = DW_FORM_data4; + size = 4; + } else { + attr_form = DW_FORM_data8; + size = 8; + } + + new_attr = (Dwarf_P_Attribute) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); + if (new_attr == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + new_attr->ar_attribute = attr; + new_attr->ar_attribute_form = attr_form; + new_attr->ar_rel_type = R_MIPS_NONE; + new_attr->ar_reloc_len = 0; /* irrelevant: unused with R_MIPS_NONE */ + new_attr->ar_nbytes = size; + new_attr->ar_next = 0; + + new_attr->ar_data = (char *) + _dwarf_p_get_alloc(dbg, size); + if (new_attr->ar_data == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + WRITE_UNALIGNED(dbg, new_attr->ar_data, + (const void *) &value, sizeof(value), size); + + /* add attribute to the die */ + _dwarf_pro_add_at_to_die(ownerdie, new_attr); + return new_attr; +} + + +/* + This function adds attributes whose value + is a location expression. +*/ +Dwarf_P_Attribute +dwarf_add_AT_location_expr(Dwarf_P_Debug dbg, + Dwarf_P_Die ownerdie, + Dwarf_Half attr, + Dwarf_P_Expr loc_expr, Dwarf_Error * error) +{ + char encode_buffer[ENCODE_SPACE_NEEDED]; + int res; + Dwarf_P_Attribute new_attr; + Dwarf_Half attr_form; + char *len_str = 0; + int len_size; + int block_size; + char *block_dest_ptr; + int do_len_as_int = 0; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + if (ownerdie == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + if (loc_expr == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_EXPR_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + if (loc_expr->ex_dbg != dbg) { + _dwarf_p_error(dbg, error, DW_DLE_LOC_EXPR_BAD); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + block_size = loc_expr->ex_next_byte_offset; + + switch (attr) { + case DW_AT_location: + case DW_AT_string_length: + case DW_AT_const_value: + case DW_AT_use_location: + case DW_AT_return_addr: + case DW_AT_data_member_location: + case DW_AT_frame_base: + case DW_AT_static_link: + case DW_AT_vtable_elem_location: + case DW_AT_lower_bound: + case DW_AT_upper_bound: + case DW_AT_count: + case DW_AT_associated: + case DW_AT_allocated: + case DW_AT_data_location: + case DW_AT_byte_stride: + case DW_AT_bit_stride: + case DW_AT_byte_size: + case DW_AT_bit_size: + break; + + default: + if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) { + _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + break; + } + + /* + Compute the number of bytes needed to hold constant. */ + if (block_size <= UCHAR_MAX) { + attr_form = DW_FORM_block1; + len_size = 1; + do_len_as_int = 1; + } else if (block_size <= USHRT_MAX) { + attr_form = DW_FORM_block2; + len_size = 2; + do_len_as_int = 1; + } else if (block_size <= UINT_MAX) { + attr_form = DW_FORM_block4; + len_size = 4; + do_len_as_int = 1; + } else { + attr_form = DW_FORM_block; + res = _dwarf_pro_encode_leb128_nm(block_size, &len_size, + encode_buffer, + sizeof(encode_buffer)); + if (res != DW_DLV_OK) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + len_str = (char *) encode_buffer; + } + + new_attr = (Dwarf_P_Attribute) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); + if (new_attr == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + new_attr->ar_attribute = attr; + new_attr->ar_attribute_form = attr_form; + new_attr->ar_reloc_len = dbg->de_pointer_size; + if (loc_expr->ex_reloc_sym_index != NO_ELF_SYM_INDEX) { + new_attr->ar_rel_type = dbg->de_ptr_reloc; + } else { + new_attr->ar_rel_type = R_MIPS_NONE; + } + new_attr->ar_rel_symidx = loc_expr->ex_reloc_sym_index; + new_attr->ar_rel_offset = + (Dwarf_Word) loc_expr->ex_reloc_offset + len_size; + + new_attr->ar_nbytes = block_size + len_size; + + new_attr->ar_next = 0; + new_attr->ar_data = block_dest_ptr = + (char *) _dwarf_p_get_alloc(dbg, block_size + len_size); + if (new_attr->ar_data == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + if (do_len_as_int) { + WRITE_UNALIGNED(dbg, block_dest_ptr, (const void *) &block_size, + sizeof(block_size), len_size); + } else { + /* Is uleb number form, DW_FORM_block. See above. */ + memcpy(block_dest_ptr, len_str, len_size); + } + block_dest_ptr += len_size; + memcpy(block_dest_ptr, &(loc_expr->ex_byte_stream[0]), block_size); + + /* add attribute to the die */ + _dwarf_pro_add_at_to_die(ownerdie, new_attr); + return new_attr; +} + + +/* + This function adds attributes of reference class. + The references here are local CU references, + not DW_FORM_ref_addr. + The offset field is 4 bytes for 32-bit objects, + and 8-bytes for 64-bit objects. Otherdie is the + that is referenced by ownerdie. + + For reference attributes, the ar_data and ar_nbytes + are not needed. Instead, the ar_ref_die points to + the other die, and its di_offset value is used as + the reference value. +*/ +Dwarf_P_Attribute +dwarf_add_AT_reference(Dwarf_P_Debug dbg, + Dwarf_P_Die ownerdie, + Dwarf_Half attr, + Dwarf_P_Die otherdie, Dwarf_Error * error) +{ + Dwarf_P_Attribute new_attr; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + if (ownerdie == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + if (otherdie == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + switch (attr) { + case DW_AT_specification: + case DW_AT_discr: + case DW_AT_common_reference: + case DW_AT_import: + case DW_AT_containing_type: + case DW_AT_default_value: + case DW_AT_abstract_origin: + case DW_AT_friend: + case DW_AT_priority: + case DW_AT_type: + case DW_AT_lower_bound: + case DW_AT_upper_bound: + case DW_AT_count: + case DW_AT_associated: + case DW_AT_allocated: + case DW_AT_bit_offset: + case DW_AT_bit_size: + case DW_AT_byte_size: + case DW_AT_sibling: + case DW_AT_bit_stride: + case DW_AT_byte_stride: + case DW_AT_namelist_item: + break; + + default: + if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) { + _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + break; + } + + new_attr = (Dwarf_P_Attribute) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); + if (new_attr == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + new_attr->ar_attribute = attr; + new_attr->ar_attribute_form = dbg->de_ar_ref_attr_form; + new_attr->ar_nbytes = dbg->de_offset_size; + new_attr->ar_reloc_len = dbg->de_offset_size; + new_attr->ar_ref_die = otherdie; + new_attr->ar_rel_type = R_MIPS_NONE; + new_attr->ar_next = 0; + + /* add attribute to the die */ + _dwarf_pro_add_at_to_die(ownerdie, new_attr); + return new_attr; +} + + +/* + This function adds attributes of the flag class. +*/ +Dwarf_P_Attribute +dwarf_add_AT_flag(Dwarf_P_Debug dbg, + Dwarf_P_Die ownerdie, + Dwarf_Half attr, + Dwarf_Small flag, Dwarf_Error * error) +{ + Dwarf_P_Attribute new_attr; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + if (ownerdie == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + +#if 0 + switch (attr) { + case DW_AT_is_optional: + case DW_AT_artificial: + case DW_AT_declaration: + case DW_AT_external: + case DW_AT_prototyped: + case DW_AT_variable_parameter: + break; + + default: + if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) { + _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + break; + } +#endif + + new_attr = (Dwarf_P_Attribute) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); + if (new_attr == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + new_attr->ar_attribute = attr; + new_attr->ar_attribute_form = DW_FORM_flag; + new_attr->ar_nbytes = 1; + new_attr->ar_reloc_len = 0; /* not used */ + new_attr->ar_rel_type = R_MIPS_NONE; + new_attr->ar_next = 0; + + new_attr->ar_data = (char *) + _dwarf_p_get_alloc(dbg, 1); + if (new_attr->ar_data == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + memcpy(new_attr->ar_data, &flag, 1); + + /* add attribute to the die */ + _dwarf_pro_add_at_to_die(ownerdie, new_attr); + return new_attr; +} + + +/* + This function adds values of attributes + belonging to the string class. +*/ +Dwarf_P_Attribute +dwarf_add_AT_string(Dwarf_P_Debug dbg, + Dwarf_P_Die ownerdie, + Dwarf_Half attr, char *string, Dwarf_Error * error) +{ + Dwarf_P_Attribute new_attr; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + if (ownerdie == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + new_attr = (Dwarf_P_Attribute) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); + if (new_attr == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + switch (attr) { + case DW_AT_name: + case DW_AT_comp_dir: + case DW_AT_const_value: + case DW_AT_producer: + break; + + default: + if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) { + _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + break; + } + + new_attr->ar_attribute = attr; + new_attr->ar_attribute_form = DW_FORM_string; + new_attr->ar_nbytes = strlen(string) + 1; + new_attr->ar_next = 0; + + new_attr->ar_data = + (char *) _dwarf_p_get_alloc(dbg, strlen(string)+1); + if (new_attr->ar_data == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + strcpy(new_attr->ar_data, string); + new_attr->ar_rel_type = R_MIPS_NONE; + new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */ + + /* add attribute to the die */ + _dwarf_pro_add_at_to_die(ownerdie, new_attr); + return new_attr; +} + + +Dwarf_P_Attribute +dwarf_add_AT_const_value_string(Dwarf_P_Die ownerdie, + char *string_value, Dwarf_Error * error) +{ + Dwarf_P_Attribute new_attr; + + if (ownerdie == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + new_attr = (Dwarf_P_Attribute) + _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s)); + if (new_attr == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + new_attr->ar_attribute = DW_AT_const_value; + new_attr->ar_attribute_form = DW_FORM_string; + new_attr->ar_nbytes = strlen(string_value) + 1; + new_attr->ar_next = 0; + + new_attr->ar_data = + (char *) _dwarf_p_get_alloc(ownerdie->di_dbg, strlen(string_value)+1); + if (new_attr->ar_data == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + strcpy(new_attr->ar_data, string_value); + new_attr->ar_rel_type = R_MIPS_NONE; + new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */ + + /* add attribute to the die */ + _dwarf_pro_add_at_to_die(ownerdie, new_attr); + return new_attr; +} + + +Dwarf_P_Attribute +dwarf_add_AT_producer(Dwarf_P_Die ownerdie, + char *producer_string, Dwarf_Error * error) +{ + Dwarf_P_Attribute new_attr; + + if (ownerdie == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + new_attr = (Dwarf_P_Attribute) + _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s)); + if (new_attr == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + new_attr->ar_attribute = DW_AT_producer; + new_attr->ar_attribute_form = DW_FORM_string; + new_attr->ar_nbytes = strlen(producer_string) + 1; + new_attr->ar_next = 0; + + new_attr->ar_data = + (char *) _dwarf_p_get_alloc(ownerdie->di_dbg, strlen(producer_string)+1); + if (new_attr->ar_data == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + strcpy(new_attr->ar_data, producer_string); + new_attr->ar_rel_type = R_MIPS_NONE; + new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */ + + /* add attribute to the die */ + _dwarf_pro_add_at_to_die(ownerdie, new_attr); + return new_attr; +} + + +Dwarf_P_Attribute +dwarf_add_AT_const_value_signedint(Dwarf_P_Die ownerdie, + Dwarf_Signed signed_value, + Dwarf_Error * error) +{ + Dwarf_P_Attribute new_attr; + int leb_size; + char encode_buffer[ENCODE_SPACE_NEEDED]; + int res; + + if (ownerdie == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + new_attr = (Dwarf_P_Attribute) + _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s)); + if (new_attr == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + new_attr->ar_attribute = DW_AT_const_value; + new_attr->ar_attribute_form = DW_FORM_sdata; + new_attr->ar_rel_type = R_MIPS_NONE; + new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */ + new_attr->ar_next = 0; + + res = _dwarf_pro_encode_signed_leb128_nm(signed_value, &leb_size, + encode_buffer, + sizeof(encode_buffer)); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + new_attr->ar_data = (char *) + _dwarf_p_get_alloc(ownerdie->di_dbg, leb_size); + if (new_attr->ar_data == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + memcpy(new_attr->ar_data, encode_buffer, leb_size); + new_attr->ar_nbytes = leb_size; + + /* add attribute to the die */ + _dwarf_pro_add_at_to_die(ownerdie, new_attr); + return new_attr; +} + + +Dwarf_P_Attribute +dwarf_add_AT_const_value_unsignedint(Dwarf_P_Die ownerdie, + Dwarf_Unsigned unsigned_value, + Dwarf_Error * error) +{ + Dwarf_P_Attribute new_attr; + int leb_size; + char encode_buffer[ENCODE_SPACE_NEEDED]; + int res; + + if (ownerdie == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + new_attr = (Dwarf_P_Attribute) + _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s)); + if (new_attr == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + + new_attr->ar_attribute = DW_AT_const_value; + new_attr->ar_attribute_form = DW_FORM_udata; + new_attr->ar_rel_type = R_MIPS_NONE; + new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */ + new_attr->ar_next = 0; + + res = _dwarf_pro_encode_leb128_nm(unsigned_value, &leb_size, + encode_buffer, + sizeof(encode_buffer)); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + new_attr->ar_data = (char *) + _dwarf_p_get_alloc(ownerdie->di_dbg, leb_size); + if (new_attr->ar_data == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); + return ((Dwarf_P_Attribute) DW_DLV_BADADDR); + } + memcpy(new_attr->ar_data, encode_buffer, leb_size); + new_attr->ar_nbytes = leb_size; + + /* add attribute to the die */ + _dwarf_pro_add_at_to_die(ownerdie, new_attr); + return new_attr; +} diff --git a/usr/src/lib/libdwarf/common/pro_frame.c b/usr/src/lib/libdwarf/common/pro_frame.c new file mode 100644 index 0000000000..bd1ef6a637 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_frame.c @@ -0,0 +1,598 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include +#include +#include +#include "pro_incl.h" +#include "pro_frame.h" + +static void _dwarf_pro_add_to_fde(Dwarf_P_Fde fde, + Dwarf_P_Frame_Pgm inst); + +/*------------------------------------------------------------------------- + This function adds a cie struct to the debug pointer. Its in the + form of a linked list. + augmenter: string reps augmentation (implementation defined) + code_align: alignment of code + data_align: alignment of data + init_bytes: byts having initial instructions + init_n_bytes: number of bytes of initial instructions +--------------------------------------------------------------------------*/ +Dwarf_Unsigned +dwarf_add_frame_cie(Dwarf_P_Debug dbg, + char *augmenter, + Dwarf_Small code_align, + Dwarf_Small data_align, + Dwarf_Small return_reg, + Dwarf_Ptr init_bytes, + Dwarf_Unsigned init_n_bytes, Dwarf_Error * error) +{ + Dwarf_P_Cie curcie; + + if (dbg->de_frame_cies == NULL) { + dbg->de_frame_cies = (Dwarf_P_Cie) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s)); + if (dbg->de_frame_cies == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_NOCOUNT); + } + curcie = dbg->de_frame_cies; + dbg->de_n_cie = 1; + dbg->de_last_cie = curcie; + } else { + curcie = dbg->de_last_cie; + curcie->cie_next = (Dwarf_P_Cie) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s)); + if (curcie->cie_next == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_NOCOUNT); + } + curcie = curcie->cie_next; + dbg->de_n_cie++; + dbg->de_last_cie = curcie; + } + curcie->cie_version = DW_CIE_VERSION; + curcie->cie_aug = augmenter; + curcie->cie_code_align = code_align; + curcie->cie_data_align = data_align; + curcie->cie_ret_reg = return_reg; + curcie->cie_inst = (char *) init_bytes; + curcie->cie_inst_bytes = (long) init_n_bytes; + curcie->cie_next = NULL; + return dbg->de_n_cie; +} + + +/*------------------------------------------------------------------------- + This functions adds a fde struct to the debug pointer. Its in the + form of a linked list. + die: subprogram/function die corresponding to this fde + cie: cie referred to by this fde, obtained from call to + add_frame_cie() routine. + virt_addr: beginning address + code_len: length of code reps by the fde +--------------------------------------------------------------------------*/ + /*ARGSUSED*/ /* pretend all args used */ + Dwarf_Unsigned +dwarf_add_frame_fde(Dwarf_P_Debug dbg, + Dwarf_P_Fde fde, + Dwarf_P_Die die, + Dwarf_Unsigned cie, + Dwarf_Unsigned virt_addr, + Dwarf_Unsigned code_len, + Dwarf_Unsigned symidx, Dwarf_Error * error) +{ + return dwarf_add_frame_fde_b(dbg, fde, die, cie, virt_addr, + code_len, symidx, 0, 0, error); +} + +/*ARGSUSED10*/ +Dwarf_Unsigned +dwarf_add_frame_fde_b(Dwarf_P_Debug dbg, + Dwarf_P_Fde fde, + Dwarf_P_Die die, + Dwarf_Unsigned cie, + Dwarf_Unsigned virt_addr, + Dwarf_Unsigned code_len, + Dwarf_Unsigned symidx, + Dwarf_Unsigned symidx_of_end, + Dwarf_Addr offset_from_end_sym, + Dwarf_Error * error) +{ + Dwarf_P_Fde curfde; + + fde->fde_die = die; + fde->fde_cie = (long) cie; + fde->fde_initloc = virt_addr; + fde->fde_r_symidx = symidx; + fde->fde_addr_range = code_len; + fde->fde_offset_into_exception_tables = DW_DLX_NO_EH_OFFSET; + fde->fde_exception_table_symbol = 0; + fde->fde_end_symbol_offset = offset_from_end_sym; + fde->fde_end_symbol = symidx_of_end; + fde->fde_dbg = dbg; + + curfde = dbg->de_last_fde; + if (curfde == NULL) { + dbg->de_frame_fdes = fde; + dbg->de_last_fde = fde; + dbg->de_n_fde = 1; + } else { + curfde->fde_next = fde; + dbg->de_last_fde = fde; + dbg->de_n_fde++; + } + return dbg->de_n_fde; +} + +/*------------------------------------------------------------------------- + This functions adds information to an fde. The fde is + linked into the linked list of fde's maintained in the Dwarf_P_Debug + structure. + dbg: The debug descriptor. + fde: The fde to be added. + die: subprogram/function die corresponding to this fde + cie: cie referred to by this fde, obtained from call to + add_frame_cie() routine. + virt_addr: beginning address + code_len: length of code reps by the fde + symidx: The symbol id of the symbol wrt to which relocation needs + to be performed for 'virt_addr'. + offset_into_exception_tables: The start of exception tables for + this function (indicated as an offset into the exception + tables). A value of -1 indicates that there is no exception + table entries associated with this function. + exception_table_symbol: The symbol id of the section for exception + tables wrt to which the offset_into_exception_tables will + be relocated. +--------------------------------------------------------------------------*/ +Dwarf_Unsigned +dwarf_add_frame_info(Dwarf_P_Debug dbg, + Dwarf_P_Fde fde, + Dwarf_P_Die die, + Dwarf_Unsigned cie, + Dwarf_Unsigned virt_addr, + Dwarf_Unsigned code_len, + Dwarf_Unsigned symidx, + Dwarf_Signed offset_into_exception_tables, + Dwarf_Unsigned exception_table_symbol, + Dwarf_Error * error) +{ + + return dwarf_add_frame_info_b(dbg, fde, die, cie, virt_addr, + code_len, symidx, + /* end_symbol */ 0, + /* offset_from_end */ 0, + offset_into_exception_tables, + exception_table_symbol, error); + +} + + /*ARGSUSED*/ /* pretend all args used */ +Dwarf_Unsigned +dwarf_add_frame_info_b(Dwarf_P_Debug dbg, + Dwarf_P_Fde fde, + Dwarf_P_Die die, + Dwarf_Unsigned cie, + Dwarf_Unsigned virt_addr, + Dwarf_Unsigned code_len, + Dwarf_Unsigned symidx, + Dwarf_Unsigned end_symidx, + Dwarf_Unsigned offset_from_end_symbol, + Dwarf_Signed offset_into_exception_tables, + Dwarf_Unsigned exception_table_symbol, + Dwarf_Error * error) +{ + Dwarf_P_Fde curfde; + + fde->fde_die = die; + fde->fde_cie = (long) cie; + fde->fde_initloc = virt_addr; + fde->fde_r_symidx = symidx; + fde->fde_addr_range = code_len; + fde->fde_offset_into_exception_tables = + offset_into_exception_tables; + fde->fde_exception_table_symbol = exception_table_symbol; + fde->fde_end_symbol_offset = offset_from_end_symbol; + fde->fde_end_symbol = end_symidx; + fde->fde_dbg = dbg; + + curfde = dbg->de_last_fde; + if (curfde == NULL) { + dbg->de_frame_fdes = fde; + dbg->de_last_fde = fde; + dbg->de_n_fde = 1; + } else { + curfde->fde_next = fde; + dbg->de_last_fde = fde; + dbg->de_n_fde++; + } + return dbg->de_n_fde; +} + +/* This is an alternate to inserting frame instructions + one instruction at a time. But use either this + or instruction level, not both in one fde. */ +int +dwarf_insert_fde_inst_bytes(Dwarf_P_Debug dbg, + Dwarf_P_Fde fde,Dwarf_Unsigned len, Dwarf_Ptr ibytes, + Dwarf_Error *error) +{ + if( len == 0) { + return DW_DLV_OK; + } + if(fde->fde_block || fde->fde_inst) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DUPLICATE_INST_BLOCK, + (int)DW_DLV_BADADDR); + } + fde->fde_block = (Dwarf_Ptr)_dwarf_p_get_alloc(dbg, len); + memcpy(fde->fde_block,ibytes,len); + fde->fde_inst_block_size = len; + fde->fde_n_bytes += len; + return DW_DLV_OK; +} + + + +/*------------------------------------------------------------------- + Create a new fde. +---------------------------------------------------------------------*/ +Dwarf_P_Fde +dwarf_new_fde(Dwarf_P_Debug dbg, Dwarf_Error * error) +{ + Dwarf_P_Fde fde; + + fde = (Dwarf_P_Fde) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Fde_s)); + if (fde == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_FDE_ALLOC, + (Dwarf_P_Fde) DW_DLV_BADADDR); + } + + fde->fde_uwordb_size = dbg->de_offset_size; + + return fde; +} + + +/*------------------------------------------------------------------------ + Add a cfe_offset instruction to the fde passed in. +-------------------------------------------------------------------------*/ +Dwarf_P_Fde +dwarf_fde_cfa_offset(Dwarf_P_Fde fde, + Dwarf_Unsigned reg, + Dwarf_Signed offset, Dwarf_Error * error) +{ + Dwarf_Ubyte opc, regno; + char *ptr; + Dwarf_P_Frame_Pgm curinst; + int nbytes; + int res; + char buff1[ENCODE_SPACE_NEEDED]; + Dwarf_P_Debug dbg = fde->fde_dbg; + + curinst = (Dwarf_P_Frame_Pgm) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s)); + if (curinst == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_FPGM_ALLOC, + (Dwarf_P_Fde) DW_DLV_BADADDR); + } + opc = DW_CFA_offset; + regno = reg; + if (regno & 0xc0) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_REGNO_OVFL, + (Dwarf_P_Fde) DW_DLV_BADADDR); + } + opc = opc | regno; /* lower 6 bits are register number */ + curinst->dfp_opcode = opc; + res = _dwarf_pro_encode_leb128_nm(offset, &nbytes, + buff1, sizeof(buff1)); + if (res != DW_DLV_OK) { + _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); + return ((Dwarf_P_Fde) DW_DLV_BADADDR); + } + ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes); + if (ptr == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); + return ((Dwarf_P_Fde) DW_DLV_BADADDR); + } + memcpy(ptr, buff1, nbytes); + + curinst->dfp_args = ptr; + curinst->dfp_nbytes = nbytes; + curinst->dfp_next = NULL; + + _dwarf_pro_add_to_fde(fde, curinst); + return fde; +} + +/* + Generic routine to add opcode to fde instructions. val1 and + val2 are parameters whose interpretation depends on the 'op'. + + This does not work properly for DW_DLC_SYMBOLIC_RELOCATIONS + for DW_CFA_set_loc or DW_DVA_advance_loc* 'op', as + these ops normally are addresses or (DW_CFA_set_loc) + or code lengths (DW_DVA_advance_loc*) and such must be + represented with relocations and symbol indices for + DW_DLC_SYMBOLIC_RELOCATIONS. + + This does not treat all DW_CFA instructions yet. + + For certain operations a val? value must be + signed (though passed in as unsigned here). + + Currently this does not check that the frame + version is 3(for dwarf3) or 4 (for dwarf4) + when applying operations that are only valid for + dwarf3 or dwarf4. + +*/ +Dwarf_P_Fde +dwarf_add_fde_inst(Dwarf_P_Fde fde, + Dwarf_Small op, + Dwarf_Unsigned val1, + Dwarf_Unsigned val2, Dwarf_Error * error) +{ + Dwarf_P_Frame_Pgm curinst; + int nbytes, nbytes1, nbytes2; + Dwarf_Ubyte db; + Dwarf_Half dh; + Dwarf_Word dw; + Dwarf_Unsigned du; + char *ptr; + int res; + char buff1[ENCODE_SPACE_NEEDED]; + char buff2[ENCODE_SPACE_NEEDED]; + Dwarf_P_Debug dbg = fde->fde_dbg; + /* This is a hack telling the code when to transform + a value to a signed leb number. */ + int signed_second = 0; + int signed_first = 0; + + + nbytes = 0; + ptr = NULL; + curinst = (Dwarf_P_Frame_Pgm) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s)); + if (curinst == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_FPGM_ALLOC); + return ((Dwarf_P_Fde) DW_DLV_BADADDR); + } + + switch (op) { + + case DW_CFA_advance_loc: + if (val1 <= 0x3f) { + db = val1; + op |= db; + } + /* test not portable FIX */ + else if (val1 <= UCHAR_MAX) { + op = DW_CFA_advance_loc1; + db = val1; + ptr = (char *) _dwarf_p_get_alloc(dbg, 1); + if (ptr == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); + return ((Dwarf_P_Fde) DW_DLV_BADADDR); + } + memcpy((void *) ptr, (const void *) &db, 1); + nbytes = 1; + } + /* test not portable FIX */ + else if (val1 <= USHRT_MAX) { + op = DW_CFA_advance_loc2; + dh = val1; + ptr = (char *) _dwarf_p_get_alloc(dbg, 2); + if (ptr == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); + return ((Dwarf_P_Fde) DW_DLV_BADADDR); + } + memcpy((void *) ptr, (const void *) &dh, 2); + nbytes = 2; + } + /* test not portable FIX */ + else if (val1 <= ULONG_MAX) { + op = DW_CFA_advance_loc4; + dw = (Dwarf_Word) val1; + ptr = (char *) _dwarf_p_get_alloc(dbg, 4); + if (ptr == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); + return ((Dwarf_P_Fde) DW_DLV_BADADDR); + } + memcpy((void *) ptr, (const void *) &dw, 4); + nbytes = 4; + } else { + op = DW_CFA_MIPS_advance_loc8; + du = val1; + ptr = + (char *) _dwarf_p_get_alloc(dbg, + sizeof(Dwarf_Unsigned)); + if (ptr == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); + return ((Dwarf_P_Fde) DW_DLV_BADADDR); + } + memcpy((void *) ptr, (const void *) &du, 8); + nbytes = 8; + } + break; + + case DW_CFA_offset: + if (val1 <= MAX_6_BIT_VALUE) { + db = val1; + op |= db; + res = _dwarf_pro_encode_leb128_nm(val2, &nbytes, + buff1, sizeof(buff1)); + if (res != DW_DLV_OK) { + _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); + return ((Dwarf_P_Fde) DW_DLV_BADADDR); + } + ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes); + if (ptr == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); + return ((Dwarf_P_Fde) DW_DLV_BADADDR); + } + memcpy(ptr, buff1, nbytes); + + } else { + op = DW_CFA_offset_extended; + goto two_leb; + } + break; + case DW_CFA_offset_extended_sf: /* DWARF3 */ + signed_second = 1; + goto two_leb; + case DW_CFA_offset_extended: + goto two_leb; + + case DW_CFA_undefined: + case DW_CFA_same_value: + goto one_leb; + + case DW_CFA_val_offset: + goto two_leb; + case DW_CFA_val_offset_sf: + signed_second = 1; + goto two_leb; + case DW_CFA_def_cfa_sf: + signed_second = 1; + goto two_leb; + case DW_CFA_register: + case DW_CFA_def_cfa: + two_leb: + res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1, + buff1, sizeof(buff1)); + if (res != DW_DLV_OK) { + _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); + return ((Dwarf_P_Fde) DW_DLV_BADADDR); + } + if (!signed_second) { + res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2, + buff2, sizeof(buff2)); + } else { + Dwarf_Signed val2s = val2; + res = _dwarf_pro_encode_signed_leb128_nm(val2s, &nbytes2, + buff2, sizeof(buff2)); + } + + res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2, + buff2, sizeof(buff2)); + if (res != DW_DLV_OK) { + _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); + return ((Dwarf_P_Fde) DW_DLV_BADADDR); + } + + ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes1 + nbytes2); + if (ptr == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); + return ((Dwarf_P_Fde) DW_DLV_BADADDR); + } + memcpy(ptr, buff1, nbytes1); + memcpy(ptr + nbytes1, buff2, nbytes2); + nbytes = nbytes1 + nbytes2; + break; + + case DW_CFA_def_cfa_offset_sf: /* DWARF3 */ + signed_first = 1; + goto one_leb; + case DW_CFA_def_cfa_register: + case DW_CFA_def_cfa_offset: + one_leb: + if(!signed_first) { + res = _dwarf_pro_encode_leb128_nm(val1, &nbytes, + buff1, sizeof(buff1)); + } else { + Dwarf_Signed val1s = val1; + res = _dwarf_pro_encode_signed_leb128_nm(val1s, &nbytes, + buff1, sizeof(buff1)); + } + if (res != DW_DLV_OK) { + _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); + return ((Dwarf_P_Fde) DW_DLV_BADADDR); + } + ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes); + if (ptr == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); + return ((Dwarf_P_Fde) DW_DLV_BADADDR); + } + memcpy(ptr, buff1, nbytes); + break; + case DW_CFA_def_cfa_expression: /* DWARF3 */ + /* FIXME: argument is dwarf expr, not handled yet. */ + case DW_CFA_expression: /* DWARF3 */ + /* First arg: ULEB reg num. 2nd arg dwarf expr in form block. + FIXME: not handled yet. */ + case DW_CFA_val_expression: /* DWARF3f */ + /* First arg: ULEB reg num. 2nd arg dwarf expr in form block. + FIXME: not handled yet. */ + default: + _dwarf_p_error(dbg, error, DW_DLE_DEBUGFRAME_ERROR); + return ((Dwarf_P_Fde) DW_DLV_BADADDR); + } + + curinst->dfp_opcode = op; + curinst->dfp_args = ptr; + curinst->dfp_nbytes = nbytes; + curinst->dfp_next = NULL; + + _dwarf_pro_add_to_fde(fde, curinst); + return fde; +} + + +/*------------------------------------------------------------------------ + Instructions are added to an fde in the form of a linked + list. This function manages the linked list. +-------------------------------------------------------------------------*/ +void +_dwarf_pro_add_to_fde(Dwarf_P_Fde fde, Dwarf_P_Frame_Pgm curinst) +{ + if (fde->fde_last_inst) { + fde->fde_last_inst->dfp_next = curinst; + fde->fde_last_inst = curinst; + fde->fde_n_inst++; + fde->fde_n_bytes += + (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte)); + } else { + fde->fde_last_inst = curinst; + fde->fde_inst = curinst; + fde->fde_n_inst = 1; + fde->fde_n_bytes = + (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte)); + } +} diff --git a/usr/src/lib/libdwarf/common/pro_frame.h b/usr/src/lib/libdwarf/common/pro_frame.h new file mode 100644 index 0000000000..df60d369ed --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_frame.h @@ -0,0 +1,132 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +/* + Largest register value that can be coded into + the opcode since there are only 6 bits in the + register field. +*/ +#define MAX_6_BIT_VALUE 0x3f + +/* + This struct holds debug_frame instructions +*/ +typedef struct Dwarf_P_Frame_Pgm_s *Dwarf_P_Frame_Pgm; + +struct Dwarf_P_Frame_Pgm_s { + Dwarf_Ubyte dfp_opcode; /* opcode - includes reg # */ + char *dfp_args; /* operands */ + int dfp_nbytes; /* number of bytes in args */ +#if 0 + Dwarf_Unsigned dfp_sym_index; /* 0 unless reloc needed */ +#endif + Dwarf_P_Frame_Pgm dfp_next; +}; + + +/* + This struct has cie related information. Used to gather data + from user program, and later to transform to disk form +*/ +struct Dwarf_P_Cie_s { + Dwarf_Ubyte cie_version; + char *cie_aug; /* augmentation */ + Dwarf_Ubyte cie_code_align; /* alignment of code */ + Dwarf_Sbyte cie_data_align; + Dwarf_Ubyte cie_ret_reg; /* return register # */ + char *cie_inst; /* initial instruction */ + long cie_inst_bytes; + /* no of init_inst */ + Dwarf_P_Cie cie_next; +}; + + +/* producer fields */ +struct Dwarf_P_Fde_s { + Dwarf_Unsigned fde_unused1; + + /* function/subr die for this fde */ + Dwarf_P_Die fde_die; + + /* index to asso. cie */ + Dwarf_Word fde_cie; + + /* Address of first location of the code this frame applies to If + fde_end_symbol non-zero, this represents the offset from the + symbol indicated by fde_r_symidx */ + Dwarf_Addr fde_initloc; + + /* Relocation symbol for address of the code this frame applies to. + */ + Dwarf_Unsigned fde_r_symidx; + + /* Bytes of instr for this fde, if known */ + Dwarf_Unsigned fde_addr_range; + + /* linked list of instructions we will put in fde. */ + Dwarf_P_Frame_Pgm fde_inst; + + /* number of instructions in fde */ + long fde_n_inst; + + /* number of bytes of inst in fde */ + long fde_n_bytes; + + /* offset into exception table for this function. */ + Dwarf_Signed fde_offset_into_exception_tables; + + /* The symbol for the exception table elf section. */ + Dwarf_Unsigned fde_exception_table_symbol; + + /* pointer to last inst */ + Dwarf_P_Frame_Pgm fde_last_inst; + + Dwarf_P_Fde fde_next; + + /* The symbol and offset of the end symbol. When fde_end_symbol is + non-zero we must represent the */ + Dwarf_Addr fde_end_symbol_offset; + Dwarf_Unsigned fde_end_symbol; + + int fde_uwordb_size; + Dwarf_P_Debug fde_dbg; + + /* If fde_block is non-null, then it is the set of instructions. + so we should use it rather than fde_inst. */ + Dwarf_Unsigned fde_inst_block_size; + void *fde_block; +}; diff --git a/usr/src/lib/libdwarf/common/pro_funcs.c b/usr/src/lib/libdwarf/common/pro_funcs.c new file mode 100644 index 0000000000..8ff05500bb --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_funcs.c @@ -0,0 +1,62 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include +#include +#ifdef HAVE_ELFACCESS_H +#include +#endif +#include "pro_incl.h" +#include "pro_section.h" + +/* + This function adds another function name to the + list of function names for the given Dwarf_P_Debug. + It returns 0 on error, and 1 otherwise. +*/ +Dwarf_Unsigned +dwarf_add_funcname(Dwarf_P_Debug dbg, + Dwarf_P_Die die, + char *function_name, Dwarf_Error * error) +{ + return + _dwarf_add_simple_name_entry(dbg, die, function_name, + dwarf_snk_funcname, error); + +} diff --git a/usr/src/lib/libdwarf/common/pro_incl.h b/usr/src/lib/libdwarf/common/pro_incl.h new file mode 100644 index 0000000000..10bce470c2 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_incl.h @@ -0,0 +1,92 @@ +/* + + Copyright (C) 2000,2002,2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2008-2010 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + +#ifdef HAVE_ELF_H +#include +#elif defined(HAVE_LIBELF_H) +/* On one platform without elf.h this gets Elf32_Rel + type defined (a required type). */ +#include +#endif + +#if defined(sun) +#include +#include +#endif + +/* The target address is given: the place in the source integer + is to be determined. +*/ +#ifdef WORDS_BIGENDIAN +#define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \ + { \ + dbg->de_copy_word(dest, \ + ((char *)source) +srclength-len_out, \ + len_out) ; \ + } + + +#else /* LITTLE ENDIAN */ + +#define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \ + { \ + dbg->de_copy_word( (dest) , \ + ((char *)source) , \ + len_out) ; \ + } +#endif + + +#if defined(sparc) && defined(sun) +#define REL32 Elf32_Rela +#define REL64 Elf64_Rela +#define REL_SEC_PREFIX ".rela" +#else +#define REL32 Elf32_Rel +#define REL64 Elf64_Rel +#define REL_SEC_PREFIX ".rel" +#endif + +#include "dwarf.h" +#include "libdwarf.h" + +#include "pro_opaque.h" +#include "pro_error.h" +#include "pro_util.h" +#include "pro_encode_nm.h" +#include "pro_alloc.h" diff --git a/usr/src/lib/libdwarf/common/pro_init.c b/usr/src/lib/libdwarf/common/pro_init.c new file mode 100644 index 0000000000..d696113a67 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_init.c @@ -0,0 +1,261 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2008-2010 David Anderson, Inc. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include +#include +#include "pro_incl.h" +#include "pro_section.h" /* for MAGIC_SECT_NO */ +#include "pro_reloc_symbolic.h" +#include "pro_reloc_stream.h" + + +static void common_init(Dwarf_P_Debug dbg, Dwarf_Unsigned flags); + +void *_dwarf_memcpy_swap_bytes(void *s1, const void *s2, size_t len); + +/*-------------------------------------------------------------------- + This function sets up a new dwarf producing region. + flags: Indicates type of access method, one of DW_DLC* macros + func(): Used to create a new object file, a call back function + errhand(): Error Handler provided by user + errarg: Argument to errhand() + error: returned error value +--------------------------------------------------------------------*/ + /* We want the following to have an elf section number that matches + 'nothing' */ +static struct Dwarf_P_Section_Data_s init_sect = { + MAGIC_SECT_NO, 0, 0, 0, 0 +}; + +Dwarf_P_Debug +dwarf_producer_init_b(Dwarf_Unsigned flags, + Dwarf_Callback_Func_b func, + Dwarf_Handler errhand, + Dwarf_Ptr errarg, Dwarf_Error * error) +{ + Dwarf_P_Debug dbg; + dbg = (Dwarf_P_Debug) _dwarf_p_get_alloc(NULL, + sizeof(struct + Dwarf_P_Debug_s)); + if (dbg == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, + (Dwarf_P_Debug) DW_DLV_BADADDR); + } + memset((void *) dbg, 0, sizeof(struct Dwarf_P_Debug_s)); + /* For the time being */ + if (func == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_NO_CALLBACK_FUNC, + (Dwarf_P_Debug) DW_DLV_BADADDR); + } + dbg->de_callback_func_b = func; + dbg->de_errhand = errhand; + dbg->de_errarg = errarg; + common_init(dbg, flags); + return dbg; + +} + +Dwarf_P_Debug +dwarf_producer_init(Dwarf_Unsigned flags, + Dwarf_Callback_Func func, + Dwarf_Handler errhand, + Dwarf_Ptr errarg, Dwarf_Error * error) +{ + + Dwarf_P_Debug dbg; + + + + dbg = (Dwarf_P_Debug) _dwarf_p_get_alloc(NULL, + sizeof(struct + Dwarf_P_Debug_s)); + if (dbg == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, + (Dwarf_P_Debug) DW_DLV_BADADDR); + } + memset((void *) dbg, 0, sizeof(struct Dwarf_P_Debug_s)); + /* For the time being */ + if (func == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_NO_CALLBACK_FUNC, + (Dwarf_P_Debug) DW_DLV_BADADDR); + } + dbg->de_callback_func = func; + dbg->de_errhand = errhand; + dbg->de_errarg = errarg; + common_init(dbg, flags); + return dbg; +} +static void +common_init(Dwarf_P_Debug dbg, Dwarf_Unsigned flags) +{ + unsigned int k; + + + dbg->de_version_magic_number = PRO_VERSION_MAGIC; + dbg->de_n_debug_sect = 0; + dbg->de_debug_sects = &init_sect; + dbg->de_current_active_section = &init_sect; + dbg->de_flags = flags; + + /* Now, with flags set, can use 64bit tests */ + + + +#if defined(HAVE_STRICT_DWARF2_32BIT_OFFSET) + /* This is cygnus 32bit offset, as specified in pure dwarf2 v2.0.0. + It is consistent with normal DWARF2/3 generation of always + generating 32 bit offsets. */ + dbg->de_64bit_extension = 0; + dbg->de_pointer_size = (IS_64BIT(dbg) ? 8 : 4); + dbg->de_offset_size = (IS_64BIT(dbg) ? 4 : 4); + dbg->de_ptr_reloc = + IS_64BIT(dbg) ? Get_REL64_isa(dbg) : Get_REL32_isa(dbg); + /* non-MIPS, dwarf lengths and offsets are 32 bits even for 64bit + pointer environments. */ + /* Get_REL32_isa here supports 64-bit-pointer dwarf with pure + dwarf2 v2.0.0 32bit offsets, as emitted by cygnus tools. And + pure 32 bit offset dwarf for 32bit pointer apps. */ + + dbg->de_offset_reloc = Get_REL32_isa(dbg); +#elif defined(HAVE_SGI_IRIX_OFFSETS) + /* MIPS-SGI-IRIX 32 or 64, where offsets and lengths are both 64 bit for + 64bit pointer objects and both 32 bit for 32bit pointer objects. + And a dwarf-reader must check elf info to tell which applies. */ + dbg->de_64bit_extension = 0; + dbg->de_pointer_size = (IS_64BIT(dbg) ? 8 : 4); + dbg->de_offset_size = (IS_64BIT(dbg) ? 8 : 4); + dbg->de_ptr_reloc = + IS_64BIT(dbg) ? Get_REL64_isa(dbg) : Get_REL32_isa(dbg); + dbg->de_offset_reloc = dbg->de_ptr_reloc; +#else /* HAVE_DWARF2_99_EXTENSION or default. */ + /* Revised 64 bit output, using distingushed values. Per 1999 + dwarf3. This allows run-time selection of offset size. */ + dbg->de_64bit_extension = (IS_64BIT(dbg) ? 1 : 0); + dbg->de_pointer_size = (IS_64BIT(dbg) ? 8 : 4); + if( flags & DW_DLC_OFFSET_SIZE_64 && (dbg->de_pointer_size == 8)) { + /* When it's 64 bit address, a 64bit offset is sensible. + Arguably a 32 bit address with 64 bit offset could be + sensible, but who would want that? */ + dbg->de_offset_size = 8; + dbg->de_64bit_extension = 1; + } else { + dbg->de_offset_size = 4; + dbg->de_64bit_extension = 0; + } + dbg->de_ptr_reloc = + IS_64BIT(dbg) ? Get_REL64_isa(dbg) : Get_REL32_isa(dbg); + /* Non-MIPS, dwarf lengths and offsets are 32 bits even for 64bit + pointer environments. */ + /* Get_REL??_isa here supports 64bit-offset dwarf. For 64bit, we + emit the extension bytes. */ + + dbg->de_offset_reloc = IS_64BIT(dbg) ? Get_REL64_isa(dbg) + : Get_REL32_isa(dbg); +#endif /* HAVE_DWARF2_99_EXTENSION etc. */ + + dbg->de_exc_reloc = Get_REL_SEGREL_isa(dbg); + + dbg->de_is_64bit = IS_64BIT(dbg); + + + if (flags & DW_DLC_SYMBOLIC_RELOCATIONS) { + dbg->de_relocation_record_size = + sizeof(struct Dwarf_Relocation_Data_s); + } else { + +#if HAVE_ELF64_GETEHDR + dbg->de_relocation_record_size = + IS_64BIT(dbg)? sizeof(REL64) : sizeof(REL32); +#else + dbg->de_relocation_record_size = sizeof(REL32); +#endif + + } + + if (dbg->de_offset_size == 8) { + dbg->de_ar_data_attribute_form = DW_FORM_data8; + dbg->de_ar_ref_attr_form = DW_FORM_ref8; + } else { + dbg->de_ar_data_attribute_form = DW_FORM_data4; + dbg->de_ar_ref_attr_form = DW_FORM_ref4; + } + + if (flags & DW_DLC_SYMBOLIC_RELOCATIONS) { + dbg->de_reloc_name = _dwarf_pro_reloc_name_symbolic; + dbg->de_reloc_pair = _dwarf_pro_reloc_length_symbolic; + dbg->de_transform_relocs_to_disk = + _dwarf_symbolic_relocs_to_disk; + } else { + if (IS_64BIT(dbg)) { + dbg->de_reloc_name = _dwarf_pro_reloc_name_stream64; + } else { + dbg->de_reloc_name = _dwarf_pro_reloc_name_stream32; + } + dbg->de_reloc_pair = 0; + dbg->de_transform_relocs_to_disk = _dwarf_stream_relocs_to_disk; + } + for (k = 0; k < NUM_DEBUG_SECTIONS; ++k) { + + Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[k]; + + prel->pr_slots_per_block_to_alloc = DEFAULT_SLOTS_PER_BLOCK; + } + /* First assume host, target same endianness */ + dbg->de_same_endian = 1; + dbg->de_copy_word = memcpy; +#ifdef WORDS_BIGENDIAN + /* host is big endian, so what endian is target? */ + if (flags & DW_DLC_TARGET_LITTLEENDIAN) { + dbg->de_same_endian = 0; + dbg->de_copy_word = _dwarf_memcpy_swap_bytes; + } +#else /* little endian */ + /* host is little endian, so what endian is target? */ + if (flags & DW_DLC_TARGET_BIGENDIAN) { + dbg->de_same_endian = 0; + dbg->de_copy_word = _dwarf_memcpy_swap_bytes; + } +#endif /* !WORDS_BIGENDIAN */ + + + return; + +} diff --git a/usr/src/lib/libdwarf/common/pro_line.c b/usr/src/lib/libdwarf/common/pro_line.c new file mode 100644 index 0000000000..69d3e339f0 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_line.c @@ -0,0 +1,300 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include +#include +#ifdef HAVE_ELF_H +#include +#endif +#include "pro_incl.h" +#include "pro_line.h" + +Dwarf_Unsigned _dwarf_pro_add_line_entry(Dwarf_P_Debug, + Dwarf_Unsigned file_index, + Dwarf_Addr code_address, + Dwarf_Unsigned symidx, + Dwarf_Unsigned line_no, + Dwarf_Signed col_no, + Dwarf_Bool is_stmt_begin, + Dwarf_Bool is_bb_begin, + Dwarf_Ubyte opc, + Dwarf_Error * error); + +/*------------------------------------------------------------------------- + Add a entry to the line information section + file_index: index of file in file entries, obtained from + add_file_entry() call. + + This function actually calls _dwarf_pro_add_line_entry(), with + an extra parameter, the opcode. Done so that interface calls + dwarf_lne_set_address() and dwarf_lne_end_sequence() can use + this internal routine. +---------------------------------------------------------------------------*/ +Dwarf_Unsigned +dwarf_add_line_entry(Dwarf_P_Debug dbg, + Dwarf_Unsigned file_index, + Dwarf_Addr code_address, + Dwarf_Unsigned line_no, + Dwarf_Signed col_no, + Dwarf_Bool is_stmt_begin, + Dwarf_Bool is_bb_begin, Dwarf_Error * error) +{ + Dwarf_Unsigned retval; + + retval = _dwarf_pro_add_line_entry(dbg, file_index, code_address, 0, + line_no, col_no, is_stmt_begin, + is_bb_begin, 0, error); + return retval; +} + +/*------------------------------------------------------------------------ + Ask to emit DW_LNE_set_address opcode explicitly. Used by be + to emit start of a new .text section, or to force a relocated + address into debug line information entry. +-------------------------------------------------------------------------*/ +Dwarf_Unsigned +dwarf_lne_set_address(Dwarf_P_Debug dbg, + Dwarf_Addr offs, + Dwarf_Unsigned symidx, Dwarf_Error * error) +{ + Dwarf_Ubyte opc; + Dwarf_Unsigned retval; + + opc = DW_LNE_set_address; + retval = + _dwarf_pro_add_line_entry(dbg, 0, offs, symidx, 0, 0, 0, 0, opc, + error); + return retval; +} + +/*------------------------------------------------------------------------ + Ask to emit end_seqence opcode. Used normally at the end of a + compilation unit. Can also be used in the middle if there + are gaps in the region described by the code address. +-------------------------------------------------------------------------*/ +Dwarf_Unsigned +dwarf_lne_end_sequence(Dwarf_P_Debug dbg, + Dwarf_Addr end_address, Dwarf_Error * error) +{ + Dwarf_Ubyte opc; + Dwarf_Unsigned retval; + + opc = DW_LNE_end_sequence; + retval = + _dwarf_pro_add_line_entry(dbg, 0, end_address, 0, 0, 0, 0, 0, + opc, error); + return retval; +} + +/*---------------------------------------------------------------------------- + Add an entry in the internal list of lines mantained by producer. + Opc indicates if an opcode needs to be generated, rather than just + an entry in the matrix. During opcodes generation time, these + opcodes will be used. +-----------------------------------------------------------------------------*/ +Dwarf_Unsigned +_dwarf_pro_add_line_entry(Dwarf_P_Debug dbg, + Dwarf_Unsigned file_index, + Dwarf_Addr code_address, + Dwarf_Unsigned symidx, + Dwarf_Unsigned line_no, + Dwarf_Signed col_no, + Dwarf_Bool is_stmt_begin, + Dwarf_Bool is_bb_begin, + Dwarf_Ubyte opc, Dwarf_Error * error) +{ + if (dbg->de_lines == NULL) { + dbg->de_lines = (Dwarf_P_Line) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Line_s)); + if (dbg->de_lines == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_LINE_ALLOC, DW_DLV_NOCOUNT); + } + dbg->de_last_line = dbg->de_lines; + _dwarf_pro_reg_init(dbg->de_lines); + + } else { + dbg->de_last_line->dpl_next = (Dwarf_P_Line) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Line_s)); + if (dbg->de_last_line->dpl_next == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_LINE_ALLOC, DW_DLV_NOCOUNT); + } + dbg->de_last_line = dbg->de_last_line->dpl_next; + _dwarf_pro_reg_init(dbg->de_last_line); + } + dbg->de_last_line->dpl_address = code_address; + dbg->de_last_line->dpl_file = (unsigned long) file_index; + dbg->de_last_line->dpl_line = (unsigned long) line_no; + dbg->de_last_line->dpl_column = (unsigned long) col_no; + dbg->de_last_line->dpl_is_stmt = is_stmt_begin; + dbg->de_last_line->dpl_basic_block = is_bb_begin; + dbg->de_last_line->dpl_opc = opc; + dbg->de_last_line->dpl_r_symidx = symidx; + + return (0); +} + +/*----------------------------------------------------------------------- + Add a directory declaration to the debug_line section. Stored + in linked list. +------------------------------------------------------------------------*/ +Dwarf_Unsigned +dwarf_add_directory_decl(Dwarf_P_Debug dbg, + char *name, Dwarf_Error * error) +{ + if (dbg->de_inc_dirs == NULL) { + dbg->de_inc_dirs = (Dwarf_P_Inc_Dir) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Inc_Dir_s)); + if (dbg->de_inc_dirs == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_INCDIR_ALLOC, DW_DLV_NOCOUNT); + } + dbg->de_last_inc_dir = dbg->de_inc_dirs; + dbg->de_n_inc_dirs = 1; + } else { + dbg->de_last_inc_dir->did_next = (Dwarf_P_Inc_Dir) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Inc_Dir_s)); + if (dbg->de_last_inc_dir->did_next == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_INCDIR_ALLOC, DW_DLV_NOCOUNT); + } + dbg->de_last_inc_dir = dbg->de_last_inc_dir->did_next; + dbg->de_n_inc_dirs++; + } + dbg->de_last_inc_dir->did_name = + (char *) _dwarf_p_get_alloc(dbg, strlen(name) + 1); + if (dbg->de_last_inc_dir->did_name == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_STRING_ALLOC, DW_DLV_NOCOUNT); + } + strcpy(dbg->de_last_inc_dir->did_name, name); + dbg->de_last_inc_dir->did_next = NULL; + + return dbg->de_n_inc_dirs; +} + +/*----------------------------------------------------------------------- + Add a file entry declaration to the debug_line section. Stored + in linked list. The data is immediately encodes as leb128 + and stored in Dwarf_P_F_Entry_s struct. +------------------------------------------------------------------------*/ +Dwarf_Unsigned +dwarf_add_file_decl(Dwarf_P_Debug dbg, + char *name, + Dwarf_Unsigned dir_idx, + Dwarf_Unsigned time_mod, + Dwarf_Unsigned length, Dwarf_Error * error) +{ + Dwarf_P_F_Entry cur; + char *ptr; + int nbytes_idx, nbytes_time, nbytes_len; + char buffidx[ENCODE_SPACE_NEEDED]; + char bufftime[ENCODE_SPACE_NEEDED]; + char bufflen[ENCODE_SPACE_NEEDED]; + int res; + + if (dbg->de_file_entries == NULL) { + dbg->de_file_entries = (Dwarf_P_F_Entry) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_F_Entry_s)); + if (dbg->de_file_entries == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_FILE_ENTRY_ALLOC, + DW_DLV_NOCOUNT); + } + cur = dbg->de_file_entries; + dbg->de_last_file_entry = cur; + dbg->de_n_file_entries = 1; + } else { + cur = dbg->de_last_file_entry; + cur->dfe_next = (Dwarf_P_F_Entry) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_F_Entry_s)); + if (cur->dfe_next == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_FILE_ENTRY_ALLOC, + DW_DLV_NOCOUNT); + } + cur = cur->dfe_next; + dbg->de_last_file_entry = cur; + dbg->de_n_file_entries++; + } + cur->dfe_name = (char *) _dwarf_p_get_alloc(dbg, strlen(name) + 1); + if (cur->dfe_name == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT); + } + strcpy((char *) cur->dfe_name, name); + res = _dwarf_pro_encode_leb128_nm(dir_idx, &nbytes_idx, + buffidx, sizeof(buffidx)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT); + } + res = _dwarf_pro_encode_leb128_nm(time_mod, &nbytes_time, + bufftime, sizeof(bufftime)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT); + } + res = _dwarf_pro_encode_leb128_nm(length, &nbytes_len, + bufflen, sizeof(bufflen)); + cur->dfe_args = (char *) + _dwarf_p_get_alloc(dbg, nbytes_idx + nbytes_time + nbytes_len); + if (cur->dfe_args == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT); + } + ptr = cur->dfe_args; + memcpy((void *) ptr, buffidx, nbytes_idx); + ptr += nbytes_idx; + memcpy((void *) ptr, bufftime, nbytes_time); + ptr += nbytes_time; + memcpy((void *) ptr, bufflen, nbytes_len); + ptr += nbytes_len; + cur->dfe_nbytes = nbytes_idx + nbytes_time + nbytes_len; + cur->dfe_next = NULL; + + return dbg->de_n_file_entries; +} + + +/*--------------------------------------------------------------------- + Initialize a row of the matrix for line numbers, meaning + initialize the struct corresponding to it +----------------------------------------------------------------------*/ +void +_dwarf_pro_reg_init(Dwarf_P_Line cur_line) +{ + cur_line->dpl_address = 0; + cur_line->dpl_file = 1; + cur_line->dpl_line = 1; + cur_line->dpl_column = 0; + cur_line->dpl_is_stmt = DEFAULT_IS_STMT; + cur_line->dpl_basic_block = false; + cur_line->dpl_next = NULL; +} diff --git a/usr/src/lib/libdwarf/common/pro_line.h b/usr/src/lib/libdwarf/common/pro_line.h new file mode 100644 index 0000000000..eed941239d --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_line.h @@ -0,0 +1,116 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#define VERSION 2 +#ifdef __i386 +#define MIN_INST_LENGTH 1 +#else +#define MIN_INST_LENGTH 4 +#endif +#define DEFAULT_IS_STMT false + /* line base and range are temporarily defines. + They need to be calculated later */ +#define LINE_BASE -1 +#define LINE_RANGE 4 + +#define OPCODE_BASE 10 +#define MAX_OPCODE 255 + + +/* + This struct is used to hold entries in the include directories + part of statement prologue. +*/ +struct Dwarf_P_Inc_Dir_s { + char *did_name; /* name of directory */ + Dwarf_P_Inc_Dir did_next; +}; + + +/* + This struct holds file entries for the statement prologue. + Defined in pro_line.h +*/ +struct Dwarf_P_F_Entry_s { + char *dfe_name; + char *dfe_args; /* has dir index, time of modification, + length in bytes. Encodes as leb128 */ + int dfe_nbytes; /* number of bytes in args */ + Dwarf_P_F_Entry dfe_next; +}; + + +/* + Struct holding line number information for each of the producer + line entries +*/ +struct Dwarf_P_Line_s { + /* code address */ + Dwarf_Addr dpl_address; + + /* file index, index into file entry */ + Dwarf_Word dpl_file; + + /* line number */ + Dwarf_Word dpl_line; + + /* column number */ + Dwarf_Word dpl_column; + + /* whether its a beginning of a stmt */ + Dwarf_Ubyte dpl_is_stmt; + + /* whether its a beginning of basic blk */ + Dwarf_Ubyte dpl_basic_block; + + /* used to store opcodes set_address, and end_seq */ + Dwarf_Ubyte dpl_opc; + + /* + Used only for relocations. Has index of symbol relative to + which relocation has to be done (the S part in S + A) */ + Dwarf_Unsigned dpl_r_symidx; + + Dwarf_P_Line dpl_next; +}; + +/* + to initialize state machine registers, definition in + pro_line.c +*/ +void _dwarf_pro_reg_init(Dwarf_P_Line); diff --git a/usr/src/lib/libdwarf/common/pro_macinfo.c b/usr/src/lib/libdwarf/common/pro_macinfo.c new file mode 100644 index 0000000000..cfa820aee6 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_macinfo.c @@ -0,0 +1,472 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include +#include +#include "pro_incl.h" +#include "pro_section.h" +#include "pro_macinfo.h" + +/* + I don't much like the error strings this generates, since + like the rest of libdwarf they are simple strings with + no useful numbers in them. But that's not something I can + fix without more work than I have time for + right now. davea Nov 94. +*/ + +/* these are gross overestimates of the number of +** bytes needed to store a number in LEB form. +** Just estimates, and since blocks are reasonable size, +** the end-block waste is small. +** Of course the waste is NOT present on disk. +*/ + +#define COMMAND_LEN ENCODE_SPACE_NEEDED +#define LINE_LEN ENCODE_SPACE_NEEDED +#define BASE_MACINFO_MALLOC_LEN 2048 + +static int +libdwarf_compose_begin(Dwarf_P_Debug dbg, int code, + size_t maxlen, int *compose_error_type) +{ + unsigned char *nextchar; + struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo; + + if (curblk == 0) { + struct dw_macinfo_block_s *newb; + size_t len; + + /* initial allocation */ + size_t blen = BASE_MACINFO_MALLOC_LEN; + + if (blen < maxlen) { + blen = 2 * maxlen; + } + len = sizeof(struct dw_macinfo_block_s) + blen; + newb = + (struct dw_macinfo_block_s *) _dwarf_p_get_alloc(dbg, len); + if (!newb) { + *compose_error_type = DW_DLE_MACINFO_MALLOC_FAIL; + return DW_DLV_ERROR; + } + newb->mb_data = + (char *) newb + sizeof(struct dw_macinfo_block_s); + newb->mb_avail_len = blen; + newb->mb_used_len = 0; + newb->mb_macinfo_data_space_len = blen; + dbg->de_first_macinfo = newb; + dbg->de_current_macinfo = newb; + curblk = newb; + } else if (curblk->mb_avail_len < maxlen) { + struct dw_macinfo_block_s *newb; + size_t len; + + /* no space left in block: allocate a new block */ + size_t blen = + dbg->de_current_macinfo->mb_macinfo_data_space_len * 2; + if (blen < maxlen) { + blen = 2 * maxlen; + } + len = sizeof(struct dw_macinfo_block_s) + blen; + newb = + (struct dw_macinfo_block_s *) _dwarf_p_get_alloc(dbg, len); + if (!newb) { + *compose_error_type = DW_DLE_MACINFO_MALLOC_FAIL; + return DW_DLV_ERROR; + } + newb->mb_data = + (char *) newb + sizeof(struct dw_macinfo_block_s); + newb->mb_avail_len = blen; + newb->mb_used_len = 0; + newb->mb_macinfo_data_space_len = blen; + dbg->de_first_macinfo->mb_next = newb; + dbg->de_current_macinfo = newb; + curblk = newb; + } + /* now curblk has enough room */ + dbg->de_compose_avail = curblk->mb_avail_len; + dbg->de_compose_used_len = curblk->mb_used_len; + nextchar = + (unsigned char *) (curblk->mb_data + dbg->de_compose_used_len); + *nextchar = code; + dbg->de_compose_avail--; + ++dbg->de_compose_used_len; + return DW_DLV_OK; +} + + + +static void +libdwarf_compose_add_string(Dwarf_P_Debug dbg, char *string, size_t len) +{ + struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo; + unsigned char *nextchar; + + nextchar = + (unsigned char *) (curblk->mb_data + dbg->de_compose_used_len); + + len += 1; /* count the null terminator */ + + memcpy(nextchar, string, len); + dbg->de_compose_avail -= len; + dbg->de_compose_used_len += len; + return; + +} +static int +libdwarf_compose_add_line(Dwarf_P_Debug dbg, + Dwarf_Unsigned line, int *compose_error_type) +{ + struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo; + unsigned char *nextchar; + int res; + int nbytes; + + nextchar = + (unsigned char *) (curblk->mb_data + dbg->de_compose_used_len); + + /* Put the created leb number directly into the macro buffer If + dbg->de_compose_avail is > INT_MAX this will not work as the + 'int' will look negative to _dwarf_pro_encode_leb128_nm! */ + + res = _dwarf_pro_encode_leb128_nm(line, &nbytes, + (char *) nextchar, + (int) dbg->de_compose_avail); + if (res != DW_DLV_OK) { + *compose_error_type = DW_DLE_MACINFO_INTERNAL_ERROR_SPACE; + return DW_DLV_ERROR; + } + + dbg->de_compose_avail -= nbytes; + dbg->de_compose_used_len += nbytes; + return DW_DLV_OK; +} + +/* + This function actually 'commits' the space used by the + preceeding calls. +*/ +static int +libdwarf_compose_complete(Dwarf_P_Debug dbg, int *compose_error_type) +{ + struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo; + + if (dbg->de_compose_used_len > curblk->mb_macinfo_data_space_len) { + *compose_error_type = DW_DLE_MACINFO_INTERNAL_ERROR_SPACE; + return DW_DLV_ERROR; + } + curblk->mb_avail_len = dbg->de_compose_avail; + curblk->mb_used_len = dbg->de_compose_used_len; + return DW_DLV_OK; +} + + + +int +dwarf_def_macro(Dwarf_P_Debug dbg, + Dwarf_Unsigned line, + char *macname, char *macvalue, Dwarf_Error * error) +{ + size_t len; + size_t len2; + size_t length_est; + int res; + int compose_error_type; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + if (macname == 0) { + _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL); + return (DW_DLV_ERROR); + } + len = strlen(macname) + 1; + if (len == 0) { + _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY); + return (DW_DLV_ERROR); + } + if (macvalue) { + len2 = strlen(macvalue) + 1; + } else { + len2 = 0; + } + length_est = COMMAND_LEN + LINE_LEN + len + len2 + 1; /* 1 + for + space + character + we + add */ + res = libdwarf_compose_begin(dbg, DW_MACINFO_define, length_est, + &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + res = libdwarf_compose_add_line(dbg, line, &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + libdwarf_compose_add_string(dbg, macname, len); + libdwarf_compose_add_string(dbg, " ", 1); + if (macvalue) { + libdwarf_compose_add_string(dbg, " ", 1); + libdwarf_compose_add_string(dbg, macvalue, len2); + } + res = libdwarf_compose_complete(dbg, &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + return DW_DLV_OK; +} + +int +dwarf_undef_macro(Dwarf_P_Debug dbg, + Dwarf_Unsigned line, + char *macname, Dwarf_Error * error) +{ + + size_t len; + size_t length_est; + int res; + int compose_error_type; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + if (macname == 0) { + _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL); + return (DW_DLV_ERROR); + } + len = strlen(macname) + 1; + if (len == 0) { + _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY); + return (DW_DLV_ERROR); + } + length_est = COMMAND_LEN + LINE_LEN + len; + res = libdwarf_compose_begin(dbg, DW_MACINFO_undef, length_est, + &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + res = libdwarf_compose_add_line(dbg, line, &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + libdwarf_compose_add_string(dbg, macname, len); + res = libdwarf_compose_complete(dbg, &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + return DW_DLV_OK; +} + +int +dwarf_start_macro_file(Dwarf_P_Debug dbg, + Dwarf_Unsigned fileindex, + Dwarf_Unsigned linenumber, Dwarf_Error * error) +{ + size_t length_est; + int res; + int compose_error_type; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + length_est = COMMAND_LEN + LINE_LEN + LINE_LEN; + res = libdwarf_compose_begin(dbg, DW_MACINFO_start_file, length_est, + &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + res = libdwarf_compose_add_line(dbg, fileindex, + &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + res = libdwarf_compose_add_line(dbg, linenumber, + &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + return DW_DLV_OK; +} + +int +dwarf_end_macro_file(Dwarf_P_Debug dbg, Dwarf_Error * error) +{ + size_t length_est; + int res; + int compose_error_type; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + length_est = COMMAND_LEN; + res = libdwarf_compose_begin(dbg, DW_MACINFO_end_file, length_est, + &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + res = libdwarf_compose_complete(dbg, &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + return DW_DLV_OK; +} + +int +dwarf_vendor_ext(Dwarf_P_Debug dbg, + Dwarf_Unsigned constant, + char *string, Dwarf_Error * error) +{ + size_t len; + size_t length_est; + int res; + int compose_error_type; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + if (string == 0) { + _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL); + return (DW_DLV_ERROR); + } + len = strlen(string) + 1; + if (len == 0) { + _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY); + return (DW_DLV_ERROR); + } + length_est = COMMAND_LEN + LINE_LEN + len; + res = libdwarf_compose_begin(dbg, DW_MACINFO_vendor_ext, length_est, + &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + res = libdwarf_compose_add_line(dbg, constant, &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + libdwarf_compose_add_string(dbg, string, len); + libdwarf_compose_complete(dbg, &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + return DW_DLV_OK; +} + + + +int +_dwarf_pro_transform_macro_info_to_disk(Dwarf_P_Debug dbg, + Dwarf_Error * error) +{ + /* Total num of bytes in .debug_macinfo section. */ + Dwarf_Unsigned mac_num_bytes; + + /* Points to first byte of .debug_macinfo buffer. */ + Dwarf_Small *macinfo; + + /* Fills in the .debug_macinfo buffer. */ + Dwarf_Small *macinfo_ptr; + + + /* Used to scan the section data buffers. */ + struct dw_macinfo_block_s *m_prev; + struct dw_macinfo_block_s *m_sect; + + + /* Get the size of the debug_macinfo data */ + mac_num_bytes = 0; + for (m_sect = dbg->de_first_macinfo; m_sect != NULL; + m_sect = m_sect->mb_next) { + mac_num_bytes += m_sect->mb_used_len; + } + /* Tthe final entry has a type code of 0 to indicate It is final + for this CU Takes just 1 byte. */ + mac_num_bytes += 1; + + GET_CHUNK(dbg, dbg->de_elf_sects[DEBUG_MACINFO], + macinfo, (unsigned long) mac_num_bytes, error); + if (macinfo == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (0); + } + + macinfo_ptr = macinfo; + m_prev = 0; + for (m_sect = dbg->de_first_macinfo; m_sect != NULL; + m_sect = m_sect->mb_next) { + memcpy(macinfo_ptr, m_sect->mb_data, m_sect->mb_used_len); + macinfo_ptr += m_sect->mb_used_len; + if (m_prev) { + _dwarf_p_dealloc(dbg, (Dwarf_Small *) m_prev); + m_prev = 0; + } + m_prev = m_sect; + } + *macinfo_ptr = 0; /* the type code of 0 as last entry */ + if (m_prev) { + _dwarf_p_dealloc(dbg, (Dwarf_Small *) m_prev); + m_prev = 0; + } + + dbg->de_first_macinfo = NULL; + dbg->de_current_macinfo = NULL; + + return (int) dbg->de_n_debug_sect; +} diff --git a/usr/src/lib/libdwarf/common/pro_macinfo.h b/usr/src/lib/libdwarf/common/pro_macinfo.h new file mode 100644 index 0000000000..852a0cec1f --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_macinfo.h @@ -0,0 +1,40 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + + +int _dwarf_pro_transform_macro_info_to_disk(Dwarf_P_Debug dbg, + Dwarf_Error * error); diff --git a/usr/src/lib/libdwarf/common/pro_opaque.h b/usr/src/lib/libdwarf/common/pro_opaque.h new file mode 100644 index 0000000000..befc69faa6 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_opaque.h @@ -0,0 +1,484 @@ +/* + + Copyright (C) 2000,2002,2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + +#include + +/* + Sgidefs included to define __uint32_t, + a guaranteed 4-byte quantity. +*/ +#include "libdwarfdefs.h" + +#define true 1 +#define false 0 + +/* to identify a cie */ +#define DW_CIE_ID ~(0x0) +#define DW_CIE_VERSION 1 + +/*Dwarf_Word is unsigned word usable for index, count in memory */ +/*Dwarf_Sword is signed word usable for index, count in memory */ +/* The are 32 or 64 bits depending if 64 bit longs or not, which +** fits the ILP32 and LP64 models +** These work equally well with ILP64. +*/ + +typedef unsigned long Dwarf_Word; +typedef long Dwarf_Sword; + + +typedef signed char Dwarf_Sbyte; +typedef unsigned char Dwarf_Ubyte; +typedef signed short Dwarf_Shalf; + +/* + On any change that makes libdwarf producer + incompatible, increment this number. + 1->2->3 ... + +*/ +#define PRO_VERSION_MAGIC 0xdead1 + + +/* these 2 are fixed sizes which must not vary with the +** ILP32/LP64 model. These two stay at 32 bit. +*/ +typedef __uint32_t Dwarf_ufixed; +typedef __int32_t Dwarf_sfixed; + +/* + producer: + This struct is used to hold information about all + debug* sections. On creating a new section, section + names and indices are added to this struct + definition in pro_section.h +*/ +typedef struct Dwarf_P_Section_Data_s *Dwarf_P_Section_Data; + +/* + producer: + This struct is used to hold entries in the include directories + part of statement prologue. Definition in pro_line.h +*/ +typedef struct Dwarf_P_Inc_Dir_s *Dwarf_P_Inc_Dir; + +/* + producer: + This struct holds file entries for the statement prologue. + Defined in pro_line.h +*/ +typedef struct Dwarf_P_F_Entry_s *Dwarf_P_F_Entry; + +/* + producer: + This struct holds information for each cie. Defn in pro_frame.h +*/ +typedef struct Dwarf_P_Cie_s *Dwarf_P_Cie; + +/* + producer: + Struct to hold line number information, different from + Dwarf_Line opaque type. +*/ +typedef struct Dwarf_P_Line_s *Dwarf_P_Line; + +/* + producer: + Struct to hold information about address ranges. +*/ +typedef struct Dwarf_P_Simple_nameentry_s *Dwarf_P_Simple_nameentry; +typedef struct Dwarf_P_Simple_name_header_s *Dwarf_P_Simple_name_header; +typedef struct Dwarf_P_Arange_s *Dwarf_P_Arange; +typedef struct Dwarf_P_Per_Reloc_Sect_s *Dwarf_P_Per_Reloc_Sect; +typedef struct Dwarf_P_Per_Sect_String_Attrs_s *Dwarf_P_Per_Sect_String_Attrs; + +/* Defined to get at the elf section numbers and section name + indices in symtab for the dwarf sections + Must match .rel.* names in _dwarf_rel_section_names + exactly. +*/ +#define DEBUG_INFO 0 +#define DEBUG_LINE 1 +#define DEBUG_ABBREV 2 +#define DEBUG_FRAME 3 +#define DEBUG_ARANGES 4 +#define DEBUG_PUBNAMES 5 +#define DEBUG_STR 6 +#define DEBUG_FUNCNAMES 7 +#define DEBUG_TYPENAMES 8 +#define DEBUG_VARNAMES 9 +#define DEBUG_WEAKNAMES 10 +#define DEBUG_MACINFO 11 +#define DEBUG_LOC 12 + + /* number of debug_* sections not including the relocations */ +#define NUM_DEBUG_SECTIONS DEBUG_LOC + 1 + + +struct Dwarf_P_Die_s { + Dwarf_Unsigned di_offset; /* offset in debug info */ + char *di_abbrev; /* abbreviation */ + Dwarf_Word di_abbrev_nbytes; /* # of bytes in abbrev */ + Dwarf_Tag di_tag; + Dwarf_P_Die di_parent; /* parent of current die */ + Dwarf_P_Die di_child; /* first child */ + /* The last child field makes linking up children an O(1) operation, + See pro_die.c. */ + Dwarf_P_Die di_last_child; + Dwarf_P_Die di_left; /* left sibling */ + Dwarf_P_Die di_right; /* right sibling */ + Dwarf_P_Attribute di_attrs; /* list of attributes */ + Dwarf_P_Attribute di_last_attr; /* last attribute */ + int di_n_attr; /* number of attributes */ + Dwarf_P_Debug di_dbg; /* For memory management */ + Dwarf_Unsigned di_marker; /* used to attach symbols to dies */ +}; + + +/* producer fields */ +struct Dwarf_P_Attribute_s { + Dwarf_Half ar_attribute; /* Attribute Value. */ + Dwarf_Half ar_attribute_form; /* Attribute Form. */ + Dwarf_P_Die ar_ref_die; /* die pointer if form ref */ + char *ar_data; /* data, format given by form */ + Dwarf_Unsigned ar_nbytes; /* no. of bytes of data */ + Dwarf_Unsigned ar_rel_symidx; /* when attribute has a + relocatable value, holds + index of symbol in SYMTAB */ + Dwarf_Ubyte ar_rel_type; /* relocation type */ + Dwarf_Word ar_rel_offset; /* Offset of relocation within block */ + char ar_reloc_len; /* Number of bytes that relocation + applies to. 4 or 8. Unused and may + be 0 if if ar_rel_type is + R_MIPS_NONE */ + Dwarf_P_Attribute ar_next; +}; + +/* A block of .debug_macinfo data: this forms a series of blocks. +** Each macinfo input is compressed immediately and put into +** the current block if room, else a newblock allocated. +** The space allocation is such that the block and the macinfo +** data are one malloc block: free with a pointer to this and the +** mb_data is freed automatically. +** Like the struct hack, but legal ANSI C. +*/ +struct dw_macinfo_block_s { + struct dw_macinfo_block_s *mb_next; + unsigned long mb_avail_len; + unsigned long mb_used_len; + unsigned long mb_macinfo_data_space_len; + char *mb_data; /* original malloc ptr. */ +}; + +/* dwarf_sn_kind is for the array of similarly-treated + name -> cu ties +*/ +enum dwarf_sn_kind { dwarf_snk_pubname, dwarf_snk_funcname, + dwarf_snk_weakname, dwarf_snk_typename, + dwarf_snk_varname, + dwarf_snk_entrycount /* this one must be last */ +}; + + + +/* The calls to add a varname etc use a list of + these as the list. +*/ +struct Dwarf_P_Simple_nameentry_s { + Dwarf_P_Die sne_die; + char *sne_name; + int sne_name_len; + Dwarf_P_Simple_nameentry sne_next; +}; + +/* An array of these, each of which heads a list + of Dwarf_P_Simple_nameentry +*/ +struct Dwarf_P_Simple_name_header_s { + Dwarf_P_Simple_nameentry sn_head; + Dwarf_P_Simple_nameentry sn_tail; + Dwarf_Signed sn_count; + + /* length that will be generated, not counting fixed header or + trailer */ + Dwarf_Signed sn_net_len; +}; +typedef int (*_dwarf_pro_reloc_name_func_ptr) (Dwarf_P_Debug dbg, + int sec_index, + Dwarf_Unsigned offset,/* r_offset */ + Dwarf_Unsigned symidx, + enum Dwarf_Rel_Type type, + int reltarget_length); + +typedef int (*_dwarf_pro_reloc_length_func_ptr) (Dwarf_P_Debug dbg, + int sec_index, Dwarf_Unsigned offset,/* r_offset */ + Dwarf_Unsigned start_symidx, + Dwarf_Unsigned end_symidx, + enum Dwarf_Rel_Type type, + int reltarget_length); +typedef int (*_dwarf_pro_transform_relocs_func_ptr) (Dwarf_P_Debug dbg, + Dwarf_Signed * + new_sec_count); + +/* + Each slot in a block of slots could be: + a binary stream relocation entry (32 or 64bit relocation data) + a SYMBOLIC relocation entry. + During creation sometimes we create multiple chained blocks, + but sometimes we create a single long block. + Before returning reloc data to caller, + we switch to a single, long-enough, + block. + + We make counters here Dwarf_Unsigned so that we + get sufficient alignment. Since we use space after + the struct (at malloc time) for user data which + must have Dwarf_Unsigned alignment, this + struct must have that alignment too. +*/ +struct Dwarf_P_Relocation_Block_s { + Dwarf_Unsigned rb_slots_in_block; /* slots in block, as created */ + Dwarf_Unsigned rb_next_slot_to_use; /* counter, start at 0. */ + struct Dwarf_P_Relocation_Block_s *rb_next; + char *rb_where_to_add_next; /* pointer to next slot (might be past + end, depending on + rb_next_slot_to_use) */ + char *rb_data; /* data area */ +}; + +/* One of these per potential relocation section + So one per actual dwarf section. + Left zeroed when not used (some sections have + no relocations). +*/ +struct Dwarf_P_Per_Reloc_Sect_s { + unsigned long pr_reloc_total_count; /* total number of entries + across all blocks */ + + unsigned long pr_slots_per_block_to_alloc; /* at Block alloc, this + is the default number of slots to use */ + + int pr_sect_num_of_reloc_sect; /* sect number returned by + de_callback_func() or de_callback_func_b() call, this is the sect + number of the relocation section. */ + + /* singly-linked list. add at and ('last') with count of blocks */ + struct Dwarf_P_Relocation_Block_s *pr_first_block; + struct Dwarf_P_Relocation_Block_s *pr_last_block; + unsigned long pr_block_count; +}; + +#define DEFAULT_SLOTS_PER_BLOCK 3 + +typedef struct memory_list_s { + struct memory_list_s *prev; + struct memory_list_s *next; +} memory_list_t; + +struct Dwarf_P_Per_Sect_String_Attrs_s { + int sect_sa_section_number; + unsigned sect_sa_n_alloc; + unsigned sect_sa_n_used; + Dwarf_P_String_Attr sect_sa_list; +}; + +/* Fields used by producer */ +struct Dwarf_P_Debug_s { + /* used to catch dso passing dbg to another DSO with incompatible + version of libdwarf See PRO_VERSION_MAGIC */ + int de_version_magic_number; + + Dwarf_Handler de_errhand; + Dwarf_Ptr de_errarg; + + /* Call back function, used to create .debug* sections. Provided + by user. Only of these used per dbg. */ + Dwarf_Callback_Func de_callback_func; + Dwarf_Callback_Func_b de_callback_func_b; + + /* Flags from producer_init call */ + Dwarf_Unsigned de_flags; + + /* This holds information on debug section stream output, including + the stream data */ + Dwarf_P_Section_Data de_debug_sects; + + /* Pointer to the 'current active' section */ + Dwarf_P_Section_Data de_current_active_section; + + /* Number of debug data streams globs. */ + Dwarf_Word de_n_debug_sect; + + /* File entry information, null terminated singly-linked list */ + Dwarf_P_F_Entry de_file_entries; + Dwarf_P_F_Entry de_last_file_entry; + Dwarf_Unsigned de_n_file_entries; + + /* Has the directories used to search for source files */ + Dwarf_P_Inc_Dir de_inc_dirs; + Dwarf_P_Inc_Dir de_last_inc_dir; + Dwarf_Unsigned de_n_inc_dirs; + + /* Has all the line number info for the stmt program */ + Dwarf_P_Line de_lines; + Dwarf_P_Line de_last_line; + + /* List of cie's for the debug unit */ + Dwarf_P_Cie de_frame_cies; + Dwarf_P_Cie de_last_cie; + Dwarf_Unsigned de_n_cie; + + /* Singly-linked list of fde's for the debug unit */ + Dwarf_P_Fde de_frame_fdes; + Dwarf_P_Fde de_last_fde; + Dwarf_Unsigned de_n_fde; + + /* First die, leads to all others */ + Dwarf_P_Die de_dies; + + /* Pointer to list of strings */ + char *de_strings; + + /* Pointer to chain of aranges */ + Dwarf_P_Arange de_arange; + Dwarf_P_Arange de_last_arange; + Dwarf_Sword de_arange_count; + + /* macinfo controls. */ + /* first points to beginning of the list during creation */ + struct dw_macinfo_block_s *de_first_macinfo; + + /* current points to the current, unfilled, block */ + struct dw_macinfo_block_s *de_current_macinfo; + + /* Pointer to the first section, to support reset_section_bytes */ + Dwarf_P_Section_Data de_first_debug_sect; + + /* handles pubnames, weaknames, etc. See dwarf_sn_kind in + pro_opaque.h */ + struct Dwarf_P_Simple_name_header_s + de_simple_name_headers[dwarf_snk_entrycount]; + + /* relocation data. not all sections will actally have relocation + info, of course */ + struct Dwarf_P_Per_Reloc_Sect_s de_reloc_sect[NUM_DEBUG_SECTIONS]; + int de_reloc_next_to_return; /* iterator on reloc sections + (SYMBOLIC output) */ + + /* used in remembering sections */ + int de_elf_sects[NUM_DEBUG_SECTIONS]; /* elf sect number of + the section itself, DEBUG_LINE for example */ + + Dwarf_Unsigned de_sect_name_idx[NUM_DEBUG_SECTIONS]; /* section + name index or handle for the name of the symbol for + DEBUG_LINE for example */ + + int de_offset_reloc; /* offset reloc type, R_MIPS_32 for + example. Specific to the ABI being + produced. Relocates offset size + field */ + int de_exc_reloc; /* reloc type specific to exception + table relocs. */ + int de_ptr_reloc; /* standard reloc type, R_MIPS_32 for + example. Specific to the ABI being + produced. relocates pointer size + field */ + + unsigned char de_offset_size; /* section offset. Here to + avoid test of abi in macro + at run time MIPS -n32 4, + -64 8. */ + + unsigned char de_pointer_size; /* size of pointer in target. + Here to avoid test of abi in + macro at run time MIPS -n32 + 4, -64 is 8. */ + + unsigned char de_is_64bit; /* non-zero if is 64bit. Else 32 bit: + used for passing this info as a flag + */ + unsigned char de_relocation_record_size; /* reloc record size + varies by ABI and + relocation-output + method (stream or + symbolic) */ + + unsigned char de_64bit_extension; /* non-zero if creating 64 bit + offsets using dwarf2-99 + extension proposal */ + + int de_ar_data_attribute_form; /* data8, data4 abi dependent */ + int de_ar_ref_attr_form; /* ref8 ref4 , abi dependent */ + + /* simple name relocations */ + _dwarf_pro_reloc_name_func_ptr de_reloc_name; + + /* relocations for a length, requiring a pair of symbols */ + _dwarf_pro_reloc_length_func_ptr de_reloc_pair; + + _dwarf_pro_transform_relocs_func_ptr de_transform_relocs_to_disk; + + /* following used for macro buffers */ + unsigned long de_compose_avail; + unsigned long de_compose_used_len; + + unsigned char de_same_endian; + void *(*de_copy_word) (void *, const void *, size_t); + + /* Add new fields at the END of this struct to preserve some hope + of sensible behavior on dbg passing between DSOs linked with + mismatched libdwarf producer versions. */ + + Dwarf_P_Marker de_markers; /* pointer to array of markers */ + unsigned de_marker_n_alloc; + unsigned de_marker_n_used; + int de_sect_sa_next_to_return; /* Iterator on sring attrib sects */ + /* String attributes data of each section. */ + struct Dwarf_P_Per_Sect_String_Attrs_s de_sect_string_attr[NUM_DEBUG_SECTIONS]; +}; + +#define CURRENT_VERSION_STAMP 2 + +Dwarf_Unsigned _dwarf_add_simple_name_entry(Dwarf_P_Debug dbg, + Dwarf_P_Die die, + char *entry_name, + enum dwarf_sn_kind + entrykind, + Dwarf_Error * error); + + +#define DISTINGUISHED_VALUE 0xffffffff /* 64bit extension flag */ diff --git a/usr/src/lib/libdwarf/common/pro_pubnames.c b/usr/src/lib/libdwarf/common/pro_pubnames.c new file mode 100644 index 0000000000..e07fe35943 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_pubnames.c @@ -0,0 +1,63 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include +#include +#ifdef HAVE_ELFACCESS_H +#include +#endif +#include "pro_incl.h" +#include "pro_section.h" + + +/* + This function adds another public name to the + list of public names for the given Dwarf_P_Debug. + It returns 0 on error, and 1 otherwise. +*/ + +Dwarf_Unsigned +dwarf_add_pubname(Dwarf_P_Debug dbg, + Dwarf_P_Die die, + char *pubname_name, Dwarf_Error * error) +{ + return + _dwarf_add_simple_name_entry(dbg, die, pubname_name, + dwarf_snk_pubname, error); +} diff --git a/usr/src/lib/libdwarf/common/pro_reloc.c b/usr/src/lib/libdwarf/common/pro_reloc.c new file mode 100644 index 0000000000..66f16acbd0 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_reloc.c @@ -0,0 +1,269 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2008-2010 David Anderson, Inc. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include +#include +/*#include */ +#include "pro_incl.h" + + +/*Do initial alloc of newslots slots. + Fails only if malloc fails. + + Supposed to be called before any relocs allocated. + Ignored if after any allocated. + + Part of an optimization, so that for a known 'newslots' + relocations count we can preallocate the right size block. + Called from just 2 places. + + returns DW_DLV_OK or DW_DLV_ERROR +*/ +int +_dwarf_pro_pre_alloc_n_reloc_slots(Dwarf_P_Debug dbg, + int rel_sec_index, + Dwarf_Unsigned newslots) +{ + unsigned long len = 0; + struct Dwarf_P_Relocation_Block_s *data = 0; + Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[rel_sec_index]; + unsigned long slots_in_blk = (unsigned long) newslots; + unsigned long rel_rec_size = dbg->de_relocation_record_size; + + if (prel->pr_first_block) + return DW_DLV_OK; /* do nothing */ + + len = sizeof(struct Dwarf_P_Relocation_Block_s) + + slots_in_blk * rel_rec_size; + + + data = (struct Dwarf_P_Relocation_Block_s *) + _dwarf_p_get_alloc(dbg, len); + if (!data) { + return DW_DLV_ERROR; + } + data->rb_slots_in_block = slots_in_blk; /* could use default + here, as fallback in + case our origininal + estimate wrong. When + we call this we + presumably know what + we are doing, so + keep this count for + now */ + data->rb_next_slot_to_use = 0; + data->rb_where_to_add_next = + ((char *) data) + sizeof(struct Dwarf_P_Relocation_Block_s); + data->rb_data = data->rb_where_to_add_next; + + prel->pr_first_block = data; + prel->pr_last_block = data; + prel->pr_block_count = 1; + + + return DW_DLV_OK; +} + + +/*Do alloc of slots. + Fails only if malloc fails. + + Only allocator used. + + returns DW_DLV_OK or DW_DLV_ERROR +*/ +int +_dwarf_pro_alloc_reloc_slots(Dwarf_P_Debug dbg, int rel_sec_index) +{ + unsigned long len = 0; + struct Dwarf_P_Relocation_Block_s *data = 0; + Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[rel_sec_index]; + unsigned long slots_in_blk = prel->pr_slots_per_block_to_alloc; + unsigned long rel_rec_size = dbg->de_relocation_record_size; + + len = sizeof(struct Dwarf_P_Relocation_Block_s) + + slots_in_blk * rel_rec_size; + + data = (struct Dwarf_P_Relocation_Block_s *) + _dwarf_p_get_alloc(dbg, len); + if (!data) { + return DW_DLV_ERROR; + } + + if (prel->pr_first_block) { + prel->pr_last_block->rb_next = data; + prel->pr_last_block = data; + prel->pr_block_count += 1; + + } else { + + prel->pr_first_block = data; + prel->pr_last_block = data; + prel->pr_block_count = 1; + } + + data->rb_slots_in_block = slots_in_blk; + data->rb_next_slot_to_use = 0; + data->rb_where_to_add_next = + ((char *) data) + sizeof(struct Dwarf_P_Relocation_Block_s); + data->rb_data = data->rb_where_to_add_next; + + return DW_DLV_OK; + +} + +/* + Reserve a slot. return DW_DLV_OK if succeeds. + + Return DW_DLV_ERROR if fails (malloc error). + + Use the relrec_to_fill to pass back a pointer to + a slot space to use. +*/ +int +_dwarf_pro_reloc_get_a_slot(Dwarf_P_Debug dbg, + int base_sec_index, void **relrec_to_fill) +{ + struct Dwarf_P_Relocation_Block_s *data = 0; + Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[base_sec_index]; + unsigned long rel_rec_size = dbg->de_relocation_record_size; + + char *ret_addr = 0; + + data = prel->pr_last_block; + if ((data == 0) || + (data->rb_next_slot_to_use >= data->rb_slots_in_block)) { + int res; + + res = _dwarf_pro_alloc_reloc_slots(dbg, base_sec_index); + if (res != DW_DLV_OK) { + return res; + } + } + + data = prel->pr_last_block; + /* now we have an empty slot */ + ret_addr = data->rb_where_to_add_next; + + data->rb_where_to_add_next += rel_rec_size; + data->rb_next_slot_to_use += 1; + + prel->pr_reloc_total_count += 1; + + *relrec_to_fill = (void *) ret_addr; + + return DW_DLV_OK; + +} + +/* + On success returns count of + .rel.* sections that are symbolic + thru count_of_relocation_sections. + + On success, returns DW_DLV_OK. + + If this is not a 'symbolic' run, returns + DW_DLV_NO_ENTRY. + + No errors are possible. + + + + +*/ + + /*ARGSUSED*/ int +dwarf_get_relocation_info_count(Dwarf_P_Debug dbg, + Dwarf_Unsigned * + count_of_relocation_sections, + int *drd_buffer_version, + Dwarf_Error * error) +{ + if (dbg->de_flags & DW_DLC_SYMBOLIC_RELOCATIONS) { + int i; + unsigned int count = 0; + + for (i = 0; i < NUM_DEBUG_SECTIONS; ++i) { + if (dbg->de_reloc_sect[i].pr_reloc_total_count > 0) { + ++count; + } + } + *count_of_relocation_sections = (Dwarf_Unsigned) count; + *drd_buffer_version = DWARF_DRD_BUFFER_VERSION; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} + +int +dwarf_get_relocation_info(Dwarf_P_Debug dbg, + Dwarf_Signed * elf_section_index, + Dwarf_Signed * elf_section_index_link, + Dwarf_Unsigned * relocation_buffer_count, + Dwarf_Relocation_Data * reldata_buffer, + Dwarf_Error * error) +{ + int next = dbg->de_reloc_next_to_return; + + if (dbg->de_flags & DW_DLC_SYMBOLIC_RELOCATIONS) { + int i; + + for (i = next; i < NUM_DEBUG_SECTIONS; ++i) { + Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[i]; + + if (prel->pr_reloc_total_count > 0) { + dbg->de_reloc_next_to_return = i + 1; + + + /* ASSERT: prel->.pr_block_count == 1 */ + + *elf_section_index = prel->pr_sect_num_of_reloc_sect; + *elf_section_index_link = dbg->de_elf_sects[i]; + *relocation_buffer_count = prel->pr_reloc_total_count; + *reldata_buffer = (Dwarf_Relocation_Data) + (prel->pr_first_block->rb_data); + return DW_DLV_OK; + } + } + DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, DW_DLV_ERROR); + } + return DW_DLV_NO_ENTRY; +} diff --git a/usr/src/lib/libdwarf/common/pro_reloc.h b/usr/src/lib/libdwarf/common/pro_reloc.h new file mode 100644 index 0000000000..d2e6c67357 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_reloc.h @@ -0,0 +1,47 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + + +int _dwarf_pro_pre_alloc_n_reloc_slots(Dwarf_P_Debug dbg, + int rel_sec_index, + Dwarf_Unsigned newslots); + +int _dwarf_pro_alloc_reloc_slots(Dwarf_P_Debug dbg, int rel_sec_index); + +int _dwarf_pro_reloc_get_a_slot(Dwarf_P_Debug dbg, + int base_sec_index, + void **relrec_to_fill); diff --git a/usr/src/lib/libdwarf/common/pro_reloc_stream.c b/usr/src/lib/libdwarf/common/pro_reloc_stream.c new file mode 100644 index 0000000000..459779ceda --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_reloc_stream.c @@ -0,0 +1,297 @@ +/* + + Copyright (C) 2000,2001,2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2008-2010 David Anderson, Inc. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include +#include +#ifdef HAVE_ELFACCESS_H +#include +#else +/* Set r_info as defined by ELF generic ABI */ +#define Set_REL32_info(r,s,t) ((r).r_info = ELF32_R_INFO(s,t)) +#define Set_REL64_info(r,s,t) ((r).r_info = ELF64_R_INFO(s,t)) +#endif +#include "pro_incl.h" +#include "pro_section.h" +#include "pro_reloc.h" +#include "pro_reloc_stream.h" + +/* + Return DW_DLV_ERROR on malloc error or reltarget_length error. + Return DW_DLV_OK otherwise + + + +*/ + /*ARGSUSED*/ int +_dwarf_pro_reloc_name_stream64(Dwarf_P_Debug dbg, + int base_sec_index, + Dwarf_Unsigned offset, /* r_offset of reloc */ + Dwarf_Unsigned symidx, + enum Dwarf_Rel_Type type, + int reltarget_length) +{ +#if HAVE_ELF64_GETEHDR + REL64 *elf64_reloc = 0; + void *relrec_to_fill = 0; + int res = 0; + int rel_type = 0; + + res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index, + &relrec_to_fill); + if (res != DW_DLV_OK) + return res; + + + if (type == dwarf_drt_data_reloc) { + if (reltarget_length == dbg->de_offset_size) { + rel_type = dbg->de_offset_reloc; + } else if (reltarget_length == dbg->de_pointer_size) { + rel_type = dbg->de_ptr_reloc; + } else { + return DW_DLV_ERROR; + } + } else if (type == dwarf_drt_segment_rel) { + rel_type = dbg->de_exc_reloc; + } else { + /* We are in trouble: improper use of stream relocations. + Someone else will diagnose */ + rel_type = 0; + } + + elf64_reloc = (REL64 *)relrec_to_fill; + elf64_reloc->r_offset = offset; + Set_REL64_info(*elf64_reloc, symidx, rel_type); + return DW_DLV_OK; +#else /* !HAVE_ELF64_GETEHDR */ + return DW_DLV_ERROR; +#endif /* #if HAVE_ELF64_GETEHDR */ +} + +/* + Return DW_DLV_ERROR on malloc error or reltarget_length error. + Return DW_DLV_OK otherwise + a binary reloc: 32bit ABI +*/ +int +_dwarf_pro_reloc_name_stream32(Dwarf_P_Debug dbg, int base_sec_index, + Dwarf_Unsigned offset, /* r_offset of reloc */ + Dwarf_Unsigned symidx, + enum Dwarf_Rel_Type type, + int reltarget_length) +{ + REL32 *elf32_reloc = 0; + void *relrec_to_fill = 0; + int res = 0; + int rel_type = 0; + + res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index, + &relrec_to_fill); + if (res != DW_DLV_OK) + return res; + if (type == dwarf_drt_data_reloc) { + if (reltarget_length == dbg->de_offset_size) { + rel_type = dbg->de_offset_reloc; + } else if (reltarget_length == dbg->de_pointer_size) { + rel_type = dbg->de_ptr_reloc; + } else { + return DW_DLV_ERROR; + } + } else if (type == dwarf_drt_segment_rel) { + rel_type = dbg->de_exc_reloc; + } else { + /* We are in trouble: improper use of stream relocations. + Someone else will diagnose */ + rel_type = 0; + } + + elf32_reloc = (REL32*)relrec_to_fill; + elf32_reloc->r_offset = (Elf32_Addr) offset; + Set_REL32_info(*elf32_reloc, (Dwarf_Word) symidx, rel_type); + return DW_DLV_OK; + + /* get a slot, fill in the slot entry */ +} + + + +/* + Return DW_DLV_OK. + Never can really do anything: lengths cannot + be represented as end-start in a stream. + +*/ + /*ARGSUSED*/ int +_dwarf_pro_reloc_length_stream(Dwarf_P_Debug dbg, + int base_sec_index, + Dwarf_Unsigned offset, /* r_offset of reloc */ + Dwarf_Unsigned start_symidx, + Dwarf_Unsigned end_symidx, + enum Dwarf_Rel_Type type, + int reltarget_length) +{ + /* get a slot, fill in the slot entry */ + return DW_DLV_OK; +} + + +/* + Ensure each stream is a single buffer and + add that single buffer to the set of stream buffers. + + By creating a new buffer and copying if necessary. + + Free the input set of buffers if we consolidate. + Return -1 on error (malloc failure) + + + Return DW_DLV_OK on success. Any other return indicates + malloc failed. + +*/ +int +_dwarf_stream_relocs_to_disk(Dwarf_P_Debug dbg, + Dwarf_Signed * new_sec_count) +{ + unsigned long total_size = 0; + Dwarf_Small *data = 0; + int sec_index = 0; + unsigned long i = 0; + Dwarf_Error err = 0; + Dwarf_Error *error = &err; + + Dwarf_Signed sec_count = 0; + + Dwarf_P_Per_Reloc_Sect p_reloc = &dbg->de_reloc_sect[0]; + + for (i = 0; i < NUM_DEBUG_SECTIONS; ++i, ++p_reloc) { + unsigned long ct = p_reloc->pr_reloc_total_count; + unsigned len = 0; + struct Dwarf_P_Relocation_Block_s *p_blk = 0; + struct Dwarf_P_Relocation_Block_s *p_blk_last = 0; + Dwarf_P_Per_Reloc_Sect prb = 0; + + if (ct == 0) { + continue; + } + prb = &dbg->de_reloc_sect[i]; + len = dbg->de_relocation_record_size; + ++sec_count; + + total_size = ct * len; + sec_index = prb->pr_sect_num_of_reloc_sect; + if (sec_index == 0) { + /* Call de_callback_func or de_callback_func_b, getting + section number of reloc section. */ + int rel_section_index = 0; + Dwarf_Unsigned name_idx = 0; + int int_name = 0; + int err = 0; + + if (dbg->de_callback_func_b) { + rel_section_index = + dbg->de_callback_func_b(_dwarf_rel_section_names[i], + /* size */ + dbg->de_relocation_record_size, + /* type */ SHT_REL, + /* flags */ 0, + /* link to symtab, which we cannot + know */ 0, + /* info == link to sec rels apply to + */ + dbg->de_elf_sects[i], + &name_idx, &err); + } else { + rel_section_index = + dbg->de_callback_func(_dwarf_rel_section_names[i], + /* size */ + dbg->de_relocation_record_size, + /* type */ SHT_REL, + /* flags */ 0, + /* link to symtab, which we cannot + know */ 0, + /* info == link to sec rels apply to */ + dbg->de_elf_sects[i], &int_name, &err); + name_idx = int_name; + } + if (rel_section_index == -1) { + { + _dwarf_p_error(dbg, error, DW_DLE_ELF_SECT_ERR); + return (DW_DLV_ERROR); + } + + } + prb->pr_sect_num_of_reloc_sect = rel_section_index; + sec_index = rel_section_index; + } + GET_CHUNK(dbg, sec_index, data, total_size, &err); + p_blk = p_reloc->pr_first_block; + + /* following loop executes at least once. Effects the + consolidation to a single block or, if already a single + block, simply copies to the output buffer. And frees the + input block. The new block is in the de_debug_sects list. */ + while (p_blk) { + + unsigned long len = + p_blk->rb_where_to_add_next - p_blk->rb_data; + + memcpy(data, p_blk->rb_data, len); + + + data += len; + + p_blk_last = p_blk; + p_blk = p_blk->rb_next; + + _dwarf_p_dealloc(dbg, (Dwarf_Small *) p_blk_last); + } + /* ASSERT: sum of len copied == total_size */ + + /* + We have copied the input, now drop the pointers to it. For + debugging, leave the other data untouched. */ + p_reloc->pr_first_block = 0; + p_reloc->pr_last_block = 0; + } + + *new_sec_count = sec_count; + return DW_DLV_OK; +} diff --git a/usr/src/lib/libdwarf/common/pro_reloc_stream.h b/usr/src/lib/libdwarf/common/pro_reloc_stream.h new file mode 100644 index 0000000000..892ea5baf3 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_reloc_stream.h @@ -0,0 +1,63 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + + +int _dwarf_pro_reloc_name_stream64(Dwarf_P_Debug dbg, int base_sec_index, Dwarf_Unsigned offset, /* r_offset + of + reloc + */ + Dwarf_Unsigned symidx, + enum Dwarf_Rel_Type, + int reltarget_length); +int _dwarf_pro_reloc_name_stream32(Dwarf_P_Debug dbg, int base_sec_index, Dwarf_Unsigned offset, /* r_offset + of + reloc + */ + Dwarf_Unsigned symidx, + enum Dwarf_Rel_Type, + int reltarget_length); +int _dwarf_pro_reloc_length_stream(Dwarf_P_Debug dbg, int base_sec_index, Dwarf_Unsigned offset, /* r_offset + of + reloc + */ + Dwarf_Unsigned start_symidx, + Dwarf_Unsigned end_symidx, + enum Dwarf_Rel_Type, + int reltarget_length); + +int _dwarf_stream_relocs_to_disk(Dwarf_P_Debug dbg, + Dwarf_Signed * new_sec_count); diff --git a/usr/src/lib/libdwarf/common/pro_reloc_symbolic.c b/usr/src/lib/libdwarf/common/pro_reloc_symbolic.c new file mode 100644 index 0000000000..22080a00cd --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_reloc_symbolic.c @@ -0,0 +1,276 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include +#include +/*#include */ +#include "pro_incl.h" +#include "pro_section.h" +#include "pro_reloc.h" +#include "pro_reloc_symbolic.h" + +/* + Return DW_DLV_ERROR on malloc error. + Return DW_DLV_OK otherwise +*/ + +int +_dwarf_pro_reloc_name_symbolic(Dwarf_P_Debug dbg, + int base_sec_index, + Dwarf_Unsigned offset, /* r_offset of reloc */ + Dwarf_Unsigned symidx, + enum Dwarf_Rel_Type type, + int reltarget_length) +{ + /* get a slot, fill in the slot entry */ + void *relrec_to_fill = 0; + int res = 0; + struct Dwarf_Relocation_Data_s *slotp; + + res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index, + &relrec_to_fill); + if (res != DW_DLV_OK) + return res; + slotp = (struct Dwarf_Relocation_Data_s *) relrec_to_fill; + slotp->drd_type = type; + slotp->drd_length = reltarget_length; + slotp->drd_offset = offset; + slotp->drd_symbol_index = symidx; + return DW_DLV_OK; +} + + + +/* + Return DW_DLV_ERROR on malloc error. + Return DW_DLV_OK otherwise +*/ +int +_dwarf_pro_reloc_length_symbolic(Dwarf_P_Debug dbg, + int base_sec_index, + Dwarf_Unsigned offset, /* r_offset of reloc */ + Dwarf_Unsigned start_symidx, + Dwarf_Unsigned end_symidx, + enum Dwarf_Rel_Type type, + int reltarget_length) +{ + /* get a slot, fill in the slot entry */ + void *relrec_to_fill = 0; + int res = 0; + struct Dwarf_Relocation_Data_s *slotp1 = 0; + struct Dwarf_Relocation_Data_s *slotp2 = 0; + + res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index, + &relrec_to_fill); + if (res != DW_DLV_OK) + return res; + slotp1 = (struct Dwarf_Relocation_Data_s *) relrec_to_fill; + res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index, + &relrec_to_fill); + if (res != DW_DLV_OK) + return res; + slotp2 = (struct Dwarf_Relocation_Data_s *) relrec_to_fill; + + /* ASSERT: type == dwarf_drt_first_of_length_type_pair */ + slotp1->drd_type = type; + slotp1->drd_length = reltarget_length; + slotp1->drd_offset = offset; + slotp1->drd_symbol_index = start_symidx; + + slotp2->drd_type = dwarf_drt_second_of_length_pair; + slotp2->drd_length = reltarget_length; + slotp2->drd_offset = offset; + slotp2->drd_symbol_index = end_symidx; + return DW_DLV_OK; +} + +/* + Reset whatever fields of Dwarf_P_Per_Reloc_Sect_s + we must to allow adding a fresh new single + block easily (block consolidation use only). + +*/ +static void +_dwarf_reset_reloc_sect_info(struct Dwarf_P_Per_Reloc_Sect_s *pblk, + unsigned long ct) +{ + + + /* Do not zero pr_sect_num_of_reloc_sect */ + pblk->pr_reloc_total_count = 0; + pblk->pr_first_block = 0; + pblk->pr_last_block = 0; + pblk->pr_block_count = 0; + pblk->pr_slots_per_block_to_alloc = ct; +} + +/* + Ensure each stream is a single buffer and + add that single buffer to the set of stream buffers. + + By creating a new buffer and copying if necessary. + (If > 1 block, reduce to 1 block) + + Free the input set of buffers if we consolidate. + + We pass back *new_sec_count as zero because we + are not creating normal sections for a .o, but + symbolic relocations, separately counted. + + Return -1 on error (malloc failure) + + Return DW_DLV_OK on success. Any other return indicates + malloc failed. +*/ +int +_dwarf_symbolic_relocs_to_disk(Dwarf_P_Debug dbg, + Dwarf_Signed * new_sec_count) +{ + /* unsigned long total_size =0; */ + Dwarf_Small *data = 0; + int sec_index = 0; + int res = 0; + unsigned long i = 0; + Dwarf_Error error = 0; + Dwarf_Signed sec_count = 0; + Dwarf_P_Per_Reloc_Sect p_reloc = &dbg->de_reloc_sect[0]; + + for (i = 0; i < NUM_DEBUG_SECTIONS; ++i, ++p_reloc) { + unsigned long ct = p_reloc->pr_reloc_total_count; + struct Dwarf_P_Relocation_Block_s *p_blk; + struct Dwarf_P_Relocation_Block_s *p_blk_last; + int err; + if (ct == 0) { + continue; + } + + /* len = dbg->de_relocation_record_size; */ + ++sec_count; + + /* total_size = ct *len; */ + sec_index = p_reloc->pr_sect_num_of_reloc_sect; + if (sec_index == 0) { + /* Call de_callback_func or de_callback_func_b, + getting section number of reloc section. */ + int rel_section_index = 0; + int int_name = 0; + Dwarf_Unsigned name_idx = 0; + + /* + This is a bit of a fake, as we do not really have true + elf sections at all. Just the data such might contain. + But this lets the caller eventually link things + together: without this call we would not know what rel + data goes with what section when we are asked for the + real arrays. */ + + if (dbg->de_callback_func_b) { + rel_section_index = + dbg->de_callback_func_b(_dwarf_rel_section_names[i], + dbg->de_relocation_record_size, + /* type */ SHT_REL, + /* flags */ 0, + /* link to symtab, which we cannot + know */ SHN_UNDEF, + /* sec rels apply to */ + dbg->de_elf_sects[i], + &name_idx, &err); + } else { + rel_section_index = + dbg->de_callback_func(_dwarf_rel_section_names[i], + dbg->de_relocation_record_size, + /* type */ SHT_REL, + /* flags */ 0, + /* link to symtab, which we cannot + know */ SHN_UNDEF, + /* sec rels apply to, in elf, sh_info */ + dbg->de_elf_sects[i], &int_name, &err); + name_idx = int_name; + } + if (rel_section_index == -1) { + { + _dwarf_p_error(dbg, &error, DW_DLE_ELF_SECT_ERR); + return (DW_DLV_ERROR); + } + } + p_reloc->pr_sect_num_of_reloc_sect = rel_section_index; + sec_index = rel_section_index; + } + + p_blk = p_reloc->pr_first_block; + + if (p_reloc->pr_block_count > 1) { + struct Dwarf_P_Relocation_Block_s *new_blk; + + /* HACK , not normal interfaces, trashing p_reloc current + contents! */ + _dwarf_reset_reloc_sect_info(p_reloc, ct); + + /* Creating new single block for all 'ct' entries */ + res = _dwarf_pro_pre_alloc_n_reloc_slots(dbg, (int) i, ct); + if (res != DW_DLV_OK) { + return res; + } + new_blk = p_reloc->pr_first_block; + + data = (Dwarf_Small *) new_blk->rb_data; + + /* The following loop does the consolidation to a single + block and frees the input block(s). */ + do { + unsigned long len = + p_blk->rb_where_to_add_next - p_blk->rb_data; + memcpy(data, p_blk->rb_data, len); + data += len; + p_blk_last = p_blk; + p_blk = p_blk->rb_next; + _dwarf_p_dealloc(dbg, (Dwarf_Small *) p_blk_last); + } while (p_blk); + /* ASSERT: sum of len copied == total_size */ + new_blk->rb_next_slot_to_use = ct; + new_blk->rb_where_to_add_next = (char *) data; + p_reloc->pr_reloc_total_count = ct; + + /* have now created a single block, but no change in slots + used (pr_reloc_total_count) */ + } + } + *new_sec_count = 0; + return DW_DLV_OK; +} diff --git a/usr/src/lib/libdwarf/common/pro_reloc_symbolic.h b/usr/src/lib/libdwarf/common/pro_reloc_symbolic.h new file mode 100644 index 0000000000..3d03a47863 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_reloc_symbolic.h @@ -0,0 +1,55 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + +int _dwarf_pro_reloc_name_symbolic(Dwarf_P_Debug dbg, int base_sec_index, Dwarf_Unsigned offset, /* r_offset + of + reloc + */ + Dwarf_Unsigned symidx, + enum Dwarf_Rel_Type, + int reltarget_length); +int + _dwarf_pro_reloc_length_symbolic(Dwarf_P_Debug dbg, int base_sec_index, Dwarf_Unsigned offset, /* r_offset + of + reloc + */ + Dwarf_Unsigned start_symidx, + Dwarf_Unsigned end_symidx, + enum Dwarf_Rel_Type, + int reltarget_length); + +int _dwarf_symbolic_relocs_to_disk(Dwarf_P_Debug dbg, + Dwarf_Signed * new_sec_count); diff --git a/usr/src/lib/libdwarf/common/pro_section.c b/usr/src/lib/libdwarf/common/pro_section.c new file mode 100644 index 0000000000..6503c2cf09 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_section.c @@ -0,0 +1,2221 @@ +/* + + Copyright (C) 2000,2004,2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. + Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* + SGI has moved from the Crittenden Lane address. +*/ + + + + + +#include "config.h" +#include "libdwarfdefs.h" +#include +#include +#ifdef HAVE_ELFACCESS_H +#include +#endif +#include "pro_incl.h" +#include "pro_section.h" +#include "pro_line.h" +#include "pro_frame.h" +#include "pro_die.h" +#include "pro_macinfo.h" +#include "pro_types.h" + +#ifndef SHF_MIPS_NOSTRIP +/* if this is not defined, we probably don't need it: just use 0 */ +#define SHF_MIPS_NOSTRIP 0 +#endif +#ifndef R_MIPS_NONE +#define R_MIPS_NONE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +/* must match up with pro_section.h defines of DEBUG_INFO etc +and sectnames (below). REL_SEC_PREFIX is either ".rel" or ".rela" +see pro_incl.h +*/ +char *_dwarf_rel_section_names[] = { + REL_SEC_PREFIX ".debug_info", + REL_SEC_PREFIX ".debug_line", + REL_SEC_PREFIX ".debug_abbrev", /* no relocations on this, really */ + REL_SEC_PREFIX ".debug_frame", + REL_SEC_PREFIX ".debug_aranges", + REL_SEC_PREFIX ".debug_pubnames", + REL_SEC_PREFIX ".debug_str", + REL_SEC_PREFIX ".debug_funcnames", /* sgi extension */ + REL_SEC_PREFIX ".debug_typenames", /* sgi extension */ + REL_SEC_PREFIX ".debug_varnames", /* sgi extension */ + REL_SEC_PREFIX ".debug_weaknames", /* sgi extension */ + REL_SEC_PREFIX ".debug_macinfo", + REL_SEC_PREFIX ".debug_loc" +}; + +/* names of sections. Ensure that it matches the defines + in pro_section.h, in the same order + Must match also _dwarf_rel_section_names above +*/ +char *_dwarf_sectnames[] = { + ".debug_info", + ".debug_line", + ".debug_abbrev", + ".debug_frame", + ".debug_aranges", + ".debug_pubnames", + ".debug_str", + ".debug_funcnames", /* sgi extension */ + ".debug_typenames", /* sgi extension */ + ".debug_varnames", /* sgi extension */ + ".debug_weaknames", /* sgi extension */ + ".debug_macinfo", + ".debug_loc" +}; + + + + +static Dwarf_Ubyte std_opcode_len[] = { 0, /* DW_LNS_copy */ + 1, /* DW_LNS_advance_pc */ + 1, /* DW_LNS_advance_line */ + 1, /* DW_LNS_set_file */ + 1, /* DW_LNS_set_column */ + 0, /* DW_LNS_negate_stmt */ + 0, /* DW_LNS_set_basic_block */ + 0, /* DW_LNS_const_add_pc */ + 1, /* DW_LNS_fixed_advance_pc */ +}; + +/* struct to hold relocation entries. Its mantained as a linked + list of relocation structs, and will then be written at as a + whole into the relocation section. Whether its 32 bit or + 64 bit will be obtained from Dwarf_Debug pointer. +*/ + +typedef struct Dwarf_P_Rel_s *Dwarf_P_Rel; +struct Dwarf_P_Rel_s { + Dwarf_P_Rel dr_next; + void *dr_rel_datap; +}; +typedef struct Dwarf_P_Rel_Head_s *Dwarf_P_Rel_Head; +struct Dwarf_P_Rel_Head_s { + struct Dwarf_P_Rel_s *drh_head; + struct Dwarf_P_Rel_s *drh_tail; +}; + +static int _dwarf_pro_generate_debugline(Dwarf_P_Debug dbg, + Dwarf_Error * error); +static int _dwarf_pro_generate_debugframe(Dwarf_P_Debug dbg, + Dwarf_Error * error); +static int _dwarf_pro_generate_debuginfo(Dwarf_P_Debug dbg, + Dwarf_Error * error); +static Dwarf_P_Abbrev _dwarf_pro_getabbrev(Dwarf_P_Die, Dwarf_P_Abbrev); +static int _dwarf_pro_match_attr + (Dwarf_P_Attribute, Dwarf_P_Abbrev, int no_attr); + +/* these macros used as return value for below functions */ +#define OPC_INCS_ZERO -1 +#define OPC_OUT_OF_RANGE -2 +#define LINE_OUT_OF_RANGE -3 +static int _dwarf_pro_get_opc(Dwarf_Unsigned addr_adv, int line_adv); + + +/* BEGIN_LEN_SIZE is the size of the 'length' field in total. + Which may be 4,8, or 12 bytes! + 4 is standard DWARF2. + 8 is non-standard MIPS-IRIX 64-bit. + 12 is standard DWARF3 for 64 bit offsets. + Used in various routines: local variable names + must match the names here. +*/ +#define BEGIN_LEN_SIZE (uwordb_size + extension_size) + +/* + Return TRUE if we need the section, FALSE otherwise + + If any of the 'line-data-related' calls were made + including file or directory entries, + produce .debug_line . + +*/ +static int +dwarf_need_debug_line_section(Dwarf_P_Debug dbg) +{ + if (dbg->de_lines == NULL && dbg->de_file_entries == NULL + && dbg->de_inc_dirs == NULL) { + return FALSE; + } + return TRUE; +} + +/* + Convert debug information to a format such that + it can be written on disk. + Called exactly once per execution. +*/ +Dwarf_Signed +dwarf_transform_to_disk_form(Dwarf_P_Debug dbg, Dwarf_Error * error) +{ + /* + Section data in written out in a number of buffers. Each + _generate_*() function returns a cumulative count of buffers for + all the sections. get_section_bytes() returns pointers to these + buffers one at a time. */ + int nbufs = 0; + int sect = 0; + int err = 0; + Dwarf_Unsigned du = 0; + + if (dbg->de_version_magic_number != PRO_VERSION_MAGIC) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, DW_DLV_NOCOUNT); + } + + /* Create dwarf section headers */ + for (sect = 0; sect < NUM_DEBUG_SECTIONS; sect++) { + long flags = 0; + + switch (sect) { + + case DEBUG_INFO: + if (dbg->de_dies == NULL) + continue; + break; + + case DEBUG_LINE: + if (dwarf_need_debug_line_section(dbg) == FALSE) { + continue; + } + break; + + case DEBUG_ABBREV: + if (dbg->de_dies == NULL) + continue; + break; + + case DEBUG_FRAME: + if (dbg->de_frame_cies == NULL) + continue; + flags = SHF_MIPS_NOSTRIP; + break; + + case DEBUG_ARANGES: + if (dbg->de_arange == NULL) + continue; + break; + + case DEBUG_PUBNAMES: + if (dbg->de_simple_name_headers[dwarf_snk_pubname]. + sn_head == NULL) + continue; + break; + + case DEBUG_STR: + if (dbg->de_strings == NULL) + continue; + break; + + case DEBUG_FUNCNAMES: + if (dbg->de_simple_name_headers[dwarf_snk_funcname]. + sn_head == NULL) + continue; + break; + + case DEBUG_TYPENAMES: + if (dbg->de_simple_name_headers[dwarf_snk_typename]. + sn_head == NULL) + continue; + break; + + case DEBUG_VARNAMES: + if (dbg->de_simple_name_headers[dwarf_snk_varname]. + sn_head == NULL) + continue; + break; + + case DEBUG_WEAKNAMES: + if (dbg->de_simple_name_headers[dwarf_snk_weakname]. + sn_head == NULL) + continue; + break; + + case DEBUG_MACINFO: + if (dbg->de_first_macinfo == NULL) + continue; + break; + case DEBUG_LOC: + /* not handled yet */ + continue; + default: + /* logic error: missing a case */ + DWARF_P_DBG_ERROR(dbg, DW_DLE_ELF_SECT_ERR, DW_DLV_NOCOUNT); + } + { + int new_base_elf_sect; + + if (dbg->de_callback_func_b) { + new_base_elf_sect = + dbg->de_callback_func_b(_dwarf_sectnames[sect], + /* rec size */ 1, + SECTION_TYPE, + flags, SHN_UNDEF, 0, &du, &err); + + } else { + int name_idx = 0; + new_base_elf_sect = dbg->de_callback_func( + _dwarf_sectnames[sect], + dbg->de_relocation_record_size, + SECTION_TYPE, flags, + SHN_UNDEF, 0, + &name_idx, &err); + du = name_idx; + } + if (new_base_elf_sect == -1) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_ELF_SECT_ERR, + DW_DLV_NOCOUNT); + } + dbg->de_elf_sects[sect] = new_base_elf_sect; + + dbg->de_sect_name_idx[sect] = du; + } + } + + nbufs = 0; + + /* + Changing the order in which the sections are generated may cause + problems because of relocations. */ + + if (dwarf_need_debug_line_section(dbg) == TRUE) { + nbufs = _dwarf_pro_generate_debugline(dbg, error); + if (nbufs < 0) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGLINE_ERROR, + DW_DLV_NOCOUNT); + } + } + + if (dbg->de_frame_cies) { + nbufs = _dwarf_pro_generate_debugframe(dbg, error); + if (nbufs < 0) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGFRAME_ERROR, + DW_DLV_NOCOUNT); + } + } + if (dbg->de_first_macinfo) { + nbufs = _dwarf_pro_transform_macro_info_to_disk(dbg, error); + if (nbufs < 0) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGMACINFO_ERROR, + DW_DLV_NOCOUNT); + } + } + + if (dbg->de_dies) { + nbufs = _dwarf_pro_generate_debuginfo(dbg, error); + if (nbufs < 0) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR, + DW_DLV_NOCOUNT); + } + } + + if (dbg->de_arange) { + nbufs = _dwarf_transform_arange_to_disk(dbg, error); + if (nbufs < 0) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR, + DW_DLV_NOCOUNT); + } + } + + if (dbg->de_simple_name_headers[dwarf_snk_pubname].sn_head) { + nbufs = _dwarf_transform_simplename_to_disk(dbg, + dwarf_snk_pubname, + DEBUG_PUBNAMES, + error); + + + if (nbufs < 0) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR, + DW_DLV_NOCOUNT); + } + } + + if (dbg->de_simple_name_headers[dwarf_snk_funcname].sn_head) { + nbufs = _dwarf_transform_simplename_to_disk(dbg, + dwarf_snk_funcname, + DEBUG_FUNCNAMES, + error); + if (nbufs < 0) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR, + DW_DLV_NOCOUNT); + } + } + + if (dbg->de_simple_name_headers[dwarf_snk_typename].sn_head) { + nbufs = _dwarf_transform_simplename_to_disk(dbg, + dwarf_snk_typename, + DEBUG_TYPENAMES, + error); + if (nbufs < 0) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR, + DW_DLV_NOCOUNT); + } + } + + if (dbg->de_simple_name_headers[dwarf_snk_varname].sn_head) { + nbufs = _dwarf_transform_simplename_to_disk(dbg, + dwarf_snk_varname, + DEBUG_VARNAMES, + error); + + if (nbufs < 0) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR, + DW_DLV_NOCOUNT); + } + } + + if (dbg->de_simple_name_headers[dwarf_snk_weakname].sn_head) { + nbufs = _dwarf_transform_simplename_to_disk(dbg, + dwarf_snk_weakname, DEBUG_WEAKNAMES, error); + if (nbufs < 0) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR, + DW_DLV_NOCOUNT); + } + } + + { + Dwarf_Signed new_secs = 0; + int res = 0; + + res = dbg->de_transform_relocs_to_disk(dbg, &new_secs); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR, + DW_DLV_NOCOUNT); + } + nbufs += new_secs; + } + return nbufs; +} + + +/*--------------------------------------------------------------- + Generate debug_line section +---------------------------------------------------------------*/ +static int +_dwarf_pro_generate_debugline(Dwarf_P_Debug dbg, Dwarf_Error * error) +{ + Dwarf_P_Inc_Dir curdir = 0; + Dwarf_P_F_Entry curentry = 0; + Dwarf_P_Line curline = 0; + Dwarf_P_Line prevline = 0; + + /* all data named cur* are used to loop thru linked lists */ + + int sum_bytes = 0; + int prolog_size = 0; + unsigned char *data = 0; /* holds disk form data */ + int elfsectno = 0; + unsigned char *start_line_sec = 0; /* pointer to the buffer at + section start */ + /* temps for memcpy */ + Dwarf_Unsigned du = 0; + Dwarf_Ubyte db = 0; + Dwarf_Half dh = 0; + int res = 0; + int uwordb_size = dbg->de_offset_size; + int extension_size = dbg->de_64bit_extension ? 4 : 0; + int upointer_size = dbg->de_pointer_size; + char buff1[ENCODE_SPACE_NEEDED]; + + + + sum_bytes = 0; + + elfsectno = dbg->de_elf_sects[DEBUG_LINE]; + + /* include directories */ + curdir = dbg->de_inc_dirs; + while (curdir) { + prolog_size += strlen(curdir->did_name) + 1; + curdir = curdir->did_next; + } + prolog_size++; /* last null following last directory + entry. */ + + /* file entries */ + curentry = dbg->de_file_entries; + while (curentry) { + prolog_size += + strlen(curentry->dfe_name) + 1 + curentry->dfe_nbytes; + curentry = curentry->dfe_next; + } + prolog_size++; /* last null byte */ + + + prolog_size += BEGIN_LEN_SIZE + sizeof_uhalf(dbg) + /* version # */ + uwordb_size + /* header length */ + sizeof_ubyte(dbg) + /* min_instr length */ + sizeof_ubyte(dbg) + /* default is_stmt */ + sizeof_ubyte(dbg) + /* linebase */ + sizeof_ubyte(dbg) + /* linerange */ + sizeof_ubyte(dbg); /* opcode base */ + + /* length of table specifying # of opnds */ + prolog_size += sizeof(std_opcode_len); + + GET_CHUNK(dbg, elfsectno, data, prolog_size, error); + start_line_sec = data; + + /* copy over the data */ + /* total_length */ + du = 0; + if (extension_size) { + Dwarf_Word x = DISTINGUISHED_VALUE; + + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &x, + sizeof(x), extension_size); + data += extension_size; + } + + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du, + sizeof(du), uwordb_size); + data += uwordb_size; + + dh = VERSION; + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &dh, + sizeof(dh), sizeof(Dwarf_Half)); + data += sizeof(Dwarf_Half); + + /* header length */ + du = prolog_size - (BEGIN_LEN_SIZE + sizeof(Dwarf_Half) + + uwordb_size); + { + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du, + sizeof(du), uwordb_size); + data += uwordb_size; + } + db = MIN_INST_LENGTH; + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + db = DEFAULT_IS_STMT; + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + db = (Dwarf_Ubyte) LINE_BASE; + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + db = LINE_RANGE; + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + db = OPCODE_BASE; + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + WRITE_UNALIGNED(dbg, (void *) data, (const void *) std_opcode_len, + sizeof(std_opcode_len), sizeof(std_opcode_len)); + data += sizeof(std_opcode_len); + + /* copy over include directories */ + curdir = dbg->de_inc_dirs; + while (curdir) { + strcpy((char *) data, curdir->did_name); + data += strlen(curdir->did_name) + 1; + curdir = curdir->did_next; + } + *data = '\0'; /* last null */ + data++; + + /* copy file entries */ + curentry = dbg->de_file_entries; + while (curentry) { + strcpy((char *) data, curentry->dfe_name); + data += strlen(curentry->dfe_name) + 1; + /* copies of leb numbers, no endian issues */ + memcpy((void *) data, + (const void *) curentry->dfe_args, curentry->dfe_nbytes); + data += curentry->dfe_nbytes; + curentry = curentry->dfe_next; + } + *data = '\0'; + data++; + + sum_bytes += prolog_size; + + curline = dbg->de_lines; + prevline = (Dwarf_P_Line) + _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Line_s)); + if (prevline == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_LINE_ALLOC, -1); + } + _dwarf_pro_reg_init(prevline); + /* generate opcodes for line numbers */ + while (curline) { + int nbytes; + char *arg; + int opc; + int no_lns_copy; /* if lns copy opcode doesnt need to be + generated, if special opcode or end + sequence */ + Dwarf_Unsigned addr_adv; + int line_adv; /* supposed to be a reasonably small + number, so the size should not be a + problem. ? */ + + no_lns_copy = 0; + if (curline->dpl_opc != 0) { + int inst_bytes; /* no of bytes in extended opcode */ + char *str; /* hold leb encoded inst_bytes */ + int str_nbytes; /* no of bytes in str */ + + switch (curline->dpl_opc) { + case DW_LNE_end_sequence: + + /* Advance pc to end of text section. */ + addr_adv = curline->dpl_address - prevline->dpl_address; + if (addr_adv > 0) { + db = DW_LNS_advance_pc; + res = + _dwarf_pro_encode_leb128_nm(addr_adv / + MIN_INST_LENGTH, + &nbytes, buff1, + sizeof(buff1)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); + } + GET_CHUNK(dbg, elfsectno, data, + nbytes + sizeof(Dwarf_Ubyte), error); + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &db, sizeof(db), + sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + /* leb, no endianness issue */ + memcpy((void *) data, (const void *) buff1, nbytes); + data += nbytes + sizeof(Dwarf_Ubyte); + sum_bytes += nbytes + sizeof(Dwarf_Ubyte); + prevline->dpl_address = curline->dpl_address; + } + + /* first null byte */ + db = 0; + GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte), + error); + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + sum_bytes += sizeof(Dwarf_Ubyte); + + /* write length of extended opcode */ + inst_bytes = sizeof(Dwarf_Ubyte); + res = + _dwarf_pro_encode_leb128_nm(inst_bytes, &str_nbytes, + buff1, sizeof(buff1)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); + } + GET_CHUNK(dbg, elfsectno, data, str_nbytes, error); + memcpy((void *) data, (const void *) buff1, str_nbytes); + data += str_nbytes; + sum_bytes += str_nbytes; + + /* write extended opcode */ + db = DW_LNE_end_sequence; + GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte), + error); + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + sum_bytes += sizeof(Dwarf_Ubyte); + /* reset value to original values */ + _dwarf_pro_reg_init(prevline); + no_lns_copy = 1; + /* this is set only for end_sequence, so that a + dw_lns_copy is not generated */ + break; + + case DW_LNE_set_address: + + /* first null byte */ + db = 0; + GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte), + error); + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + sum_bytes += sizeof(Dwarf_Ubyte); + + /* write length of extended opcode */ + inst_bytes = sizeof(Dwarf_Ubyte) + upointer_size; + res = + _dwarf_pro_encode_leb128_nm(inst_bytes, &str_nbytes, + buff1, sizeof(buff1)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); + } + GET_CHUNK(dbg, elfsectno, data, str_nbytes, error); + str = buff1; + /* leb number, no endian issue */ + memcpy((void *) data, (const void *) str, str_nbytes); + data += str_nbytes; + sum_bytes += str_nbytes; + + /* write extended opcode */ + db = DW_LNE_set_address; + GET_CHUNK(dbg, elfsectno, data, upointer_size + + sizeof(Dwarf_Ubyte), error); + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + sum_bytes += sizeof(Dwarf_Ubyte); + + /* reloc for address */ + res = dbg->de_reloc_name(dbg, DEBUG_LINE, + sum_bytes, /* r_offset */ + curline->dpl_r_symidx, + dwarf_drt_data_reloc, + uwordb_size); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); + } + + /* write offset (address) */ + du = curline->dpl_address; + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du, + sizeof(du), upointer_size); + data += upointer_size; + sum_bytes += upointer_size; + prevline->dpl_address = curline->dpl_address; + no_lns_copy = 1; + break; + } + } else { + if (curline->dpl_file != prevline->dpl_file) { + db = DW_LNS_set_file; + res = + _dwarf_pro_encode_leb128_nm(curline->dpl_file, + &nbytes, buff1, + sizeof(buff1)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); + } + arg = buff1; + GET_CHUNK(dbg, elfsectno, data, + nbytes + sizeof(Dwarf_Ubyte), error); + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + memcpy((void *) data, (const void *) arg, nbytes); + data += nbytes; + sum_bytes += nbytes + sizeof(Dwarf_Ubyte); + prevline->dpl_file = curline->dpl_file; + } + if (curline->dpl_column != prevline->dpl_column) { + db = DW_LNS_set_column; + res = _dwarf_pro_encode_leb128_nm(curline->dpl_column, + &nbytes, + buff1, sizeof(buff1)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); + } + + arg = buff1; + GET_CHUNK(dbg, elfsectno, data, + nbytes + sizeof(Dwarf_Ubyte), error); + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + memcpy((void *) data, (const void *) arg, nbytes); + data += nbytes; + sum_bytes += nbytes + sizeof(Dwarf_Ubyte); + prevline->dpl_column = curline->dpl_column; + } + if (curline->dpl_is_stmt != prevline->dpl_is_stmt) { + db = DW_LNS_negate_stmt; + GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte), + error); + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + sum_bytes += sizeof(Dwarf_Ubyte); + prevline->dpl_is_stmt = curline->dpl_is_stmt; + } + if (curline->dpl_basic_block == true && + prevline->dpl_basic_block == false) { + db = DW_LNS_set_basic_block; + GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte), + error); + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + sum_bytes += sizeof(Dwarf_Ubyte); + prevline->dpl_basic_block = curline->dpl_basic_block; + } + addr_adv = curline->dpl_address - prevline->dpl_address; + + line_adv = (int) (curline->dpl_line - prevline->dpl_line); + if ((addr_adv % MIN_INST_LENGTH) != 0) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_WRONG_ADDRESS, -1); + } + if ((opc = _dwarf_pro_get_opc(addr_adv, line_adv)) > 0) { + no_lns_copy = 1; + db = opc; + GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte), + error); + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + sum_bytes += sizeof(Dwarf_Ubyte); + prevline->dpl_basic_block = false; + prevline->dpl_address = curline->dpl_address; + prevline->dpl_line = curline->dpl_line; + } else { + if (addr_adv > 0) { + db = DW_LNS_advance_pc; + res = + _dwarf_pro_encode_leb128_nm(addr_adv / + MIN_INST_LENGTH, + &nbytes, buff1, + sizeof(buff1)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); + } + + arg = buff1; + GET_CHUNK(dbg, elfsectno, data, + nbytes + sizeof(Dwarf_Ubyte), error); + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + memcpy((void *) data, (const void *) arg, nbytes); + data += nbytes + sizeof(Dwarf_Ubyte); + sum_bytes += nbytes + sizeof(Dwarf_Ubyte); + prevline->dpl_basic_block = false; + prevline->dpl_address = curline->dpl_address; + } + if (line_adv != 0) { + db = DW_LNS_advance_line; + res = _dwarf_pro_encode_signed_leb128_nm(line_adv, + &nbytes, + buff1, + sizeof + (buff1)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); + } + + arg = buff1; + GET_CHUNK(dbg, elfsectno, data, + nbytes + sizeof(Dwarf_Ubyte), error); + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &db, sizeof(db), + sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + memcpy((void *) data, (const void *) arg, nbytes); + data += nbytes + sizeof(Dwarf_Ubyte); + sum_bytes += nbytes + sizeof(Dwarf_Ubyte); + prevline->dpl_basic_block = false; + prevline->dpl_line = curline->dpl_line; + } + } + } /* ends else for opc != 0 */ + if (no_lns_copy == 0) { /* if not a special or dw_lne_end_seq + generate a matrix line */ + db = DW_LNS_copy; + GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte), error); + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + sum_bytes += sizeof(Dwarf_Ubyte); + prevline->dpl_basic_block = false; + } + curline = curline->dpl_next; + } + + /* write total length field */ + du = sum_bytes - BEGIN_LEN_SIZE; + { + start_line_sec += extension_size; + WRITE_UNALIGNED(dbg, (void *) start_line_sec, + (const void *) &du, sizeof(du), uwordb_size); + } + + return (int) dbg->de_n_debug_sect; +} + +/*--------------------------------------------------------------- + Generate debug_frame section +---------------------------------------------------------------*/ +static int +_dwarf_pro_generate_debugframe(Dwarf_P_Debug dbg, Dwarf_Error * error) +{ + int elfsectno = 0; + int i = 0; + int firsttime = 1; + int pad = 0; /* Pad for padding to align cies and fdes */ + Dwarf_P_Cie curcie = 0; + Dwarf_P_Fde curfde = 0; + unsigned char *data = 0; + Dwarf_sfixed dsw = 0; + Dwarf_Unsigned du = 0; + Dwarf_Ubyte db = 0; + long *cie_offs = 0; /* Holds byte offsets for links to fde's */ + unsigned long cie_length = 0; + int cie_no = 0; + int uwordb_size = dbg->de_offset_size; + int extension_size = dbg->de_64bit_extension ? 4 : 0; + int upointer_size = dbg->de_pointer_size; + Dwarf_Unsigned cur_off = 0; /* current offset of written data, held + for relocation info */ + + elfsectno = dbg->de_elf_sects[DEBUG_FRAME]; + + curcie = dbg->de_frame_cies; + cie_length = 0; + cur_off = 0; + cie_offs = (long *) + _dwarf_p_get_alloc(dbg, sizeof(long) * dbg->de_n_cie); + if (cie_offs == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1); + } + /* Generate cie number as we go along. This writes + all CIEs first before any FDEs, which is rather + different from the order a compiler might like (which + might be each CIE followed by its FDEs then the next CIE, and + so on). */ + cie_no = 1; + while (curcie) { + char *code_al = 0; + int c_bytes = 0; + char *data_al = 0; + int d_bytes = 0; + int res = 0; + char buff1[ENCODE_SPACE_NEEDED]; + char buff2[ENCODE_SPACE_NEEDED]; + char buff3[ENCODE_SPACE_NEEDED]; + char *augmentation = 0; + char *augmented_al = 0; + long augmented_fields_length = 0; + int a_bytes = 0; + + res = _dwarf_pro_encode_leb128_nm(curcie->cie_code_align, + &c_bytes, + buff1, sizeof(buff1)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1); + } + /* Before April 1999, the following was using an unsigned + encode. That worked ok even though the decoder used the + correct signed leb read, but doing the encode correctly + (according to the dwarf spec) saves space in the output file + and is completely compatible. + + Note the actual stored amount on MIPS was 10 bytes (!) to + store the value -4. (hex)fc ffffffff ffffffff 01 The + libdwarf consumer consumed all 10 bytes too! + + old version res = + _dwarf_pro_encode_leb128_nm(curcie->cie_data_align, + + below is corrected signed version. */ + res = _dwarf_pro_encode_signed_leb128_nm(curcie->cie_data_align, + &d_bytes, + buff2, sizeof(buff2)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1); + } + code_al = buff1; + data_al = buff2; + + /* get the correct offset */ + if (firsttime) { + cie_offs[cie_no - 1] = 0; + firsttime = 0; + } else { + cie_offs[cie_no - 1] = cie_offs[cie_no - 2] + + (long) cie_length + BEGIN_LEN_SIZE; + } + cie_no++; + augmentation = curcie->cie_aug; + if (strcmp(augmentation, DW_CIE_AUGMENTER_STRING_V0) == 0) { + augmented_fields_length = 0; + res = _dwarf_pro_encode_leb128_nm(augmented_fields_length, + &a_bytes, buff3, + sizeof(buff3)); + augmented_al = buff3; + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1); + } + cie_length = uwordb_size + /* cie_id */ + sizeof(Dwarf_Ubyte) + /* cie version */ + strlen(curcie->cie_aug) + 1 + /* augmentation */ + c_bytes + /* code alignment factor */ + d_bytes + /* data alignment factor */ + sizeof(Dwarf_Ubyte) + /* return reg address */ + a_bytes + /* augmentation length */ + curcie->cie_inst_bytes; + } else { + cie_length = uwordb_size + /* cie_id */ + sizeof(Dwarf_Ubyte) + /* cie version */ + strlen(curcie->cie_aug) + 1 + /* augmentation */ + c_bytes + d_bytes + sizeof(Dwarf_Ubyte) + /* return + reg + address + */ + curcie->cie_inst_bytes; + } + pad = (int) PADDING(cie_length, upointer_size); + cie_length += pad; + GET_CHUNK(dbg, elfsectno, data, cie_length + + BEGIN_LEN_SIZE, error); + if (extension_size) { + Dwarf_Unsigned x = DISTINGUISHED_VALUE; + + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &x, + sizeof(x), extension_size); + data += extension_size; + + } + du = cie_length; + /* total length of cie */ + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &du, sizeof(du), uwordb_size); + data += uwordb_size; + + /* cie-id is a special value. */ + du = DW_CIE_ID; + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du, + sizeof(du), uwordb_size); + data += uwordb_size; + + db = curcie->cie_version; + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + strcpy((char *) data, curcie->cie_aug); + data += strlen(curcie->cie_aug) + 1; + memcpy((void *) data, (const void *) code_al, c_bytes); + data += c_bytes; + memcpy((void *) data, (const void *) data_al, d_bytes); + data += d_bytes; + db = curcie->cie_ret_reg; + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); + + if (strcmp(augmentation, DW_CIE_AUGMENTER_STRING_V0) == 0) { + memcpy((void *) data, (const void *) augmented_al, a_bytes); + data += a_bytes; + } + memcpy((void *) data, (const void *) curcie->cie_inst, + curcie->cie_inst_bytes); + data += curcie->cie_inst_bytes; + for (i = 0; i < pad; i++) { + *data = DW_CFA_nop; + data++; + } + curcie = curcie->cie_next; + } + /* calculate current offset */ + cur_off = cie_offs[cie_no - 2] + cie_length + BEGIN_LEN_SIZE; + + /* write out fde's */ + curfde = dbg->de_frame_fdes; + while (curfde) { + Dwarf_P_Frame_Pgm curinst = 0; + long fde_length = 0; + int pad = 0; + Dwarf_P_Cie cie_ptr = 0; + Dwarf_Word cie_index = 0; + Dwarf_Word index = 0; + int oet_length = 0; + int afl_length = 0; + int res = 0; + int v0_augmentation = 0; +#if 0 + unsigned char *fde_start_point = 0; +#endif + char afl_buff[ENCODE_SPACE_NEEDED]; + + /* Find the CIE associated with this fde. */ + cie_ptr = dbg->de_frame_cies; + cie_index = curfde->fde_cie; + index = 1; /* The cie_index of the first cie is 1, + not 0. */ + while (cie_ptr && index < cie_index) { + cie_ptr = cie_ptr->cie_next; + index++; + } + if (cie_ptr == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_NULL, -1); + } + + if (strcmp(cie_ptr->cie_aug, DW_CIE_AUGMENTER_STRING_V0) == 0) { + v0_augmentation = 1; + oet_length = sizeof(Dwarf_sfixed); + /* encode the length of augmented fields. */ + res = _dwarf_pro_encode_leb128_nm(oet_length, + &afl_length, afl_buff, + sizeof(afl_buff)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1); + } + + fde_length = curfde->fde_n_bytes + BEGIN_LEN_SIZE + /* cie + pointer + */ + upointer_size + /* initial loc */ + upointer_size + /* address range */ + afl_length + /* augmented field length */ + oet_length; /* exception_table offset */ + } else { + fde_length = curfde->fde_n_bytes + BEGIN_LEN_SIZE + /* cie + pointer + */ + upointer_size + /* initial loc */ + upointer_size; /* address range */ + } + + + if (curfde->fde_die) { + /* IRIX/MIPS extension: + Using fde offset, generate DW_AT_MIPS_fde attribute for the + die corresponding to this fde. */ + if(_dwarf_pro_add_AT_fde(dbg, curfde->fde_die, cur_off, + error) < 0) { + return -1; + } + } + + /* store relocation for cie pointer */ + res = dbg->de_reloc_name(dbg, DEBUG_FRAME, cur_off + + BEGIN_LEN_SIZE /* r_offset */, + dbg->de_sect_name_idx[DEBUG_FRAME], + dwarf_drt_data_reloc, uwordb_size); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); + } + + /* store relocation information for initial location */ + res = dbg->de_reloc_name(dbg, DEBUG_FRAME, + cur_off + BEGIN_LEN_SIZE + + upointer_size /* r_offset */, + curfde->fde_r_symidx, + dwarf_drt_data_reloc, upointer_size); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); + } + /* Store the relocation information for the + offset_into_exception_info field, if the offset is valid (0 + is a valid offset). */ + if (v0_augmentation && + curfde->fde_offset_into_exception_tables >= 0) { + + res = dbg->de_reloc_name(dbg, DEBUG_FRAME, + /* r_offset, where in cie this + field starts */ + cur_off + BEGIN_LEN_SIZE + + uwordb_size + 2 * upointer_size + + afl_length, + curfde->fde_exception_table_symbol, + dwarf_drt_segment_rel, + sizeof(Dwarf_sfixed)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); + } + } + + /* adjust for padding */ + pad = (int) PADDING(fde_length, upointer_size); + fde_length += pad; + + + /* write out fde */ + GET_CHUNK(dbg, elfsectno, data, fde_length + BEGIN_LEN_SIZE, + error); +#if 0 + fde_start_point = data; +#endif + du = fde_length; + { + if (extension_size) { + Dwarf_Word x = DISTINGUISHED_VALUE; + + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &x, + sizeof(x), extension_size); + data += extension_size; + } + /* length */ + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &du, + sizeof(du), uwordb_size); + data += uwordb_size; + + /* offset to cie */ + du = cie_offs[curfde->fde_cie - 1]; + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &du, + sizeof(du), uwordb_size); + data += uwordb_size; + + du = curfde->fde_initloc; + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &du, + sizeof(du), upointer_size); + data += upointer_size; + + if (dbg->de_reloc_pair && + curfde->fde_end_symbol != 0 && + curfde->fde_addr_range == 0) { + /* symbolic reloc, need reloc for length What if we + really know the length? If so, should use the other + part of 'if'. */ + Dwarf_Unsigned val; + + res = dbg->de_reloc_pair(dbg, + /* DEBUG_ARANGES, */ + DEBUG_FRAME, cur_off + 2 * uwordb_size + upointer_size, /* r_offset + */ + curfde->fde_r_symidx, + curfde->fde_end_symbol, + dwarf_drt_first_of_length_pair, + upointer_size); + if (res != DW_DLV_OK) { + { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (0); + } + } + + /* arrange pre-calc so assem text can do .word end - + begin + val (gets val from stream) */ + val = curfde->fde_end_symbol_offset - + curfde->fde_initloc; + WRITE_UNALIGNED(dbg, data, + (const void *) &val, + sizeof(val), upointer_size); + data += upointer_size; + } else { + + du = curfde->fde_addr_range; + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &du, + sizeof(du), upointer_size); + data += upointer_size; + } + } + + if (v0_augmentation) { + /* write the encoded augmented field length. */ + memcpy((void *) data, (const void *) afl_buff, afl_length); + data += afl_length; + /* write the offset_into_exception_tables field. */ + dsw = + (Dwarf_sfixed) curfde->fde_offset_into_exception_tables; + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &dsw, + sizeof(dsw), sizeof(Dwarf_sfixed)); + data += sizeof(Dwarf_sfixed); + } + + curinst = curfde->fde_inst; + if(curfde->fde_block) { + unsigned long size = curfde->fde_inst_block_size; + memcpy((void *) data, (const void *) curfde->fde_block, size); + data += size; + } else { + while (curinst) { + db = curinst->dfp_opcode; + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + data += sizeof(Dwarf_Ubyte); +#if 0 + if (curinst->dfp_sym_index) { + int res = dbg->de_reloc_name(dbg, + DEBUG_FRAME, + /* r_offset = */ + (data - fde_start_point) + cur_off + uwordb_size, + curinst->dfp_sym_index, + dwarf_drt_data_reloc, + upointer_size); + if (res != DW_DLV_OK) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (0); + } + } +#endif + memcpy((void *) data, + (const void *) curinst->dfp_args, + curinst->dfp_nbytes); + data += curinst->dfp_nbytes; + curinst = curinst->dfp_next; + } + } + /* padding */ + for (i = 0; i < pad; i++) { + *data = DW_CFA_nop; + data++; + } + cur_off += fde_length + uwordb_size; + curfde = curfde->fde_next; + } + + + return (int) dbg->de_n_debug_sect; +} + +/* + These functions remember all the markers we see along + with the right offset in the .debug_info section so that + we can dump them all back to the user with the section info. +*/ + +static int +marker_init(Dwarf_P_Debug dbg, + unsigned count) +{ + dbg->de_marker_n_alloc = count; + dbg->de_markers = NULL; + if (count > 0) { + dbg->de_markers = _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Marker_s) * + dbg->de_marker_n_alloc); + if (dbg->de_markers == NULL) { + dbg->de_marker_n_alloc = 0; + return -1; + } + } + return 0; +} + +static int +marker_add(Dwarf_P_Debug dbg, + Dwarf_Unsigned offset, + Dwarf_Unsigned marker) +{ + if (dbg->de_marker_n_alloc >= (dbg->de_marker_n_used + 1)) { + unsigned n = dbg->de_marker_n_used++; + dbg->de_markers[n].ma_offset = offset; + dbg->de_markers[n].ma_marker = marker; + return 0; + } + + return -1; +} + +Dwarf_Signed +dwarf_get_die_markers(Dwarf_P_Debug dbg, + Dwarf_P_Marker * marker_list, /* pointer to a pointer */ + Dwarf_Unsigned * marker_count, + Dwarf_Error * error) +{ + if (marker_list == NULL || marker_count == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, DW_DLV_BADADDR); + } + if (dbg->de_marker_n_used != dbg->de_marker_n_alloc) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_MAF, DW_DLV_BADADDR); + } + + *marker_list = dbg->de_markers; + *marker_count = dbg->de_marker_n_used; + return DW_DLV_OK; +} + +/* These functions provide the offsets of DW_FORM_string + attributes in the section section_index. These information + will enable a producer app that is generating assembly + text output to easily emit those attributes in ascii form + without having to decode the byte stream. + */ +static int +string_attr_init (Dwarf_P_Debug dbg, + Dwarf_Signed section_index, + unsigned count) +{ + Dwarf_P_Per_Sect_String_Attrs sect_sa = &dbg->de_sect_string_attr[section_index]; + + sect_sa->sect_sa_n_alloc = count; + sect_sa->sect_sa_list = NULL; + if (count > 0) { + sect_sa->sect_sa_section_number = section_index; + sect_sa->sect_sa_list = _dwarf_p_get_alloc(dbg, + sizeof(struct Dwarf_P_String_Attr_s) + * sect_sa->sect_sa_n_alloc); + if (sect_sa->sect_sa_list == NULL) { + sect_sa->sect_sa_n_alloc = 0; + return -1; + } + } + return 0; +} + +static int +string_attr_add (Dwarf_P_Debug dbg, + Dwarf_Signed section_index, + Dwarf_Unsigned offset, + Dwarf_P_Attribute attr) +{ + Dwarf_P_Per_Sect_String_Attrs sect_sa = &dbg->de_sect_string_attr[section_index]; + if (sect_sa->sect_sa_n_alloc >= (sect_sa->sect_sa_n_used + 1)) { + unsigned n = sect_sa->sect_sa_n_used++; + sect_sa->sect_sa_list[n].sa_offset = offset; + sect_sa->sect_sa_list[n].sa_nbytes = attr->ar_nbytes; + return 0; + } + + return -1; +} + +int +dwarf_get_string_attributes_count(Dwarf_P_Debug dbg, + Dwarf_Unsigned * + count_of_sa_sections, + int *drd_buffer_version, + Dwarf_Error *error) +{ + int i; + unsigned int count = 0; + + for (i = 0; i < NUM_DEBUG_SECTIONS; ++i) { + if (dbg->de_sect_string_attr[i].sect_sa_n_used > 0) { + ++count; + } + } + *count_of_sa_sections = (Dwarf_Unsigned) count; + *drd_buffer_version = DWARF_DRD_BUFFER_VERSION; + + return DW_DLV_OK; +} + +int +dwarf_get_string_attributes_info(Dwarf_P_Debug dbg, + Dwarf_Signed *elf_section_index, + Dwarf_Unsigned *sect_sa_buffer_count, + Dwarf_P_String_Attr *sect_sa_buffer, + Dwarf_Error *error) +{ + int i; + int next = dbg->de_sect_sa_next_to_return; + + for (i = next; i < NUM_DEBUG_SECTIONS; ++i) { + Dwarf_P_Per_Sect_String_Attrs sect_sa = &dbg->de_sect_string_attr[i]; + if (sect_sa->sect_sa_n_used > 0) { + dbg->de_sect_sa_next_to_return = i + 1; + *elf_section_index = sect_sa->sect_sa_section_number; + *sect_sa_buffer_count = sect_sa->sect_sa_n_used; + *sect_sa_buffer = sect_sa->sect_sa_list; + return DW_DLV_OK; + } + } + return DW_DLV_NO_ENTRY; +} + + + +/*--------------------------------------------------------------- + Generate debug_info and debug_abbrev sections +---------------------------------------------------------------*/ +static int +_dwarf_pro_generate_debuginfo(Dwarf_P_Debug dbg, Dwarf_Error * error) +{ + int elfsectno_of_debug_info = 0; + int abbrevsectno = 0; + unsigned char *data = 0; + int cu_header_size = 0; + Dwarf_P_Abbrev curabbrev = 0; + Dwarf_P_Abbrev abbrev_head = 0; + Dwarf_P_Abbrev abbrev_tail = 0; + Dwarf_P_Die curdie = 0; + Dwarf_P_Die first_child = 0; + Dwarf_Word dw = 0; + Dwarf_Unsigned du = 0; + Dwarf_Half dh = 0; + Dwarf_Ubyte db = 0; + Dwarf_Half version = 0; /* Need 2 byte quantity. */ + Dwarf_Unsigned die_off = 0; /* Offset of die in debug_info. */ + int n_abbrevs = 0; + int res = 0; + unsigned marker_count = 0; + unsigned string_attr_count = 0; + unsigned string_attr_offset = 0; + + Dwarf_Small *start_info_sec = 0; + + int uwordb_size = dbg->de_offset_size; + int extension_size = dbg->de_64bit_extension ? 4 : 0; + + abbrev_head = abbrev_tail = NULL; + elfsectno_of_debug_info = dbg->de_elf_sects[DEBUG_INFO]; + + /* write cu header */ + cu_header_size = BEGIN_LEN_SIZE + sizeof(Dwarf_Half) + /* version + stamp + */ + uwordb_size + /* offset into abbrev table */ + sizeof(Dwarf_Ubyte); /* size of target address */ + GET_CHUNK(dbg, elfsectno_of_debug_info, data, cu_header_size, + error); + start_info_sec = data; + if (extension_size) { + du = DISTINGUISHED_VALUE; + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &du, sizeof(du), extension_size); + data += extension_size; + } + du = 0; /* length of debug_info, not counting + this field itself (unknown at this + point). */ + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &du, sizeof(du), uwordb_size); + data += uwordb_size; + + version = CURRENT_VERSION_STAMP; /* assume this length will not + change */ + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &version, + sizeof(version), sizeof(Dwarf_Half)); + data += sizeof(Dwarf_Half); + + du = 0; /* offset into abbrev table, not yet + known. */ + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &du, sizeof(du), uwordb_size); + data += uwordb_size; + + + db = dbg->de_pointer_size; + + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), 1); + + /* We have filled the chunk we got with GET_CHUNK. At this point we + no longer dare use "data" or "start_info_sec" as a pointer any + longer except to refer to that first small chunk for the cu + header. */ + + curdie = dbg->de_dies; + + /* create AT_macro_info if appropriate */ + if (dbg->de_first_macinfo != NULL) { + if (_dwarf_pro_add_AT_macro_info(dbg, curdie, 0, error) < 0) + return -1; + } + + /* create AT_stmt_list attribute if necessary */ + if (dwarf_need_debug_line_section(dbg) == TRUE) + if (_dwarf_pro_add_AT_stmt_list(dbg, curdie, error) < 0) + return -1; + + die_off = cu_header_size; + + /* + Relocation for abbrev offset in cu header store relocation + record in linked list */ + res = dbg->de_reloc_name(dbg, DEBUG_INFO, BEGIN_LEN_SIZE + + sizeof(Dwarf_Half), + /* r_offset */ + dbg->de_sect_name_idx[DEBUG_ABBREV], + dwarf_drt_data_reloc, uwordb_size); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1); + } + + /* pass 0: only top level dies, add at_sibling attribute to those + dies with children */ + first_child = curdie->di_child; + while (first_child && first_child->di_right) { + if (first_child->di_child) + dwarf_add_AT_reference(dbg, + first_child, + DW_AT_sibling, + first_child->di_right, error); + first_child = first_child->di_right; + } + + /* pass 1: create abbrev info, get die offsets, calc relocations */ + marker_count = 0; + string_attr_count = 0; + while (curdie != NULL) { + int nbytes = 0; + Dwarf_P_Attribute curattr; + Dwarf_P_Attribute new_first_attr; + Dwarf_P_Attribute new_last_attr; + char *space = 0; + int res = 0; + char buff1[ENCODE_SPACE_NEEDED]; + int i = 0; + + curdie->di_offset = die_off; + + if (curdie->di_marker != 0) + marker_count++; + + curabbrev = _dwarf_pro_getabbrev(curdie, abbrev_head); + if (curabbrev == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1); + } + if (abbrev_head == NULL) { + n_abbrevs = 1; + curabbrev->abb_idx = n_abbrevs; + abbrev_tail = abbrev_head = curabbrev; + } else { + /* check if its a new abbreviation, if yes, add to tail */ + if (curabbrev->abb_idx == 0) { + n_abbrevs++; + curabbrev->abb_idx = n_abbrevs; + abbrev_tail->abb_next = curabbrev; + abbrev_tail = curabbrev; + } + } + res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_idx, + &nbytes, + buff1, sizeof(buff1)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1); + } + space = _dwarf_p_get_alloc(dbg, nbytes); + if (space == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1); + } + memcpy(space, buff1, nbytes); + curdie->di_abbrev = space; + curdie->di_abbrev_nbytes = nbytes; + die_off += nbytes; + + /* Resorting the attributes!! */ + new_first_attr = new_last_attr = NULL; + curattr = curdie->di_attrs; + for (i = 0; i < (int)curabbrev->abb_n_attr; i++) { + Dwarf_P_Attribute ca; + Dwarf_P_Attribute cl; + + /* The following should always find an attribute! */ + for (ca = cl = curattr; + ca && curabbrev->abb_attrs[i] != ca->ar_attribute; + cl = ca, ca = ca->ar_next) + { + } + + if (!ca) { + DWARF_P_DBG_ERROR(dbg,DW_DLE_ABBREV_ALLOC, -1); + } + + /* Remove the attribute from the old list. */ + if (ca == curattr) { + curattr = ca->ar_next; + } else { + cl->ar_next = ca->ar_next; + } + + ca->ar_next = NULL; + + /* Add the attribute to the new list. */ + if (new_first_attr == NULL) { + new_first_attr = new_last_attr = ca; + } else { + new_last_attr->ar_next = ca; + new_last_attr = ca; + } + } + + curdie->di_attrs = new_first_attr; + + curattr = curdie->di_attrs; + + while (curattr) { + if (curattr->ar_rel_type != R_MIPS_NONE) { + switch (curattr->ar_attribute) { + case DW_AT_stmt_list: + curattr->ar_rel_symidx = + dbg->de_sect_name_idx[DEBUG_LINE]; + break; + case DW_AT_MIPS_fde: + curattr->ar_rel_symidx = + dbg->de_sect_name_idx[DEBUG_FRAME]; + break; + case DW_AT_macro_info: + curattr->ar_rel_symidx = + dbg->de_sect_name_idx[DEBUG_MACINFO]; + break; + default: + break; + } + res = dbg->de_reloc_name(dbg, DEBUG_INFO, die_off + curattr->ar_rel_offset, /* r_offset + */ + curattr->ar_rel_symidx, + dwarf_drt_data_reloc, + curattr->ar_reloc_len); + + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1); + } + + } + if (curattr->ar_attribute_form == DW_FORM_string) { + string_attr_count++; + } + die_off += curattr->ar_nbytes; + curattr = curattr->ar_next; + } + + /* depth first search */ + if (curdie->di_child) + curdie = curdie->di_child; + else { + while (curdie != NULL && curdie->di_right == NULL) { + curdie = curdie->di_parent; + die_off++; /* since we are writing a null die at + the end of each sibling chain */ + } + if (curdie != NULL) + curdie = curdie->di_right; + } + + } /* end while (curdie != NULL) */ + + res = marker_init(dbg, marker_count); + if (res == -1) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1); + } + res = string_attr_init(dbg, DEBUG_INFO, string_attr_count); + if (res == -1) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1); + } + + /* Pass 2: Write out the die information Here 'data' is a + temporary, one block for each GET_CHUNK. 'data' is overused. */ + curdie = dbg->de_dies; + while (curdie != NULL) { + Dwarf_P_Attribute curattr; + + if (curdie->di_marker != 0) { + res = marker_add(dbg, curdie->di_offset, curdie->di_marker); + if (res == -1) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1); + } + } + + /* index to abbreviation table */ + GET_CHUNK(dbg, elfsectno_of_debug_info, + data, curdie->di_abbrev_nbytes, error); + + memcpy((void *) data, + (const void *) curdie->di_abbrev, + curdie->di_abbrev_nbytes); + + /* Attribute values - need to fill in all form attributes */ + curattr = curdie->di_attrs; + string_attr_offset = curdie->di_offset + curdie->di_abbrev_nbytes; + + while (curattr) { + GET_CHUNK(dbg, elfsectno_of_debug_info, data, + (unsigned long) curattr->ar_nbytes, error); + switch (curattr->ar_attribute_form) { + case DW_FORM_ref1: + { + if (curattr->ar_ref_die->di_offset > + (unsigned) 0xff) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, -1); + } + db = curattr->ar_ref_die->di_offset; + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + break; + } + case DW_FORM_ref2: + { + if (curattr->ar_ref_die->di_offset > + (unsigned) 0xffff) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, -1); + } + dh = curattr->ar_ref_die->di_offset; + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &dh, + sizeof(dh), sizeof(Dwarf_Half)); + break; + } + case DW_FORM_ref_addr: + { + /* curattr->ar_ref_die == NULL! + * + * ref_addr doesn't take a CU-offset. + * This is different than other refs. + * This value will be set by the user of the + * producer library using a relocation. + * No need to set a value here. + */ +#if 0 + du = curattr->ar_ref_die->di_offset; + { + /* ref to offset of die */ + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &du, + sizeof(du), uwordb_size); + } +#endif + break; + + } + case DW_FORM_ref4: + { + if (curattr->ar_ref_die->di_offset > + (unsigned) 0xffffffff) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, -1); + } + dw = (Dwarf_Word) curattr->ar_ref_die->di_offset; + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &dw, + sizeof(dw), sizeof(Dwarf_ufixed)); + break; + } + case DW_FORM_ref8: + du = curattr->ar_ref_die->di_offset; + WRITE_UNALIGNED(dbg, (void *) data, + (const void *) &du, + sizeof(du), sizeof(Dwarf_Unsigned)); + break; + case DW_FORM_ref_udata: + { /* unsigned leb128 offset */ + + int nbytes; + char buff1[ENCODE_SPACE_NEEDED]; + + res = + _dwarf_pro_encode_leb128_nm(curattr-> + ar_ref_die-> + di_offset, &nbytes, + buff1, + sizeof(buff1)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1); + } + + memcpy(data, buff1, nbytes); + break; + } + default: + memcpy((void *) data, + (const void *) curattr->ar_data, + curattr->ar_nbytes); + break; + } + if (curattr->ar_attribute_form == DW_FORM_string) { + string_attr_add(dbg, DEBUG_INFO, string_attr_offset, curattr); + } + string_attr_offset += curattr->ar_nbytes; + curattr = curattr->ar_next; + } + + /* depth first search */ + if (curdie->di_child) + curdie = curdie->di_child; + else { + while (curdie != NULL && curdie->di_right == NULL) { + GET_CHUNK(dbg, elfsectno_of_debug_info, data, 1, error); + *data = '\0'; + curdie = curdie->di_parent; + } + if (curdie != NULL) + curdie = curdie->di_right; + } + } /* end while (curdir != NULL) */ + + /* Write out debug_info size */ + /* Dont include length field or extension bytes */ + du = die_off - BEGIN_LEN_SIZE; + WRITE_UNALIGNED(dbg, (void *) (start_info_sec + extension_size), + (const void *) &du, sizeof(du), uwordb_size); + + + data = 0; /* Emphasise not usable now */ + + /* Write out debug_abbrev section */ + abbrevsectno = dbg->de_elf_sects[DEBUG_ABBREV]; + + curabbrev = abbrev_head; + while (curabbrev) { + char *val; + int nbytes; + int idx; + int res; + char buff1[ENCODE_SPACE_NEEDED]; + + res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_idx, &nbytes, + buff1, sizeof(buff1)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1); + } + + GET_CHUNK(dbg, abbrevsectno, data, nbytes, error); + val = buff1; + memcpy((void *) data, (const void *) val, nbytes); + res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_tag, &nbytes, + buff1, sizeof(buff1)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1); + } + val = buff1; + GET_CHUNK(dbg, abbrevsectno, data, nbytes, error); + memcpy((void *) data, (const void *) val, nbytes); + db = curabbrev->abb_children; + GET_CHUNK(dbg, abbrevsectno, data, sizeof(Dwarf_Ubyte), error); + WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, + sizeof(db), sizeof(Dwarf_Ubyte)); + + /* add attributes and forms */ + for (idx = 0; idx < curabbrev->abb_n_attr; idx++) { + res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_attrs[idx], + &nbytes, + buff1, sizeof(buff1)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1); + } + val = buff1; + GET_CHUNK(dbg, abbrevsectno, data, nbytes, error); + memcpy((void *) data, (const void *) val, nbytes); + res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_forms[idx], + &nbytes, + buff1, sizeof(buff1)); + if (res != DW_DLV_OK) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1); + } + val = buff1; + GET_CHUNK(dbg, abbrevsectno, data, nbytes, error); + memcpy((void *) data, (const void *) val, nbytes); + } + GET_CHUNK(dbg, abbrevsectno, data, 2, error); /* two zeros, + for last + entry, see + dwarf2 sec + 7.5.3 */ + *data = 0; + data++; + *data = 0; + + curabbrev = curabbrev->abb_next; + } + + GET_CHUNK(dbg, abbrevsectno, data, 1, error); /* one zero, + for end of + cu, see + dwarf2 sec + 7.5.3 */ + *data = 0; + + + return (int) dbg->de_n_debug_sect; +} + + +/*--------------------------------------------------------------------- + Get a buffer of section data. + section_idx is the elf-section number that this data applies to. + length shows length of returned data +----------------------------------------------------------------------*/ + /*ARGSUSED*/ /* pretend all args used */ + Dwarf_Ptr +dwarf_get_section_bytes(Dwarf_P_Debug dbg, + Dwarf_Signed dwarf_section, + Dwarf_Signed * section_idx, + Dwarf_Unsigned * length, Dwarf_Error * error) +{ + Dwarf_Ptr buf; + + if (dbg->de_version_magic_number != PRO_VERSION_MAGIC) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, NULL); + } + + if (dbg->de_debug_sects == 0) { + /* no more data !! */ + return NULL; + } + if (dbg->de_debug_sects->ds_elf_sect_no == MAGIC_SECT_NO) { + /* no data ever entered !! */ + return NULL; + } + *section_idx = dbg->de_debug_sects->ds_elf_sect_no; + *length = dbg->de_debug_sects->ds_nbytes; + + buf = (Dwarf_Ptr *) dbg->de_debug_sects->ds_data; + + dbg->de_debug_sects = dbg->de_debug_sects->ds_next; + + /* We may want to call the section stuff more than once: see + dwarf_reset_section_bytes() do not do: dbg->de_n_debug_sect--; */ + + return buf; +} + +/* + No errors possible. +*/ +void +dwarf_reset_section_bytes(Dwarf_P_Debug dbg) +{ + dbg->de_debug_sects = dbg->de_first_debug_sect; + /* No need to reset; commented out decrement. dbg->de_n_debug_sect + = ???; */ + dbg->de_reloc_next_to_return = 0; + dbg->de_sect_sa_next_to_return = 0; +} + +/* + Storage handler. Gets either a new chunk of memory, or + a pointer in existing memory, from the linked list attached + to dbg at de_debug_sects, depending on size of nbytes + + Assume dbg not null, checked in top level routine + + Returns a pointer to the allocated buffer space for the + lib to fill in, predincrements next-to-use count so the + space requested is already counted 'used' + when this returns (ie, reserved). + +*/ +Dwarf_Small * +_dwarf_pro_buffer(Dwarf_P_Debug dbg, + int elfsectno, unsigned long nbytes) +{ + Dwarf_P_Section_Data cursect; + + + cursect = dbg->de_current_active_section; + /* By using MAGIC_SECT_NO we allow the following MAGIC_SECT_NO must + not match any legit section number. test to have just two + clauses (no NULL pointer test) See dwarf_producer_init(). */ + if ((cursect->ds_elf_sect_no != elfsectno) || + ((cursect->ds_nbytes + nbytes) > cursect->ds_orig_alloc) + ) { + + /* Either the elf section has changed or there is not enough + space in the current section. + + Create a new Dwarf_P_Section_Data_s for the chunk. and have + space 'on the end' for the buffer itself so we just do one + malloc (not two). + + */ + unsigned long space = nbytes; + + if (nbytes < CHUNK_SIZE) + space = CHUNK_SIZE; + + cursect = (Dwarf_P_Section_Data) + _dwarf_p_get_alloc(dbg, + sizeof(struct Dwarf_P_Section_Data_s) + + space); + + + if (cursect == NULL) + return (NULL); + + /* _dwarf_p_get_alloc zeroes the space... */ + + cursect->ds_data = (char *) cursect + + sizeof(struct Dwarf_P_Section_Data_s); + cursect->ds_orig_alloc = space; + cursect->ds_elf_sect_no = elfsectno; + cursect->ds_nbytes = nbytes; /* reserve this number of bytes + of space for caller to fill + in */ + + /* Now link on the end of the list, and mark this one as the + current one */ + + if (dbg->de_debug_sects->ds_elf_sect_no == MAGIC_SECT_NO) { + /* the only entry is the special one for 'no entry' so + delete that phony one while adding this initial real + one. */ + dbg->de_debug_sects = cursect; + dbg->de_current_active_section = cursect; + dbg->de_first_debug_sect = cursect; + } else { + dbg->de_current_active_section->ds_next = cursect; + dbg->de_current_active_section = cursect; + } + dbg->de_n_debug_sect++; + + return ((Dwarf_Small *) cursect->ds_data); + } + + /* There is enough space in the current buffer */ + { + Dwarf_Small *space_for_caller = (Dwarf_Small *) + (cursect->ds_data + cursect->ds_nbytes); + + cursect->ds_nbytes += nbytes; + return space_for_caller; + } +} + + +/*------------------------------------------------------------ + Given address advance and line advance, it gives + either special opcode, or a number < 0 +------------------------------------------------------------*/ +static int +_dwarf_pro_get_opc(Dwarf_Unsigned addr_adv, int line_adv) +{ + int opc; + + addr_adv = addr_adv / MIN_INST_LENGTH; + if (line_adv == 0 && addr_adv == 0) + return OPC_INCS_ZERO; + if (line_adv >= LINE_BASE && line_adv < LINE_BASE + LINE_RANGE) { + opc = + (line_adv - LINE_BASE) + (addr_adv * LINE_RANGE) + + OPCODE_BASE; + if (opc > 255) + return OPC_OUT_OF_RANGE; + return opc; + } else + return LINE_OUT_OF_RANGE; +} + +/*----------------------------------------------------------------------- + Handles abbreviations. It takes a die, searches through + current list of abbreviations for matching one. If it + finds one, it returns a pointer to it, and if it doesnt, + it returns a new one. Upto the user of this function to + link it up to the abbreviation head. If its a new one, + abb_idx has 0. +-----------------------------------------------------------------------*/ +static Dwarf_P_Abbrev +_dwarf_pro_getabbrev(Dwarf_P_Die die, Dwarf_P_Abbrev head) +{ + Dwarf_P_Abbrev curabbrev; + Dwarf_P_Attribute curattr; + int res1; + int nattrs; + int match; + Dwarf_ufixed *forms = 0; + Dwarf_ufixed *attrs = 0; + + curabbrev = head; + while (curabbrev) { + if ((die->di_tag == curabbrev->abb_tag) && + ((die->di_child != NULL && + curabbrev->abb_children == DW_CHILDREN_yes) || + (die->di_child == NULL && + curabbrev->abb_children == DW_CHILDREN_no)) && + (die->di_n_attr == curabbrev->abb_n_attr)) { + + /* There is a chance of a match. */ + curattr = die->di_attrs; + match = 1; /* Assume match found. */ + while (match && curattr) { + res1 = _dwarf_pro_match_attr(curattr, + curabbrev, + (int) curabbrev-> + abb_n_attr); + if (res1 == 0) + match = 0; + curattr = curattr->ar_next; + } + if (match == 1) + return curabbrev; + } + curabbrev = curabbrev->abb_next; + } + + /* no match, create new abbreviation */ + if (die->di_n_attr != 0) { + forms = (Dwarf_ufixed *) + _dwarf_p_get_alloc(die->di_dbg, + sizeof(Dwarf_ufixed) * die->di_n_attr); + if (forms == NULL) + return NULL; + attrs = (Dwarf_ufixed *) + _dwarf_p_get_alloc(die->di_dbg, + sizeof(Dwarf_ufixed) * die->di_n_attr); + if (attrs == NULL) + return NULL; + } + nattrs = 0; + curattr = die->di_attrs; + while (curattr) { + attrs[nattrs] = curattr->ar_attribute; + forms[nattrs] = curattr->ar_attribute_form; + nattrs++; + curattr = curattr->ar_next; + } + + curabbrev = (Dwarf_P_Abbrev) + _dwarf_p_get_alloc(die->di_dbg, sizeof(struct Dwarf_P_Abbrev_s)); + if (curabbrev == NULL) + return NULL; + + if (die->di_child == NULL) + curabbrev->abb_children = DW_CHILDREN_no; + else + curabbrev->abb_children = DW_CHILDREN_yes; + curabbrev->abb_tag = die->di_tag; + curabbrev->abb_attrs = attrs; + curabbrev->abb_forms = forms; + curabbrev->abb_n_attr = die->di_n_attr; + curabbrev->abb_idx = 0; + curabbrev->abb_next = NULL; + + return curabbrev; +} + +/*------------------------------------------------------------------ + Tries to see if given attribute and form combination + exists in the given abbreviation +-------------------------------------------------------------------*/ +static int +_dwarf_pro_match_attr(Dwarf_P_Attribute attr, + Dwarf_P_Abbrev abbrev, int no_attr) +{ + int i; + int found = 0; + + for (i = 0; i < no_attr; i++) { + if (attr->ar_attribute == abbrev->abb_attrs[i] && + attr->ar_attribute_form == abbrev->abb_forms[i]) { + found = 1; + break; + } + } + return found; +} diff --git a/usr/src/lib/libdwarf/common/pro_section.h b/usr/src/lib/libdwarf/common/pro_section.h new file mode 100644 index 0000000000..b37ade44dc --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_section.h @@ -0,0 +1,112 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + + + +/* relocation section names */ +extern char *_dwarf_rel_section_names[]; + +/* section names */ +extern char *_dwarf_sectnames[]; + +/* struct to hold relocation entries. Its mantained as a linked + list of relocation structs, and will then be written at as a + whole into the relocation section. Whether its 32 bit or + 64 bit will be obtained from Dwarf_Debug pointer. +*/ + + + + + +/* + struct stores a chunk of data pertaining to a section +*/ +struct Dwarf_P_Section_Data_s { + int ds_elf_sect_no; /* elf section number */ + char *ds_data; /* data contained in section */ + unsigned long ds_nbytes; /* bytes of data used so far */ + unsigned long ds_orig_alloc; /* bytes allocated originally */ + Dwarf_P_Section_Data ds_next; /* next on the list */ +}; + +/* Used to allow a dummy initial struct (which we + drop before it gets used + This must not match any legitimate 'section' number. +*/ +#define MAGIC_SECT_NO -3 + +/* Size of chunk of data allocated in one alloc + Not clear if this is the best size. + Used to be just 4096 for user data, the section data struct + was a separate malloc. +*/ +#define CHUNK_SIZE (4096 - sizeof (struct Dwarf_P_Section_Data_s)) + +/* + chunk alloc routine - + if chunk->ds_data is nil, it will alloc CHUNK_SIZE bytes, + and return pointer to the beginning. If chunk is not nil, + it will see if there's enoungh space for nbytes in current + chunk, if not, add new chunk to linked list, and return + a char * pointer to it. Return null if unsuccessful. +*/ +Dwarf_Small *_dwarf_pro_buffer(Dwarf_P_Debug dbg, int sectno, + unsigned long nbytes); + +#define GET_CHUNK(dbg,sectno,ptr,nbytes,error) \ + { \ + (ptr) = _dwarf_pro_buffer((dbg),(sectno),(nbytes)); \ + if ((ptr) == NULL) { \ + DWARF_P_DBG_ERROR(dbg,DW_DLE_CHUNK_ALLOC,-1); \ + } \ + } + + + +int + _dwarf_transform_arange_to_disk(Dwarf_P_Debug dbg, + Dwarf_Error * error); + +/* These are for creating ELF section type codes. +*/ +#if defined(linux) || defined(__BEOS__) || !defined(SHT_MIPS_DWARF) +/* Intel's SoftSdv accepts only this */ +#define SECTION_TYPE SHT_PROGBITS +#else +#define SECTION_TYPE SHT_MIPS_DWARF +#endif diff --git a/usr/src/lib/libdwarf/common/pro_types.c b/usr/src/lib/libdwarf/common/pro_types.c new file mode 100644 index 0000000000..1f3f93280c --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_types.c @@ -0,0 +1,296 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include +#include +#ifdef HAVE_ELFACCESS_H +#include +#endif +#include "pro_incl.h" +#include "pro_section.h" + + +/* + This function adds another type name to the + list of type names for the given Dwarf_P_Debug. + It returns 0 on error, and 1 otherwise. +*/ +Dwarf_Unsigned +dwarf_add_typename(Dwarf_P_Debug dbg, + Dwarf_P_Die die, + char *type_name, Dwarf_Error * error) +{ + return + _dwarf_add_simple_name_entry(dbg, die, type_name, + dwarf_snk_typename, error); +} + +/* + The following is the generic 'add a simple name entry' + for any of the simple name sections. + + See enum dwarf_sn_kind in pro_opaque.h + +*/ +Dwarf_Unsigned +_dwarf_add_simple_name_entry(Dwarf_P_Debug dbg, + Dwarf_P_Die die, + char *entry_name, + enum dwarf_sn_kind entrykind, + Dwarf_Error * error) +{ + Dwarf_P_Simple_nameentry nameentry; + Dwarf_P_Simple_name_header hdr; + char *name; + int uword_size; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return (0); + } + + if (die == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL); + return (0); + } + + + nameentry = (Dwarf_P_Simple_nameentry) + _dwarf_p_get_alloc(dbg, + sizeof(struct Dwarf_P_Simple_nameentry_s)); + if (nameentry == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (0); + } + + name = _dwarf_p_get_alloc(dbg, strlen(entry_name) + 1); + if (name == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (0); + } + strcpy(name, entry_name); + + nameentry->sne_die = die; + nameentry->sne_name = name; + nameentry->sne_name_len = strlen(name); + uword_size = dbg->de_offset_size; + + hdr = &dbg->de_simple_name_headers[entrykind]; + if (hdr->sn_head == NULL) + hdr->sn_head = hdr->sn_tail = nameentry; + else { + hdr->sn_tail->sne_next = nameentry; + hdr->sn_tail = nameentry; + } + hdr->sn_count++; + hdr->sn_net_len += uword_size + nameentry->sne_name_len + 1; + + return (1); +} + + + +/* + _dwarf_transform_simplename_to_disk writes + ".rel.debug_pubnames", + ".rel.debug_funcnames", sgi extension + ".rel.debug_typenames", sgi extension + ".rel.debug_varnames", sgi extension + ".rel.debug_weaknames", sgi extension + to disk. + section_index indexes one of those sections. + entrykind is one of those 'kind's. + +*/ +int +_dwarf_transform_simplename_to_disk(Dwarf_P_Debug dbg, enum dwarf_sn_kind entrykind, int section_index, /* in + de_elf_sects + etc + */ + Dwarf_Error * error) +{ + + + /* Used to fill in 0. */ + const Dwarf_Signed big_zero = 0; + + /* Used to scan the section data buffers. */ + Dwarf_P_Section_Data debug_sect; + + Dwarf_Signed debug_info_size; + + Dwarf_P_Simple_nameentry nameentry_original; + Dwarf_P_Simple_nameentry nameentry; + Dwarf_Small *stream_bytes; + Dwarf_Small *cur_stream_bytes_ptr; + Dwarf_Unsigned stream_bytes_count; + Dwarf_Unsigned adjusted_length; /* count excluding length field + */ + + + int uword_size = dbg->de_offset_size; + int extension_size = dbg->de_64bit_extension ? 4 : 0; + + Dwarf_P_Simple_name_header hdr; + + + /* ***** BEGIN CODE ***** */ + + debug_info_size = 0; + for (debug_sect = dbg->de_debug_sects; debug_sect != NULL; + debug_sect = debug_sect->ds_next) { + /* We want the size of the .debug_info section for this CU + because the dwarf spec requires us to output it below so we + look for it specifically. */ + if (debug_sect->ds_elf_sect_no == dbg->de_elf_sects[DEBUG_INFO]) { + debug_info_size += debug_sect->ds_nbytes; + } + } + + hdr = &dbg->de_simple_name_headers[entrykind]; + /* Size of the .debug_typenames (or similar) section header. */ + stream_bytes_count = extension_size + uword_size + /* Size of + length + field. */ + sizeof(Dwarf_Half) + /* Size of version field. */ + uword_size + /* Size of .debug_info offset. */ + uword_size; /* Size of .debug_names. */ + + + + nameentry_original = hdr->sn_head; + nameentry = nameentry_original; + /* add in the content size */ + stream_bytes_count += hdr->sn_net_len; + + /* Size of the last 0 offset. */ + stream_bytes_count += uword_size; + + /* Now we know how long the entire section is */ + GET_CHUNK(dbg, dbg->de_elf_sects[section_index], + stream_bytes, (unsigned long) stream_bytes_count, error); + if (stream_bytes == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (0); + } + cur_stream_bytes_ptr = stream_bytes; + + if (extension_size) { + Dwarf_Unsigned x = DISTINGUISHED_VALUE; + + WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, + (const void *) &x, sizeof(x), extension_size); + cur_stream_bytes_ptr += extension_size; + + } + /* Write the adjusted length of .debug_*names section. */ + adjusted_length = stream_bytes_count - uword_size - extension_size; + WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, + (const void *) &adjusted_length, + sizeof(adjusted_length), uword_size); + cur_stream_bytes_ptr += uword_size; + + /* Write the version as 2 bytes. */ + { + Dwarf_Half verstamp = CURRENT_VERSION_STAMP; + + WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, + (const void *) &verstamp, + sizeof(verstamp), sizeof(Dwarf_Half)); + cur_stream_bytes_ptr += sizeof(Dwarf_Half); + } + + /* Write the offset of the compile-unit. */ + WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, + (const void *) &big_zero, + sizeof(big_zero), uword_size); + cur_stream_bytes_ptr += uword_size; + + /* now create the relocation for the compile_unit offset */ + { + int res = dbg->de_reloc_name(dbg, + section_index, + extension_size + uword_size + + sizeof(Dwarf_Half) + /* r_offset */ + , + /* debug_info section name symbol */ + dbg->de_sect_name_idx[DEBUG_INFO], + dwarf_drt_data_reloc, + uword_size); + + if (res != DW_DLV_OK) { + { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (0); + } + } + } + + /* Write the size of .debug_info section. */ + WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, + (const void *) &debug_info_size, + sizeof(debug_info_size), uword_size); + cur_stream_bytes_ptr += uword_size; + + + for (nameentry = nameentry_original; + nameentry != NULL; nameentry = nameentry->sne_next) { + + /* Copy offset of die from start of compile-unit. */ + WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, + (const void *) &nameentry->sne_die->di_offset, + sizeof(nameentry->sne_die->di_offset), + uword_size); + cur_stream_bytes_ptr += uword_size; + + /* Copy the type name. */ + strcpy((char *) cur_stream_bytes_ptr, nameentry->sne_name); + cur_stream_bytes_ptr += nameentry->sne_name_len + 1; + } + + WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, + (const void *) &big_zero, + sizeof(big_zero), uword_size); + + + + + return (int) dbg->de_n_debug_sect; +} diff --git a/usr/src/lib/libdwarf/common/pro_types.h b/usr/src/lib/libdwarf/common/pro_types.h new file mode 100644 index 0000000000..817609215b --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_types.h @@ -0,0 +1,44 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + +/* pro_types.h */ + + +int _dwarf_transform_simplename_to_disk(Dwarf_P_Debug dbg, enum dwarf_sn_kind entrykind, int section_index, /* in + de_elf_sects + etc + */ + Dwarf_Error * error); diff --git a/usr/src/lib/libdwarf/common/pro_util.h b/usr/src/lib/libdwarf/common/pro_util.h new file mode 100644 index 0000000000..56bde8bda6 --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_util.h @@ -0,0 +1,148 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + + +#define IS_64BIT(dbg) ((dbg)->de_flags & DW_DLC_SIZE_64 ? 1 : 0) +#define ISA_IA64(dbg) ((dbg)->de_flags & DW_DLC_ISA_IA64 ? 1 : 0) + +/* definition of sizes of types, given target machine */ +#define sizeof_sbyte(dbg) sizeof(Dwarf_Sbyte) +#define sizeof_ubyte(dbg) sizeof(Dwarf_Ubyte) +#define sizeof_uhalf(dbg) sizeof(Dwarf_Half) +/* certain sizes not defined here, but set in dbg record. + See pro_init.c +*/ + +/* Computes amount of padding necessary to align n to a k-boundary. */ +/* Important: Assumes n, k both GREATER than zero. */ +#define PADDING(n, k) ( (k)-1 - ((n)-1)%(k) ) + +/* The following defines are only important for users of the +** producer part of libdwarf, and such should have these +** defined correctly (as necessary) +** by the #include done in pro_incl.h +** before the #include "pro_util.h". +** For others producer macros do not matter so 0 is a usable value, and +** zero values let compilation succeed on more non-MIPS architectures. +** A better approach would be welcome. +*/ +/* R_MIPS* are #define so #ifndef works */ +/* R_IA_64* are not necessarily #define (might be enum) so #ifndef + is useless, we use the configure script generating + HAVE_R_IA_64_DIR32LSB and HAVE_R_IA64_DIR32LSB. +*/ +#ifndef R_MIPS_64 +#define R_MIPS_64 0 +#endif +#ifndef R_MIPS_32 +#define R_MIPS_32 0 +#endif +#ifndef R_MIPS_SCN_DISP +#define R_MIPS_SCN_DISP 0 +#endif + +/* R_IA_64_DIR32LSB came before the now-standard R_IA64_DIR32LSB + (etc) was defined. This now deals with either form, + preferring the new form if available. */ +#ifdef HAVE_R_IA64_DIR32LSB +#define DWARF_PRO_R_IA64_DIR32LSB R_IA64_DIR32LSB +#define DWARF_PRO_R_IA64_DIR64LSB R_IA64_DIR64LSB +#define DWARF_PRO_R_IA64_SEGREL64LSB R_IA64_SEGREL64LSB +#define DWARF_PRO_R_IA64_SEGREL32LSB R_IA64_SEGREL32LSB +#endif +#if defined(HAVE_R_IA_64_DIR32LSB) && !defined(HAVE_R_IA64_DIR32LSB) +#define DWARF_PRO_R_IA64_DIR32LSB R_IA_64_DIR32LSB +#define DWARF_PRO_R_IA64_DIR64LSB R_IA_64_DIR64LSB +#define DWARF_PRO_R_IA64_SEGREL64LSB R_IA_64_SEGREL64LSB +#define DWARF_PRO_R_IA64_SEGREL32LSB R_IA_64_SEGREL32LSB +#endif +#if !defined(HAVE_R_IA_64_DIR32LSB) && !defined(HAVE_R_IA64_DIR32LSB) +#define DWARF_PRO_R_IA64_DIR32LSB 0 +#define DWARF_PRO_R_IA64_DIR64LSB 0 +#define DWARF_PRO_R_IA64_SEGREL64LSB 0 +#define DWARF_PRO_R_IA64_SEGREL32LSB 0 +#endif + +/* + * The default "I don't know" value can't be zero. + * Because that's the sentinel value that means "no relocation". + * In order to use this library in 'symbolic relocation mode we + * don't care if this value is the right relocation value, + * only that it's non-NULL. So at the end, we define it + * to something sensible. + */ + + + +#if defined(sun) +#if defined(sparc) +#define Get_REL64_isa(dbg) (R_SPARC_UA64) +#define Get_REL32_isa(dbg) (R_SPARC_UA32) +#define Get_REL_SEGREL_isa(dbg) (R_SPARC_NONE) /* I don't know! */ +#else /* i386 */ +#define Get_REL64_isa(dbg) (R_386_32) /* Any non-zero value is ok */ +#define Get_REL32_isa(dbg) (R_386_32) +#define Get_REL_SEGREL_isa(dbg) (R_386_NONE) /* I don't know! */ +#endif /* sparc || i386 */ +#else /* !sun */ +#ifdef HAVE_SYS_IA64_ELF_H +#define Get_REL64_isa(dbg) (ISA_IA64(dbg) ? \ + DWARF_PRO_R_IA64_DIR64LSB : R_MIPS_64) +#define Get_REL32_isa(dbg) (ISA_IA64(dbg) ? \ + DWARF_PRO_R_IA64_DIR32LSB : R_MIPS_32) + + +/* ia64 uses 32bit dwarf offsets for sections */ +#define Get_REL_SEGREL_isa(dbg) (ISA_IA64(dbg) ? \ + DWARF_PRO_R_IA64_SEGREL32LSB : R_MIPS_SCN_DISP) +#else /* HAVE_SYS_IA64_ELF_H */ + +#if !defined(linux) && !defined(__BEOS__) +#define Get_REL64_isa(dbg) (R_MIPS_64) +#define Get_REL32_isa(dbg) (R_MIPS_32) +#define Get_REL_SEGREL_isa(dbg) (R_MIPS_SCN_DISP) +#else +#define Get_REL64_isa(dbg) (1) +#define Get_REL32_isa(dbg) (1) /* these are used on linux */ +#define Get_REL_SEGREL_isa(dbg) (1) /* non zero values, see comments above */ +#endif + +#endif /* HAVE_SYS_IA64_ELF_H */ +#endif /* !sun */ + + diff --git a/usr/src/lib/libdwarf/common/pro_vars.c b/usr/src/lib/libdwarf/common/pro_vars.c new file mode 100644 index 0000000000..3e75a9d9af --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_vars.c @@ -0,0 +1,62 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include +#include +#ifdef HAVE_ELFACCESS_H +#include +#endif +#include "pro_incl.h" +#include "pro_section.h" + +/* + This function adds another variable name to the + list of variable names for the given Dwarf_P_Debug. + It returns 0 on error, and 1 otherwise. +*/ +Dwarf_Unsigned +dwarf_add_varname(Dwarf_P_Debug dbg, + Dwarf_P_Die die, char *var_name, Dwarf_Error * error) +{ + return + _dwarf_add_simple_name_entry(dbg, die, var_name, + dwarf_snk_varname, error); + + +} diff --git a/usr/src/lib/libdwarf/common/pro_weaks.c b/usr/src/lib/libdwarf/common/pro_weaks.c new file mode 100644 index 0000000000..8c74bf08ca --- /dev/null +++ b/usr/src/lib/libdwarf/common/pro_weaks.c @@ -0,0 +1,61 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include +#include +#ifdef HAVE_ELFACCESS_H +#include +#endif +#include "pro_incl.h" +#include "pro_section.h" + +/* + This function adds another weak name to the + list of weak names for the given Dwarf_P_Debug. + It returns 0 on error, and 1 otherwise. +*/ +Dwarf_Unsigned +dwarf_add_weakname(Dwarf_P_Debug dbg, + Dwarf_P_Die die, + char *weak_name, Dwarf_Error * error) +{ + return + _dwarf_add_simple_name_entry(dbg, die, weak_name, + dwarf_snk_weakname, error); +} diff --git a/usr/src/lib/libdwarf/i386/Makefile b/usr/src/lib/libdwarf/i386/Makefile new file mode 100644 index 0000000000..4398507523 --- /dev/null +++ b/usr/src/lib/libdwarf/i386/Makefile @@ -0,0 +1,18 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2015 Joyent, Inc. +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) diff --git a/usr/src/lib/libdwarf/sparc/Makefile b/usr/src/lib/libdwarf/sparc/Makefile new file mode 100644 index 0000000000..4398507523 --- /dev/null +++ b/usr/src/lib/libdwarf/sparc/Makefile @@ -0,0 +1,18 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2015 Joyent, Inc. +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) diff --git a/usr/src/lib/libdwarf/sparcv9/Makefile b/usr/src/lib/libdwarf/sparcv9/Makefile new file mode 100644 index 0000000000..15a899f96f --- /dev/null +++ b/usr/src/lib/libdwarf/sparcv9/Makefile @@ -0,0 +1,19 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2015 Joyent, Inc. +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/lib/mergeq/mergeq.c b/usr/src/lib/mergeq/mergeq.c new file mode 100644 index 0000000000..25c9eb2892 --- /dev/null +++ b/usr/src/lib/mergeq/mergeq.c @@ -0,0 +1,606 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2015 Joyent, Inc. + */ + +/* + * Merge queue + * + * A multi-threaded merging queue. + * + * The general constraint of the merge queue is that if a set of items are + * inserted into the queue in the same order, then no matter how many threads + * are on the scene, we will always process the items in the same order. The + * secondary constraint is that to support environments that must be + * single-threaded, we explicitly *must not* create a thread in the case where + * the number of requested threads is just one. + * + * To that end, we've designed our queue as a circular buffer. We will grow that + * buffer to contain enough space for all the input items, after which we'll + * then treat it as a circular buffer. + * + * Items will be issued to a processing function two at a time, until there is + * only one item remaining in the queue, at which point we will be doing any + * merging work. + * + * A given queue has three different entries that we care about tracking: + * + * o mq_nproc - What is the slot of the next item to process for something + * looking for work. + * + * o mq_next - What is the slot of the next item that should be inserted into + * the queue. + * + * o mq_ncommit - What is the slot of the next item that should be committed. + * + * When a thread comes and looks for work, we pop entries off of the queue based + * on the index provided by mq_nproc. At the same time, it also gets the slot + * that it should place the result in, which is mq_next. However, because we + * have multiple threads that are operating on the system, we want to make sure + * that we push things onto the queue in order. We do that by allocating a slot + * to each task and when it completes, it waits for its slot to be ready based + * on it being the value of mq_ncommit. + * + * In addition, we keep track of the number of items in the queue as well as the + * number of active workers. There's also a generation count that is used to + * figure out when the various values might lap one another. + * + * The following images show what happens when we have a queue with six items + * and whose capacity has been shrunk to six, to better fit in the screen. + * + * + * 1) This is the initial configuration of the queue right before any processing + * is done in the context of mergeq_merge(). Every box has an initial item for + * merging in it (represented by an 'x'). Here, the mq_nproc, mq_next, and + * mq_ncommit will all point at the initial entry. However, the mq_next has + * already lapped around the array and thus has a generation count of one. + * + * The '+' characters indicate which bucket the corresponding value of mq_nproc, + * mq_ncommit, and mq_nproc. + * + * +---++---++---++---++---++---+ + * | X || X || X || X || X || X | + * +---++---++---++---++---++---+ + * mq_next (g1) + + * mq_ncommit (g0) + + * mq_nproc (g0) + + * + * 2) This shows the state right as the first thread begins to process an entry. + * Note in this example we will have two threads processing this queue. Note, + * mq_ncommit has not advanced. This is because the first thread has started + * processing entries, but it has not finished, and thus we can't commit it. + * We've incremented mq_next by one because it has gone ahead and assigned a + * single entry. We've incremented mq_nproc by two, because we have removed two + * entries and thus will have another set available. + * + * +---++---++---++---++---++---+ t1 - slot 0 + * | || || X || X || X || X | t2 - idle + * +---++---++---++---++---++---+ + * mq_next (g1) + + * mq_ncommit (g0) + + * mq_nproc (g0) + + * + * + * 3) This shows the state right after the second thread begins to process an + * entry, note that the first thread has not finished. The changes are very + * similar to the previous state, we've advanced, mq_nproc and mq_next, but not + * mq_ncommit. + * + * +---++---++---++---++---++---+ t1 - slot 0 + * | || || || || X || X | t2 - slot 1 + * +---++---++---++---++---++---+ + * mq_next (g1) + + * mq_ncommit (g0) + + * mq_nproc (g0) + + * + * 4) This shows the state after thread one has finished processing an item, but + * before it does anything else. Note that even if thread two finishes early, it + * cannot commit its item until thread one finishes. Here 'Y' refers to the + * result of merging the first two 'X's. + * + * +---++---++---++---++---++---+ t1 - idle + * | Y || || || || X || X | t2 - slot 1 + * +---++---++---++---++---++---+ + * mq_next (g1) + + * mq_ncommit (g0) + + * mq_nproc (g0) + + * + * 5) This shows the state after thread one has begun to process the next round + * and after thread two has committed, but before it begins processing the next + * item. Note that mq_nproc has wrapped around and we've bumped its generation + * counter. + * + * +---++---++---++---++---++---+ t1 - slot 2 + * | Y || Y || || || || | t2 - idle + * +---++---++---++---++---++---+ + * mq_next (g1) + + * mq_ncommit (g0) + + * mq_nproc (g0) + + * + * 6) Here, thread two, will take the next two Y values and thread 1 will commit + * its 'Y'. Thread one now must wait until thread two finishes such that it can + * do additional work. + * + * +---++---++---++---++---++---+ t1 - waiting + * | || || Y || || || | t2 - slot 3 + * +---++---++---++---++---++---+ + * mq_next (g1) + + * mq_ncommit (g0) + + * mq_nproc (g0) + + * + * 7) Here, thread two has committed and thread one is about to go process the + * final entry. The character 'Z' represents the results of merging two 'Y's. + * + * +---++---++---++---++---++---+ t1 - idle + * | || || Y || Z || || | t2 - idle + * +---++---++---++---++---++---+ + * mq_next (g1) + + * mq_ncommit (g0) + + * mq_nproc (g0) + + * + * 8) Here, thread one is processing the final item. Thread two is waiting in + * mergeq_pop() for enough items to be available. In this case, it will never + * happen; however, once all threads have finished it will break out. + * + * +---++---++---++---++---++---+ t1 - slot 4 + * | || || || || || | t2 - idle + * +---++---++---++---++---++---+ + * mq_next (g1) + + * mq_ncommit (g0) + + * mq_nproc (g0) + + * + * 9) This is the final state of the queue, it has a single '*' item which is + * the final merge result. At this point, both thread one and thread two would + * stop processing and we'll return the result to the user. + * + * +---++---++---++---++---++---+ t1 - slot 4 + * | || || || || * || | t2 - idle + * +---++---++---++---++---++---+ + * mq_next (g1) + + * mq_ncommit (g0) + + * mq_nproc (g0) + + * + * + * Note, that if at any point in time the processing function fails, then all + * the merges will quiesce and that error will be propagated back to the user. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "mergeq.h" + +struct mergeq { + mutex_t mq_lock; /* Protects items below */ + cond_t mq_cond; /* Condition variable */ + void **mq_items; /* Array of items to process */ + size_t mq_nitems; /* Number of items in the queue */ + size_t mq_cap; /* Capacity of the items */ + size_t mq_next; /* Place to put next entry */ + size_t mq_gnext; /* Generation for next */ + size_t mq_nproc; /* Index of next thing to process */ + size_t mq_gnproc; /* Generation for next proc */ + size_t mq_ncommit; /* Index of the next thing to commit */ + size_t mq_gncommit; /* Commit generation */ + uint_t mq_nactthrs; /* Number of active threads */ + uint_t mq_ndthreads; /* Desired number of threads */ + thread_t *mq_thrs; /* Actual threads */ + mergeq_proc_f *mq_func; /* Processing function */ + void *mq_arg; /* Argument for processing */ + boolean_t mq_working; /* Are we working on processing */ + boolean_t mq_iserror; /* Have we encountered an error? */ + int mq_error; +}; + +#define MERGEQ_DEFAULT_CAP 64 + +static int +mergeq_error(int err) +{ + errno = err; + return (MERGEQ_ERROR); +} + +void +mergeq_fini(mergeq_t *mqp) +{ + if (mqp == NULL) + return; + + VERIFY(mqp->mq_working != B_TRUE); + + if (mqp->mq_items != NULL) + mergeq_free(mqp->mq_items, sizeof (void *) * mqp->mq_cap); + if (mqp->mq_ndthreads > 0) { + mergeq_free(mqp->mq_thrs, sizeof (thread_t) * + mqp->mq_ndthreads); + } + VERIFY0(cond_destroy(&mqp->mq_cond)); + VERIFY0(mutex_destroy(&mqp->mq_lock)); + mergeq_free(mqp, sizeof (mergeq_t)); +} + +int +mergeq_init(mergeq_t **outp, uint_t nthrs) +{ + int ret; + mergeq_t *mqp; + + mqp = mergeq_alloc(sizeof (mergeq_t)); + if (mqp == NULL) + return (mergeq_error(ENOMEM)); + + bzero(mqp, sizeof (mergeq_t)); + mqp->mq_items = mergeq_alloc(sizeof (void *) * MERGEQ_DEFAULT_CAP); + if (mqp->mq_items == NULL) { + mergeq_free(mqp, sizeof (mergeq_t)); + return (mergeq_error(ENOMEM)); + } + bzero(mqp->mq_items, sizeof (void *) * MERGEQ_DEFAULT_CAP); + + mqp->mq_ndthreads = nthrs - 1; + if (mqp->mq_ndthreads > 0) { + mqp->mq_thrs = mergeq_alloc(sizeof (thread_t) * + mqp->mq_ndthreads); + if (mqp->mq_thrs == NULL) { + mergeq_free(mqp->mq_items, sizeof (void *) * + MERGEQ_DEFAULT_CAP); + mergeq_free(mqp, sizeof (mergeq_t)); + return (mergeq_error(ENOMEM)); + } + } + + if ((ret = mutex_init(&mqp->mq_lock, USYNC_THREAD | LOCK_ERRORCHECK, + NULL)) != 0) { + if (mqp->mq_ndthreads > 0) { + mergeq_free(mqp->mq_thrs, + sizeof (thread_t) * mqp->mq_ndthreads); + } + mergeq_free(mqp->mq_items, sizeof (void *) * + MERGEQ_DEFAULT_CAP); + mergeq_free(mqp, sizeof (mergeq_t)); + return (mergeq_error(ret)); + } + + if ((ret = cond_init(&mqp->mq_cond, USYNC_THREAD, NULL)) != 0) { + VERIFY0(mutex_destroy(&mqp->mq_lock)); + if (mqp->mq_ndthreads > 0) { + mergeq_free(mqp->mq_thrs, + sizeof (thread_t) * mqp->mq_ndthreads); + } + mergeq_free(mqp->mq_items, sizeof (void *) * + MERGEQ_DEFAULT_CAP); + mergeq_free(mqp, sizeof (mergeq_t)); + return (mergeq_error(ret)); + } + + mqp->mq_cap = MERGEQ_DEFAULT_CAP; + *outp = mqp; + return (0); +} + +static void +mergeq_reset(mergeq_t *mqp) +{ + VERIFY(MUTEX_HELD(&mqp->mq_lock)); + VERIFY(mqp->mq_working == B_FALSE); + if (mqp->mq_cap != 0) + bzero(mqp->mq_items, sizeof (void *) * mqp->mq_cap); + mqp->mq_nitems = 0; + mqp->mq_next = 0; + mqp->mq_gnext = 0; + mqp->mq_nproc = 0; + mqp->mq_gnproc = 0; + mqp->mq_ncommit = 0; + mqp->mq_gncommit = 0; + mqp->mq_func = NULL; + mqp->mq_arg = NULL; + mqp->mq_iserror = B_FALSE; + mqp->mq_error = 0; +} + +static int +mergeq_grow(mergeq_t *mqp) +{ + size_t ncap; + void **items; + + VERIFY(MUTEX_HELD(&mqp->mq_lock)); + VERIFY(mqp->mq_working == B_FALSE); + + if (SIZE_MAX - mqp->mq_cap < MERGEQ_DEFAULT_CAP) + return (ENOSPC); + + ncap = mqp->mq_cap + MERGEQ_DEFAULT_CAP; + items = mergeq_alloc(ncap * sizeof (void *)); + if (items == NULL) + return (ENOMEM); + + bzero(items, ncap * sizeof (void *)); + bcopy(mqp->mq_items, items, mqp->mq_cap * sizeof (void *)); + mergeq_free(mqp->mq_items, sizeof (mqp->mq_cap) * sizeof (void *)); + mqp->mq_items = items; + mqp->mq_cap = ncap; + return (0); +} + +int +mergeq_add(mergeq_t *mqp, void *item) +{ + VERIFY0(mutex_lock(&mqp->mq_lock)); + if (mqp->mq_working == B_TRUE) { + VERIFY0(mutex_unlock(&mqp->mq_lock)); + return (mergeq_error(ENXIO)); + } + + if (mqp->mq_next == mqp->mq_cap) { + int ret; + + if ((ret = mergeq_grow(mqp)) != 0) { + VERIFY0(mutex_unlock(&mqp->mq_lock)); + return (mergeq_error(ret)); + } + } + mqp->mq_items[mqp->mq_next] = item; + mqp->mq_next++; + mqp->mq_nitems++; + + VERIFY0(mutex_unlock(&mqp->mq_lock)); + return (0); +} + +static size_t +mergeq_slot(mergeq_t *mqp) +{ + size_t s; + + VERIFY(MUTEX_HELD(&mqp->mq_lock)); + VERIFY(mqp->mq_next < mqp->mq_cap); + + /* + * This probably should be a cv / wait thing. + */ + VERIFY(mqp->mq_nproc != (mqp->mq_next + 1) % mqp->mq_cap); + + s = mqp->mq_next; + mqp->mq_next++; + if (mqp->mq_next == mqp->mq_cap) { + mqp->mq_next %= mqp->mq_cap; + mqp->mq_gnext++; + } + + return (s); +} + +/* + * Internal function to push items onto the queue which is now a circular + * buffer. This should only be used once we begin working on the queue. + */ +static void +mergeq_push(mergeq_t *mqp, size_t slot, void *item) +{ + VERIFY(MUTEX_HELD(&mqp->mq_lock)); + VERIFY(slot < mqp->mq_cap); + + /* + * We need to verify that we don't push over something that exists. + * Based on the design, this should never happen. However, in the face + * of bugs, anything is possible. + */ + while (mqp->mq_ncommit != slot && mqp->mq_iserror == B_FALSE) + (void) cond_wait(&mqp->mq_cond, &mqp->mq_lock); + + if (mqp->mq_iserror == B_TRUE) + return; + + mqp->mq_items[slot] = item; + mqp->mq_nitems++; + mqp->mq_ncommit++; + if (mqp->mq_ncommit == mqp->mq_cap) { + mqp->mq_ncommit %= mqp->mq_cap; + mqp->mq_gncommit++; + } + (void) cond_broadcast(&mqp->mq_cond); +} + +static void * +mergeq_pop_one(mergeq_t *mqp) +{ + void *out; + + /* + * We can't move mq_nproc beyond mq_next if they're on the same + * generation. + */ + VERIFY(mqp->mq_gnext != mqp->mq_gnproc || + mqp->mq_nproc != mqp->mq_next); + + out = mqp->mq_items[mqp->mq_nproc]; + + mqp->mq_items[mqp->mq_nproc] = NULL; + mqp->mq_nproc++; + if (mqp->mq_nproc == mqp->mq_cap) { + mqp->mq_nproc %= mqp->mq_cap; + mqp->mq_gnproc++; + } + mqp->mq_nitems--; + + return (out); +} + +/* + * Pop a set of two entries from the queue. We may not have anything to process + * at the moment, eg. be waiting for someone to add something. In which case, + * we'll be sitting and waiting. + */ +static boolean_t +mergeq_pop(mergeq_t *mqp, void **first, void **second) +{ + VERIFY(MUTEX_HELD(&mqp->mq_lock)); + VERIFY(mqp->mq_nproc < mqp->mq_cap); + + while (mqp->mq_nitems < 2 && mqp->mq_nactthrs > 0 && + mqp->mq_iserror == B_FALSE) + (void) cond_wait(&mqp->mq_cond, &mqp->mq_lock); + + if (mqp->mq_iserror == B_TRUE) + return (B_FALSE); + + if (mqp->mq_nitems < 2 && mqp->mq_nactthrs == 0) { + VERIFY(mqp->mq_iserror == B_TRUE || mqp->mq_nitems == 1); + return (B_FALSE); + } + VERIFY(mqp->mq_nitems >= 2); + + *first = mergeq_pop_one(mqp); + *second = mergeq_pop_one(mqp); + + return (B_TRUE); +} + +static void * +mergeq_thr_merge(void *arg) +{ + mergeq_t *mqp = arg; + + VERIFY0(mutex_lock(&mqp->mq_lock)); + + /* + * Check to make sure creation worked and if not, fail fast. + */ + if (mqp->mq_iserror == B_TRUE) { + VERIFY0(mutex_unlock(&mqp->mq_lock)); + return (NULL); + } + + for (;;) { + void *first, *second, *out; + int ret; + size_t slot; + + if (mqp->mq_nitems == 1 && mqp->mq_nactthrs == 0) { + VERIFY0(mutex_unlock(&mqp->mq_lock)); + return (NULL); + } + + if (mergeq_pop(mqp, &first, &second) == B_FALSE) { + VERIFY0(mutex_unlock(&mqp->mq_lock)); + return (NULL); + } + slot = mergeq_slot(mqp); + + mqp->mq_nactthrs++; + + VERIFY0(mutex_unlock(&mqp->mq_lock)); + ret = mqp->mq_func(first, second, &out, mqp->mq_arg); + VERIFY0(mutex_lock(&mqp->mq_lock)); + + if (ret != 0) { + if (mqp->mq_iserror == B_FALSE) { + mqp->mq_iserror = B_TRUE; + mqp->mq_error = ret; + (void) cond_broadcast(&mqp->mq_cond); + } + mqp->mq_nactthrs--; + VERIFY0(mutex_unlock(&mqp->mq_lock)); + return (NULL); + } + mergeq_push(mqp, slot, out); + mqp->mq_nactthrs--; + } +} + +int +mergeq_merge(mergeq_t *mqp, mergeq_proc_f *func, void *arg, void **outp, + int *errp) +{ + int ret, i; + boolean_t seterr = B_FALSE; + + if (mqp == NULL || func == NULL || outp == NULL) { + return (mergeq_error(EINVAL)); + } + + VERIFY0(mutex_lock(&mqp->mq_lock)); + if (mqp->mq_working == B_TRUE) { + VERIFY0(mutex_unlock(&mqp->mq_lock)); + return (mergeq_error(EBUSY)); + } + + if (mqp->mq_nitems == 0) { + *outp = NULL; + mergeq_reset(mqp); + VERIFY0(mutex_unlock(&mqp->mq_lock)); + return (0); + } + + /* + * Now that we've finished adding items to the queue, turn it into a + * circular buffer. + */ + mqp->mq_func = func; + mqp->mq_arg = arg; + mqp->mq_nproc = 0; + mqp->mq_working = B_TRUE; + if (mqp->mq_next == mqp->mq_cap) { + mqp->mq_next %= mqp->mq_cap; + mqp->mq_gnext++; + } + mqp->mq_ncommit = mqp->mq_next; + + ret = 0; + for (i = 0; i < mqp->mq_ndthreads; i++) { + ret = thr_create(NULL, 0, mergeq_thr_merge, mqp, 0, + &mqp->mq_thrs[i]); + if (ret != 0) { + mqp->mq_iserror = B_TRUE; + break; + } + } + + VERIFY0(mutex_unlock(&mqp->mq_lock)); + if (ret == 0) + (void) mergeq_thr_merge(mqp); + + for (i = 0; i < mqp->mq_ndthreads; i++) { + VERIFY0(thr_join(mqp->mq_thrs[i], NULL, NULL)); + } + + VERIFY0(mutex_lock(&mqp->mq_lock)); + + VERIFY(mqp->mq_nactthrs == 0); + mqp->mq_working = B_FALSE; + if (ret == 0 && mqp->mq_iserror == B_FALSE) { + VERIFY(mqp->mq_nitems == 1); + *outp = mergeq_pop_one(mqp); + } else if (ret == 0 && mqp->mq_iserror == B_TRUE) { + ret = MERGEQ_UERROR; + if (errp != NULL) + *errp = mqp->mq_error; + } else { + seterr = B_TRUE; + } + + mergeq_reset(mqp); + VERIFY0(mutex_unlock(&mqp->mq_lock)); + + if (seterr == B_TRUE) + return (mergeq_error(ret)); + + return (ret); +} diff --git a/usr/src/lib/mergeq/mergeq.h b/usr/src/lib/mergeq/mergeq.h new file mode 100644 index 0000000000..4c1a21d696 --- /dev/null +++ b/usr/src/lib/mergeq/mergeq.h @@ -0,0 +1,52 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2015 Joyent, Inc. + */ + +#ifndef _MERGEQ_H +#define _MERGEQ_H + +/* + * mergeq library routines + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mergeq mergeq_t; +typedef int (mergeq_proc_f)(void *, void *, void **, void *); + +extern int mergeq_init(mergeq_t **, uint_t); +extern void mergeq_fini(mergeq_t *); + +extern int mergeq_add(mergeq_t *, void *); + +#define MERGEQ_ERROR -1 +#define MERGEQ_UERROR -2 +extern int mergeq_merge(mergeq_t *, mergeq_proc_f *, void *, void **, int *); + +/* + * Routines consumers need to implement + */ +extern void *mergeq_alloc(size_t); +extern void mergeq_free(void *, size_t); + +#ifdef __cplusplus +} +#endif + +#endif /* _MERGEQ_H */ diff --git a/usr/src/lib/mergeq/workq.c b/usr/src/lib/mergeq/workq.c new file mode 100644 index 0000000000..b9f1f2aa1c --- /dev/null +++ b/usr/src/lib/mergeq/workq.c @@ -0,0 +1,311 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2015 Joyent, Inc. + */ + +/* + * Work queue + * + * A multi-threaded work queue. + * + * The general design of this is to add a fixed number of items to the queue and + * then drain them with the specified number of threads. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "workq.h" + +struct workq { + mutex_t wq_lock; /* Protects below items */ + cond_t wq_cond; /* Condition variable */ + void **wq_items; /* Array of items to process */ + size_t wq_nitems; /* Number of items in queue */ + size_t wq_cap; /* Queue capacity */ + size_t wq_next; /* Next item to process */ + uint_t wq_ndthreads; /* Desired number of threads */ + thread_t *wq_thrs; /* Actual threads */ + workq_proc_f *wq_func; /* Processing function */ + void *wq_arg; /* Argument for processing */ + boolean_t wq_working; /* Are we actively using it? */ + boolean_t wq_iserror; /* Have we encountered an error? */ + int wq_error; /* Error value, if any */ +}; + +#define WORKQ_DEFAULT_CAP 64 + +static int +workq_error(int err) +{ + VERIFY(err != 0); + errno = err; + return (WORKQ_ERROR); +} + +void +workq_fini(workq_t *wqp) +{ + if (wqp == NULL) + return; + + VERIFY(wqp->wq_working != B_TRUE); + VERIFY0(mutex_destroy(&wqp->wq_lock)); + VERIFY0(cond_destroy(&wqp->wq_cond)); + if (wqp->wq_cap > 0) + workq_free(wqp->wq_items, sizeof (void *) * wqp->wq_cap); + if (wqp->wq_ndthreads > 0) + workq_free(wqp->wq_thrs, sizeof (thread_t) * wqp->wq_ndthreads); + workq_free(wqp, sizeof (workq_t)); +} + +int +workq_init(workq_t **outp, uint_t nthrs) +{ + int ret; + workq_t *wqp; + + wqp = workq_alloc(sizeof (workq_t)); + if (wqp == NULL) + return (workq_error(ENOMEM)); + + bzero(wqp, sizeof (workq_t)); + wqp->wq_items = workq_alloc(sizeof (void *) * WORKQ_DEFAULT_CAP); + if (wqp->wq_items == NULL) { + workq_free(wqp, sizeof (workq_t)); + return (workq_error(ENOMEM)); + } + bzero(wqp->wq_items, sizeof (void *) * WORKQ_DEFAULT_CAP); + + wqp->wq_ndthreads = nthrs - 1; + if (wqp->wq_ndthreads > 0) { + wqp->wq_thrs = workq_alloc(sizeof (thread_t) * + wqp->wq_ndthreads); + if (wqp->wq_thrs == NULL) { + workq_free(wqp->wq_items, sizeof (void *) * + WORKQ_DEFAULT_CAP); + workq_free(wqp, sizeof (workq_t)); + return (workq_error(ENOMEM)); + } + } + + if ((ret = mutex_init(&wqp->wq_lock, USYNC_THREAD | LOCK_ERRORCHECK, + NULL)) != 0) { + if (wqp->wq_ndthreads > 0) { + workq_free(wqp->wq_thrs, + sizeof (thread_t) * wqp->wq_ndthreads); + } + workq_free(wqp->wq_items, sizeof (void *) * WORKQ_DEFAULT_CAP); + workq_free(wqp, sizeof (workq_t)); + return (workq_error(ret)); + } + + if ((ret = cond_init(&wqp->wq_cond, USYNC_THREAD, NULL)) != 0) { + VERIFY0(mutex_destroy(&wqp->wq_lock)); + if (wqp->wq_ndthreads > 0) { + workq_free(wqp->wq_thrs, + sizeof (thread_t) * wqp->wq_ndthreads); + } + workq_free(wqp->wq_items, sizeof (void *) * WORKQ_DEFAULT_CAP); + workq_free(wqp, sizeof (workq_t)); + return (workq_error(ret)); + } + + wqp->wq_cap = WORKQ_DEFAULT_CAP; + *outp = wqp; + return (0); +} + +static void +workq_reset(workq_t *wqp) +{ + VERIFY(MUTEX_HELD(&wqp->wq_lock)); + VERIFY(wqp->wq_working == B_FALSE); + if (wqp->wq_cap > 0) + bzero(wqp->wq_items, sizeof (void *) * wqp->wq_cap); + wqp->wq_nitems = 0; + wqp->wq_next = 0; + wqp->wq_func = NULL; + wqp->wq_arg = NULL; + wqp->wq_iserror = B_FALSE; + wqp->wq_error = 0; +} + +static int +workq_grow(workq_t *wqp) +{ + size_t ncap; + void **items; + + VERIFY(MUTEX_HELD(&wqp->wq_lock)); + VERIFY(wqp->wq_working == B_FALSE); + + if (SIZE_MAX - wqp->wq_cap < WORKQ_DEFAULT_CAP) + return (ENOSPC); + + ncap = wqp->wq_cap + WORKQ_DEFAULT_CAP; + items = workq_alloc(ncap * sizeof (void *)); + if (items == NULL) + return (ENOMEM); + + bzero(items, ncap * sizeof (void *)); + bcopy(wqp->wq_items, items, wqp->wq_cap * sizeof (void *)); + workq_free(wqp->wq_items, sizeof (void *) * wqp->wq_cap); + wqp->wq_items = items; + wqp->wq_cap = ncap; + return (0); +} + +int +workq_add(workq_t *wqp, void *item) +{ + VERIFY0(mutex_lock(&wqp->wq_lock)); + if (wqp->wq_working == B_TRUE) { + VERIFY0(mutex_unlock(&wqp->wq_lock)); + return (workq_error(ENXIO)); + } + + if (wqp->wq_nitems == wqp->wq_cap) { + int ret; + + if ((ret = workq_grow(wqp)) != 0) { + VERIFY0(mutex_unlock(&wqp->wq_lock)); + return (workq_error(ret)); + } + } + + wqp->wq_items[wqp->wq_nitems] = item; + wqp->wq_nitems++; + + VERIFY0(mutex_unlock(&wqp->wq_lock)); + + return (0); +} + +static void * +workq_pop(workq_t *wqp) +{ + void *out; + + VERIFY(MUTEX_HELD(&wqp->wq_lock)); + VERIFY(wqp->wq_next < wqp->wq_nitems); + + out = wqp->wq_items[wqp->wq_next]; + wqp->wq_items[wqp->wq_next] = NULL; + wqp->wq_next++; + + return (out); +} + +static void * +workq_thr_work(void *arg) +{ + workq_t *wqp = arg; + + VERIFY0(mutex_lock(&wqp->wq_lock)); + VERIFY(wqp->wq_working == B_TRUE); + + for (;;) { + int ret; + void *item; + + if (wqp->wq_iserror == B_TRUE || + wqp->wq_next == wqp->wq_nitems) { + VERIFY0(mutex_unlock(&wqp->wq_lock)); + return (NULL); + } + + item = workq_pop(wqp); + + VERIFY0(mutex_unlock(&wqp->wq_lock)); + ret = wqp->wq_func(item, wqp->wq_arg); + VERIFY0(mutex_lock(&wqp->wq_lock)); + + if (ret != 0) { + if (wqp->wq_iserror == B_FALSE) { + wqp->wq_iserror = B_TRUE; + wqp->wq_error = ret; + } + VERIFY0(mutex_unlock(&wqp->wq_lock)); + return (NULL); + } + } +} + +int +workq_work(workq_t *wqp, workq_proc_f *func, void *arg, int *errp) +{ + int i, ret; + boolean_t seterr = B_FALSE; + + if (wqp == NULL || func == NULL) + return (workq_error(EINVAL)); + + VERIFY0(mutex_lock(&wqp->wq_lock)); + if (wqp->wq_working == B_TRUE) { + VERIFY0(mutex_unlock(&wqp->wq_lock)); + return (workq_error(EBUSY)); + } + + if (wqp->wq_nitems == 0) { + workq_reset(wqp); + VERIFY0(mutex_unlock(&wqp->wq_lock)); + return (0); + } + + wqp->wq_func = func; + wqp->wq_arg = arg; + wqp->wq_next = 0; + wqp->wq_working = B_TRUE; + + ret = 0; + for (i = 0; i < wqp->wq_ndthreads; i++) { + ret = thr_create(NULL, 0, workq_thr_work, wqp, 0, + &wqp->wq_thrs[i]); + if (ret != 0) { + wqp->wq_iserror = B_TRUE; + } + } + + VERIFY0(mutex_unlock(&wqp->wq_lock)); + if (ret == 0) + (void) workq_thr_work(wqp); + + for (i = 0; i < wqp->wq_ndthreads; i++) { + VERIFY0(thr_join(wqp->wq_thrs[i], NULL, NULL)); + } + + VERIFY0(mutex_lock(&wqp->wq_lock)); + wqp->wq_working = B_FALSE; + if (ret == 0 && wqp->wq_iserror == B_TRUE) { + ret = WORKQ_UERROR; + if (errp != NULL) + *errp = wqp->wq_error; + } else if (ret != 0) { + VERIFY(wqp->wq_iserror == B_FALSE); + seterr = B_TRUE; + } + + workq_reset(wqp); + VERIFY0(mutex_unlock(&wqp->wq_lock)); + + if (seterr == B_TRUE) + return (workq_error(ret)); + + return (ret); +} diff --git a/usr/src/lib/mergeq/workq.h b/usr/src/lib/mergeq/workq.h new file mode 100644 index 0000000000..20cfec4a95 --- /dev/null +++ b/usr/src/lib/mergeq/workq.h @@ -0,0 +1,52 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2015 Joyent, Inc. + */ + +#ifndef _WORKQ_H +#define _WORKQ_H + +/* + * workq library routines + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct workq workq_t; +typedef int (workq_proc_f)(void *, void *); + +extern int workq_init(workq_t **, uint_t); +extern void workq_fini(workq_t *); + +extern int workq_add(workq_t *, void *); + +#define WORKQ_ERROR (-1) +#define WORKQ_UERROR (-2) +extern int workq_work(workq_t *, workq_proc_f *, void *, int *); + +/* + * Routines consumers need to implement + */ +extern void *workq_alloc(size_t); +extern void workq_free(void *, size_t); + +#ifdef __cplusplus +} +#endif + +#endif /* _WORKQ_H */ diff --git a/usr/src/man/man1/Makefile b/usr/src/man/man1/Makefile index 8629eff5d0..5fce6a9c4f 100644 --- a/usr/src/man/man1/Makefile +++ b/usr/src/man/man1/Makefile @@ -84,6 +84,8 @@ MANFILES= acctcom.1 \ csh.1 \ csplit.1 \ ctags.1 \ + ctfdiff.1 \ + ctfdump.1 \ ctrun.1 \ ctstat.1 \ ctwatch.1 \ diff --git a/usr/src/man/man1/ctfdiff.1 b/usr/src/man/man1/ctfdiff.1 new file mode 100644 index 0000000000..145d8ff194 --- /dev/null +++ b/usr/src/man/man1/ctfdiff.1 @@ -0,0 +1,348 @@ +.\" +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.\" +.\" +.\" Copyright (c) 2015, Joyent, Inc. +.\" +.Dd Oct 4, 2014 +.Dt CTFDIFF 1 +.Os +.Sh NAME +.Nm ctfdiff +.Nd compare two CTF containers +.Sh SYNOPSIS +.Nm ctfdiff +.Op Fl afIloqt +.Op Fl F Ar function +.Op Fl O Ar object +.Op Fl p Ar parent1 +.Op Fl p Ar parent2 +.Op Fl T Ar type +.Ar file1 file2 +.Sh DESCRIPTION +The +.Nm +utility identifies differences between the contents of the +.Sy CTF +containers found in +.Em file1 +and +.Em file2 . +.Lp +.Nm +can find differences between two +.Sy CTF +container's +.Sy labels , +.Sy functions , +.Sy objects , +and +.Sy types . +When no options are specified, +.Nm +will only consider +.Sy functions , +.Sy objects, +and +.Sy types . +.Lp +Two +.Sy labels +are the same if they have the same name. +Two +.Sy objects +are the same if they have the same name and the type of the +object is the same. +Two +.Sy functions +are considered the same if they have the same name, the same return +type, the same number of arguments, and the types of their arguments are +the same. +.Lp +Two +.Sy types +are considered the same if they have the same name, they represent the same +kind of thing, and the contents of the type are the same. +This varies for each specific kind, for example, two structs are the +same if they have the same members whose types, offsets, and names are +all the same. +For more information on the specifics for what we look at +for each kind of type, and the kinds themselves, see the information we +use to encode them in +.Xr ctf 4 . +If the option +.Fl I +is specified, then the names of basic integer types are ignored. +For an example of where this makes sense, see +.Sy Example 4 . +.Lp +If the +.Sy CTF +container found inside of either +.Em file1 +or +.Em file2 +has been uniquified (see +.Xr ctf 4 +for more on uniquification), then the parent +.Sy CTF +container is also required for the diff to complete. +.Sh OPTIONS +The following options are supported: +.Bl -hang -width Ds +.It Fl a +.Bd -filled -compact +Diff +.Sy labels , +.Sy types , +.Sy objects , +and +.Sy functions . +.Ed +.It Fl f +.Bd -filled -compact +Diff +.Sy function +type argument information. +.Ed +.It Fl F Ar function +.Bd -filled -compact +When diffing +.Sy functions , +only consider the function +.Em function . +This option requires that the option +.Fl f +be specified and can be repeated multiple times. +.Ed +.It Fl I +.Bd -filled -compact +Ignore the names of integral types. +This option is useful when comparing types between two +.Sy CTF +containers that have different programming models. +In this case, when comparing integers, the name of the type is not +considered. +This means that the ILP32 type long which is a 32-bit wide signed +integer is the same as the LP64 type int which is a 32-bit wide signed +integer, even though they have different names. +.Ed +.It Fl l +.Bd -filled -compact +Diff the +.Sy labels +contained inside the +.Sy CTF +containers. +.Ed +.It Fl o +.Bd -filled -compact +Diff type information for +.Sy objects . +.Ed +.It Fl O Ar object +.Bd -filled -compact +When diffing type information for +.Sy objects , +only compare if the object is name +.Em object . +This option requires +.Fl o +to be specified and can be repeated multiple times. +.Ed +.It Fl p Ar parent1 +.Bd -filled -compact +Specifies the path of file that is the parent of the +.Sy CTF +container inside of +.Em file1 +is +.Em parent1 . +This option is required if +.Em file1 +has been uniquified. +For more information on uniquification, see +.Xr ctf 4 . +.Ed +.It Fl P Ar parent2 +.Bd -filled -compact +Specifies the path of file that is the parent of the +.Sy CTF +container inside of +.Em file2 is +.Em parent2 . +This option is required if +.Em file1 +has been uniquified. +For more information on uniquification, see +.Xr ctf 4 . +.Ed +.It Fl q +.Bd -filled -compact +Enables quiet mode. +Standard output from the diff will not be emitted. +However, diagnostics messages will still be emitted to standard error. +.Ed +.It Fl t +.Bd -filled -compact +Diff the +.Sy type +information sections in the +.Sy CTF +containers. +.Ed +.It Fl T Ar type +.Bd -filled -compact +When diffing the +.Sy types +section, only consider it if the type is name +.Em type . +Types specified here do not impact the diffing of +.Sy objects +or +.Sy functions . +Even with +.Fl T +specified, other types will be diffed as necessary for the evaluation of +the named types; however, the results of those intermediate differences +will not impact the results of +.Nm , +only named types are considered when evaluating the exit status of +.Nm . +.Ed +.El +.Sh EXIT STATUS +.Bl -inset +.It Sy 0 +.Bd -filled -offset indent -compact +Execution completed successfully, no differences were detected +between +.Em file1 +and +.Em file2 . +.Ed +.It Sy 1 +.Bd -filled -offset indent -compact +Execution completed successfully, but differences were detected +between +.Em file1 +and +.Em file2 . +.Ed +.It Sy 2 +.D1 Invalid command line options were specified. +.It Sy 3 +.D1 A fatal error occurred. +.El +.Sh EXAMPLES +.Sy Example 1 +Diffing Two +.Sy CTF +Containers +.Lp +The following example compares two +.Sy CTF +containers using the default set +of comparisons: +.Sy objects , +.Sy functions , +and +.Sy types . +.Bd -literal -offset 6n +$ ctfdiff /usr/lib/libc.so.1 /usr/lib/libdtrace.so.1 +ctf container /usr/lib/libc.so.1 type 37 is different +ctf container /usr/lib/libc.so.1 type 38 is different +ctf container /usr/lib/libc.so.1 type 39 is different +ctf container /usr/lib/libc.so.1 type 40 is different +ctf container /usr/lib/libc.so.1 type 41 is different +ctf container /usr/lib/libc.so.1 type 42 is different +ctf container /usr/lib/libc.so.1 type 43 is different +ctf container /usr/lib/libc.so.1 type 47 is different +ctf container /usr/lib/libc.so.1 type 48 is different +ctf container /usr/lib/libc.so.1 type 49 is different +\&... +.Ed +.Sy Example 2 +Diffing Types Between Two +.Sy CTF +Containers with Parents +.Lp +The following example compares two +.Sy CTF +containers +.Sy /ws/rm/zlan/proto/kernel/drv/amd64/vnd +and +.Sy /ws/rm/zlan/proto/kernel/drv/amd64/overlay +that have been uniquified against the same container +.Sy /ws/rm/zlan/proto/kernel/amd64/genunix . +.Bd -literal -offset 6n +$ ctfdiff -t -p /ws/rm/zlan/proto/kernel/amd64/genunix \\ + -P /ws/rm/zlan/proto/kernel/amd64/genunix \\ + /ws/rm/zlan/proto/kernel/drv/amd64/vnd \\ + /ws/rm/zlan/proto/kernel/drv/amd64/overlay +ctf container /ws/rm/zlan/proto/kernel/drv/amd64/vnd type 32769 is different +ctf container /ws/rm/zlan/proto/kernel/drv/amd64/vnd type 32770 is different +ctf container /ws/rm/zlan/proto/kernel/drv/amd64/vnd type 32771 is different +ctf container /ws/rm/zlan/proto/kernel/drv/amd64/vnd type 32772 is different +ctf container /ws/rm/zlan/proto/kernel/drv/amd64/vnd type 32774 is different +ctf container /ws/rm/zlan/proto/kernel/drv/amd64/vnd type 32775 is different +ctf container /ws/rm/zlan/proto/kernel/drv/amd64/vnd type 32776 is different +ctf container /ws/rm/zlan/proto/kernel/drv/amd64/vnd type 32777 is different +ctf container /ws/rm/zlan/proto/kernel/drv/amd64/vnd type 32778 is different +ctf container /ws/rm/zlan/proto/kernel/drv/amd64/vnd type 32779 is different +\&... +.Ed +.Lp +.Sy Example 3 +Diffing a Specific Function in Two +.Sy CTF +Containers +.Lp +This example shows us looking for differences in the function +.Sy libzfs_core_init +in two different version of the library +.Sy libzfs_core.so.1 . +.Bd -literal -offset 6n +$ ctfdiff -f -F libzfs_core_init /usr/lib/libzfs_core.so.1 \\ + /ws/rm/ctf/proto/usr/lib/libzfs_core.so.1 +$ echo $? +.Ed +.Lp +.Sy Example 4 +Diffing Types to Find Differences Between Different Data Models. +.Lp +This example looks for differences between structures used in an ioctl +that the kernel wants to be bitness neutral by comparing a 32-bit and +64-bit library that consumes it. +In this example, we'll use the library +.Sy libvnd.so.1 +and the types +.Sy vnd_ioc_attach_t , +.Sy vnd_ioc_link_t , +.Sy vnd_ioc_unlink_t , +.Sy vnd_ioc_buf_t , +and +.Sy vnd_ioc_info_t . +.Bd -literal -offset 6n +$ ctfdiff -t -I -T vnd_ioc_attach_t -T vnd_ioc_link_t \\ + -T vnd_ioc_unlink_t -T vnd_ioc_buf_t -T vnd_ioc_info_t \\ + i386/libvnd.so.1 amd64/libvnd.so.1 +$ echo $? +0 +.Ed +.Sh INTERFACE STABILITY +The command syntax is +.Sy Committed . +The output format is +.Sy Uncommitted . +.Sh SEE ALSO +.Xr ctfdump 1 , +.Xr diff 1 , +.Xr ctf 4 diff --git a/usr/src/man/man1/ctfdump.1 b/usr/src/man/man1/ctfdump.1 new file mode 100644 index 0000000000..b80c856eaf --- /dev/null +++ b/usr/src/man/man1/ctfdump.1 @@ -0,0 +1,446 @@ +.\" +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.\" +.\" +.\" Copyright 2018, Joyent, Inc. +.\" +.Dd Oct 2, 2018 +.Dt CTFDUMP 1 +.Os +.Sh NAME +.Nm ctfdump +.Nd dump parts of ctf data from files +.Sh SYNOPSIS +.Nm ctfdump +.Op Fl cdfhlsSt +.Op Fl p Ar parent +.Op Fl u Ar outfile +.Ar file +.Sh DESCRIPTION +The +.Nm +utility dumps and decodes the +.Sy CTF +data contained inside of +.Sy ELF +objects and raw +.Sy CTF +files. +.Lp +.Nm +can dump information about the +.Sy CTF header , +the +.Sy labels +encoded in the +.Sy CTF +container, +the types of +.Sy data objects , +the internal +.Sy string +table, +the types of the return function and the arguments for +.Sy functions , +and of course, it displays information about the +.Sy types +defined in the +.Sy CTF +container. +.Lp +.Nm +can also be used to dump out the raw +.Sy CTF +data and send it to another file. +When writing out data, it always ensures that the +.Sy CTF +data is decompressed. +In this form, the +.Sy CTF +data can be inspected using +.Nm +and other tools such as +.Xr mdb 1 . +.Lp +.Nm +in +.Fl c +mode will generate C-style output, which can be used for comparison. +Note that this output is not directly compilable. +.Lp +When no options are specified, +.Nm +displays all information, except the C-style output. +However, when the +.Fl u +option is used, then no information is displayed by default, unless +requested through the appropriate option. +.Sh OPTIONS +The following options are supported: +.Bl -hang -width Ds +.It Fl c +.Bd -filled -compact +Generate C-style output. +.Ed +.It Fl d +.Bd -filled -compact +Dump the types of symbols that correspond to objects. +.Ed +.It Fl f +.Bd -filled -compact +Dump the types of the return values and arguments of the functions. +.Ed +.It Fl h +.Bd -filled -compact +Dump the +.Sy CTF +header +.Ed +.It Fl l +.Bd -filled -compact +Dump all +.Sy CTF +labels associated with the file. +.Ed +.It Fl p Ar parent +.Bd -filled -compact +Use the type information in +.Em parent +to supplement output. +This is useful when a +.Nm CTF +container has been +.Sy uniquified +against +.Em parent . +This allows +.Nm +to use the names of types when used with +.Fl t . +.Ed +.It Fl s +.Bd -filled -compact +Dump the internal +.Sy CTF +string table +.Ed +.It Fl S +.Bd -filled -compact +Displays statistics about the +.Sy CTF +container. +.Ed +.It Fl t +.Bd -filled -compact +Dump the type information contained in the +.Sy CTF +conatiner. +.Ed +.It Fl u Ar outfile +.Bd -filled -compact +Copies the uncompressed +.Sy CTF +data to the file specified by +.Em outfile . +This can be used to make it easier to inspect the raw +.Sy CTF +data. +.Ed +.El +.Sh OUTPUT +When the +.Nm +utility is executed with its default options, it prints out a textual +representation of the +.Sy CTF +information. +Note, the output format of +.Nm +is subject to change at any time and should not be relied upon as a +stable format to be used for parsing. +.Ss CTF Header +This section describes the values in the +.Sy CTF +header. +Each line in the section describes the value of one of the +members of the header. +For more information on the meaning and interpretation of these members, +see +.Xr ctf 4 . +.Ss Label Table +This section describes information about the labels present in the +.Sy CTF +information. +Each entry in this section, if present, starts with a +number and is followed by a string. +An example entry in the label section might look like: +.Bd -literal +\&... + 2270 joyent_20151001T070028Z +\&... +.Ed +.Pp +The number, +.Em 2270 , +represents the last type that the label applies to. +The string, +.Em joyent_20151001T070028Z , +is the name of the label. +In this case, if there were no other labels, +it would indicate that the label applied to all types up to, and +including, the type number 2270. +For more information on how labels are used with +.Sy CTF +information, see the section +.Em The Label Section +in +.Xr ctf 4 . +.Ss Data Objects +This section describes the type information relating to data objects +from the symbol table. +An entry for a data object consists of four columns. +The first column is just a monotonic ID. +The second number is the type id of the object. +The third column is the name of the symbol and the fourth column is the +corresponding index from the symbol table. +.Pp +Take for example, the following couple of entries: +.Bd -literal +\&... + [0] 13 hz (48) + [1] 78 _nd (49) + [2] 1656 __pfmt_label (56) + [3] 926 _aio_hash (68) + [4] 13 _lio_free (70) + [5] 1321 u8_number_of_bytes (73) +\&... +.Ed +.Pp +Let's take the first entry in the list above. +The symbol is named +.Sy hz . +It is the first data object, as indicated by the number zero in +brackets. +It has a type id of 13 and in this case, it has a symbol table index of +48. +.Ss Functions +This section describes the type information for functions. +For each function present in the symbol table with type information, the +function's entry into the function section, the function's name, the +function's symbol table index, the function's return type, and the types +of the function's arguments are printed. +If a function is a variadic function, then the variadic argument is +printed as the string +.Sy '...' . +.Pp +Take for example, the following couple of entries: +.Bd -literal +\&... + [687] pfprint_stack (3110) returns: 11 args: (385, 115, 29, 1704, 223, 116, 2) + [688] pfprint_stddev (3111) returns: 11 args: (385, 115, 29, 1704, 223, 116, 2) + [689] pfprint_quantize (3112) returns: 11 args: (385, 115, 29, 1704, 223, 116, 2) + [690] pfprint_lquantize (3113) returns: 11 args: (385, 115, 29, 1704, 223, 116, 2) + [691] pfprint_llquantize (3114) returns: 11 args: (385, 115, 29, 1704, 223, 116, 2) +\&... +.Ed +.Pp +The first column is the function's entry number in the function type +information section. +It is enclosed in brackets. +The next column is the function's name and it is followed in parenthesis +by the its index in the +symbol table. +The following portions of this entry describe the return +type and then all of the arguments, in positional order. +.Ss Types +The types section gives information about each type in the +.Sy CTF +container. +Each entry begins with its type identifier. +The type identifier may either be in square brackets or in angle +brackets. +If the type identifier is enclosed in angle brackets, then that +represents that it is a root type or top-level type. +If it is square brackets, then it is not. +For more information on root types, see +.Xr ctf 4 . +.Pp +Next, the type will have its name and kind. +If it is an array, it will be followed with a subscript that describes +the number of entries in the array. +If it is a pointer, it will followed by the +.Sy * +symbol to indicate that it is a pointer. +If the type has the +.Sy const , +.Sy volatile , +.Sy typedef , +or +.Sy restrict +keyword applied to it, that will precede the name. +All of these reference types, including pointer, will then be followed +with an example of the type that they refer to. +.Pp +Types which are an integral or floating point value will be followed by +information about their encoding and the number of bits represented in +the type. +.Pp +Arrays will be followed by two different entries, the contents and +index. +The contents member contains the type id of the array's contents +and the index member describes a type which can represent the array's +index. +.Pp +Structures and unions will be preceded with the corresponding C keyword, +.Sy struct +or +.Sy union . +After that, the size in bytes of the structure will be indicated. +ON each subsequent line, a single member will be listed. +That line will contain the member's name, it's type identifier, and the +offset into the structure that it can be found in, in bits. +.Pp +The following show examples of type information for all of these +different types: +.Bd -literal +\&... + [5] char [12] contents: 1, index: 2 + [6] short encoding=SIGNED offset=0 bits=16 + <7> struct exit_status (4 bytes) + e_termination type=6 off=0 + e_exit type=6 off=16 + + <8> typedef time_t refers to 2 + <9> struct utmp (36 bytes) + ut_user type=3 off=0 + ut_id type=4 off=64 + ut_line type=5 off=96 + ut_pid type=6 off=192 + ut_type type=6 off=208 + ut_exit type=7 off=224 + ut_time type=8 off=256 + + <10> struct utmp * refers to 9 + [11] const struct utmp refers to 9 + [12] const struct utmp * refers to 11 + <13> int encoding=SIGNED offset=0 bits=32 + <14> typedef int32_t refers to 13 +\&... +.Ed +.Ss String Table +This section describes all of the strings that are present in the +.Sy CTF +container. +Each line represents an entry in the string table. +First the byte offset into the string table is shown in brackets and +then the +string's value is displayed. +Note the following examples: +.Bd -literal + [0] \0 + [1] joyent_20151001T070028Z + [25] char + [30] long + [35] short +.Ed +.Ss Statistics +This section contains miscellaneous statistics about the +.Sy CTF +data present. +Each line contains a single statistic. +A brief explanation of the statistic is placed first, followed by an +equals sign, and then finally the value. +.Sh EXIT STATUS +.Bl -inset +.It Sy 0 +.Dl Execution completed successfully. +.It Sy 1 +.Dl A fatal error occurred. +.It Sy 2 +.Dl Invalid command line options were specified. +.El +.Sh EXAMPLES +.Sy Example 1 +Displaying the Type Section of a Single File +.Lp +The following example dumps the type section of the file +.Sy /usr/lib/libc.so.1 . +.Bd -literal -offset 6n +$ ctfdump -t /usr/lib/libc.so.1 +- Types ---------------------------------------------------- + + <1> int encoding=SIGNED offset=0 bits=32 + <2> long encoding=SIGNED offset=0 bits=32 + <3> typedef pid_t refers to 2 + <4> unsigned int encoding=0x0 offset=0 bits=32 + <5> typedef uid_t refers to 4 + <6> typedef gid_t refers to 5 + <7> typedef uintptr_t refers to 4 +\&... +.Ed +.Lp +.Sy Example 2 +Dumping the CTF data to Another File +.Lp +The following example dumps the entire CTF data from the file +.Sy /usr/lib/libc.so.1 +and places it into the file +.Sy ctf.out . +This then shows how you can use the +.Xr mdb 1 +to inspect its contents. +.Bd -literal -offset 6n +$ ctfdump -u ctf.out /usr/lib/libc.so.1 +$ mdb ./ctf.out +> ::typedef -r /usr/lib/libctf.so.1 +> 0::print ctf_header_t +{ + cth_preamble = { + ctp_magic = 0xcff1 + ctp_version = 0x2 + ctp_flags = 0 + } + cth_parlabel = 0 + cth_parname = 0 + cth_lbloff = 0 + cth_objtoff = 0x8 + cth_funcoff = 0x5e0 + cth_typeoff = 0x7178 + cth_stroff = 0x12964 + cth_strlen = 0x7c9c +} +.Ed +.Lp +.Sy Example 3 +Dumping C-style output +.Bd -literal -offset 6n +$ ctfdump -c ./genunix | more +/* Types */ + +typedef Elf64_Addr Addr; + +typedef unsigned char Bool; + +typedef struct CK_AES_CCM_PARAMS CK_AES_CCM_PARAMS; + +typedef struct CK_AES_GCM_PARAMS CK_AES_GCM_PARAMS; +\&... +.Ed +.Sh INTERFACE STABILITY +The command syntax is +.Sy Committed . +The output format is +.Sy Uncommitted . +.Sh SEE ALSO +.Xr ctfdiff 1 , +.Xr dump 1 , +.Xr elfdump 1 , +.Xr mdb 1 , +.Xr ctf 4 diff --git a/usr/src/pkg/manifests/developer-build-onbld.mf b/usr/src/pkg/manifests/developer-build-onbld.mf index 1e45753b0d..8339396dc7 100644 --- a/usr/src/pkg/manifests/developer-build-onbld.mf +++ b/usr/src/pkg/manifests/developer-build-onbld.mf @@ -78,6 +78,7 @@ file path=opt/onbld/bin/$(ARCH)/codereview mode=0555 $(i386_ONLY)file path=opt/onbld/bin/$(ARCH)/cpcgen mode=0555 file path=opt/onbld/bin/$(ARCH)/cscope-fast mode=0555 file path=opt/onbld/bin/$(ARCH)/ctfconvert mode=0555 +file path=opt/onbld/bin/$(ARCH)/ctfdiff mode=0555 file path=opt/onbld/bin/$(ARCH)/ctfdump mode=0555 file path=opt/onbld/bin/$(ARCH)/ctfmerge mode=0555 file path=opt/onbld/bin/$(ARCH)/ctfstabs mode=0555 @@ -145,6 +146,7 @@ file path=opt/onbld/etc/exception_lists/interface_cmp file path=opt/onbld/etc/its.conf file path=opt/onbld/etc/its.reg file path=opt/onbld/lib/$(ARCH)/64/libmakestate.so.1 +file path=opt/onbld/lib/$(ARCH)/libctf.so.1 mode=0555 file path=opt/onbld/lib/$(ARCH)/libdwarf.so.1 file path=opt/onbld/lib/$(ARCH)/libmakestate.so.1 file path=opt/onbld/lib/perl/onbld_elfmod.pm @@ -395,10 +397,11 @@ legacy pkg=SUNWonbld desc="tools used to build the OS-Net consolidation" \ name="OS-Net Build Tools" version=11.11,REV=2009.10.22 license cr_Sun license=cr_Sun license lic_CDDL license=lic_CDDL -license usr/src/tools/ctf/dwarf/THIRDPARTYLICENSE \ - license=usr/src/tools/ctf/dwarf/THIRDPARTYLICENSE +license usr/src/lib/libdwarf/THIRDPARTYLICENSE \ + license=usr/src/lib/libdwarf/THIRDPARTYLICENSE link path=opt/onbld/bin/$(ARCH)/dmake target=make link path=opt/onbld/bin/git-nits target=git-pbchk +link path=opt/onbld/lib/$(ARCH)/libctf.so target=libctf.so.1 $(python2tools_ONLY)link path=opt/onbld/lib/python \ target=python$(PYTHON_VERSION) link path=opt/onbld/man/man1onbld/git-nits.1onbld target=git-pbchk.1onbld diff --git a/usr/src/pkg/manifests/developer-debug-ctf.mf b/usr/src/pkg/manifests/developer-debug-ctf.mf new file mode 100644 index 0000000000..30485f3284 --- /dev/null +++ b/usr/src/pkg/manifests/developer-debug-ctf.mf @@ -0,0 +1,32 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2016 Joyent, Inc. +# + +set name=pkg.fmri value=pkg:/developer/debug/ctf@$(PKGVERS) +set name=pkg.description value="Compact C Type Format (CTF) Tools" +set name=pkg.summary value="CTF Tools" +set name=info.classification \ + value=org.opensolaris.category.2008:Development/System +set name=variant.arch value=$(ARCH) +dir path=usr group=sys +dir path=usr/bin +dir path=usr/share +dir path=usr/share/man +dir path=usr/share/man/man1 +file path=usr/bin/ctfdiff mode=0555 +file path=usr/bin/ctfdump mode=0555 +file path=usr/share/man/man1/ctfdiff.1 +file path=usr/share/man/man1/ctfdump.1 +license cr_Sun license=cr_Sun +license lic_CDDL license=lic_CDDL diff --git a/usr/src/pkg/manifests/system-library.mf b/usr/src/pkg/manifests/system-library.mf index 941e64f74c..8e06bfc121 100644 --- a/usr/src/pkg/manifests/system-library.mf +++ b/usr/src/pkg/manifests/system-library.mf @@ -200,6 +200,7 @@ file path=lib/$(ARCH64)/libdl.so.1 file path=lib/$(ARCH64)/libdladm.so.1 file path=lib/$(ARCH64)/libdlpi.so.1 file path=lib/$(ARCH64)/libdoor.so.1 +file path=lib/$(ARCH64)/libdwarf.so.1 file path=lib/$(ARCH64)/libefi.so.1 file path=lib/$(ARCH64)/libelf.so.1 file path=lib/$(ARCH64)/libfakekernel.so.1 @@ -279,6 +280,7 @@ file path=lib/libdl.so.1 file path=lib/libdladm.so.1 file path=lib/libdlpi.so.1 file path=lib/libdoor.so.1 +file path=lib/libdwarf.so.1 file path=lib/libefi.so.1 file path=lib/libelf.so.1 file path=lib/libelfsign.so.1 @@ -587,6 +589,8 @@ license usr/src/lib/libcmd/THIRDPARTYLICENSE \ license=usr/src/lib/libcmd/THIRDPARTYLICENSE license usr/src/lib/libdll/THIRDPARTYLICENSE \ license=usr/src/lib/libdll/THIRDPARTYLICENSE +license usr/src/lib/libdwarf/THIRDPARTYLICENSE \ + license=usr/src/lib/libdwarf/THIRDPARTYLICENSE license usr/src/lib/libinetutil/common/THIRDPARTYLICENSE \ license=usr/src/lib/libinetutil/common/THIRDPARTYLICENSE license usr/src/lib/libkmf/THIRDPARTYLICENSE \ @@ -846,6 +850,8 @@ link path=usr/lib/$(ARCH64)/libdoor.so \ target=../../../lib/$(ARCH64)/libdoor.so.1 link path=usr/lib/$(ARCH64)/libdoor.so.1 \ target=../../../lib/$(ARCH64)/libdoor.so.1 +link path=usr/lib/$(ARCH64)/libdwarf.so.1 \ + target=../../../lib/$(ARCH64)/libdwarf.so.1 link path=usr/lib/$(ARCH64)/libefi.so \ target=../../../lib/$(ARCH64)/libefi.so.1 link path=usr/lib/$(ARCH64)/libefi.so.1 \ @@ -1105,6 +1111,7 @@ link path=usr/lib/libdlpi.so target=../../lib/libdlpi.so.1 link path=usr/lib/libdlpi.so.1 target=../../lib/libdlpi.so.1 link path=usr/lib/libdoor.so target=../../lib/libdoor.so.1 link path=usr/lib/libdoor.so.1 target=../../lib/libdoor.so.1 +link path=usr/lib/libdwarf.so.1 target=../../lib/libdwarf.so.1 link path=usr/lib/libefi.so target=../../lib/libefi.so.1 link path=usr/lib/libefi.so.1 target=../../lib/libefi.so.1 link path=usr/lib/libelf.so target=../../lib/libelf.so.1 diff --git a/usr/src/pkg/manifests/system-test-utiltest.mf b/usr/src/pkg/manifests/system-test-utiltest.mf index 3b4003b812..5937d96c61 100644 --- a/usr/src/pkg/manifests/system-test-utiltest.mf +++ b/usr/src/pkg/manifests/system-test-utiltest.mf @@ -36,6 +36,7 @@ dir path=opt/util-tests/tests/dis/sparc dir path=opt/util-tests/tests/files dir path=opt/util-tests/tests/libnvpair_json dir path=opt/util-tests/tests/libsff +dir path=opt/util-tests/tests/mergeq file path=opt/util-tests/README mode=0444 file path=opt/util-tests/bin/print_json mode=0555 file path=opt/util-tests/bin/utiltest mode=0555 @@ -331,6 +332,8 @@ file path=opt/util-tests/tests/libsff/libsff_opts.out mode=0444 file path=opt/util-tests/tests/libsff/libsff_strings mode=0555 file path=opt/util-tests/tests/libsff/libsff_wave mode=0555 file path=opt/util-tests/tests/libsff/libsff_wave.out mode=0444 +file path=opt/util-tests/tests/mergeq/mqt mode=0555 +file path=opt/util-tests/tests/mergeq/wqt mode=0555 file path=opt/util-tests/tests/printf_test mode=0555 file path=opt/util-tests/tests/set-linkprop mode=0555 file path=opt/util-tests/tests/xargs_test mode=0555 diff --git a/usr/src/test/util-tests/runfiles/default.run b/usr/src/test/util-tests/runfiles/default.run index 046888427f..f22bdd5094 100644 --- a/usr/src/test/util-tests/runfiles/default.run +++ b/usr/src/test/util-tests/runfiles/default.run @@ -31,6 +31,9 @@ outputdir = /var/tmp/test_results [/opt/util-tests/tests/xargs_test] +[/opt/util-tests/tests/mergeq/mqt] +[/opt/util-tests/tests/mergeq/wqt] + [/opt/util-tests/tests/libnvpair_json] tests = ['json_00_blank', 'json_01_boolean', 'json_02_numbers', 'json_03_empty_arrays', 'json_04_number_arrays', 'json_05_strings', diff --git a/usr/src/test/util-tests/tests/Makefile b/usr/src/test/util-tests/tests/Makefile index a32af36d11..35751b8e30 100644 --- a/usr/src/test/util-tests/tests/Makefile +++ b/usr/src/test/util-tests/tests/Makefile @@ -17,6 +17,6 @@ # SUBDIRS = date dis dladm iconv libnvpair_json libsff printf xargs grep_xpg4 -SUBDIRS += demangle +SUBDIRS += demangle mergeq workq include $(SRC)/test/Makefile.com diff --git a/usr/src/test/util-tests/tests/mergeq/Makefile b/usr/src/test/util-tests/tests/mergeq/Makefile new file mode 100644 index 0000000000..ef6c6abb99 --- /dev/null +++ b/usr/src/test/util-tests/tests/mergeq/Makefile @@ -0,0 +1,64 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2015 Joyent, Inc. +# + +include $(SRC)/Makefile.master + +ROOTOPTPKG = $(ROOT)/opt/util-tests +TESTDIR = $(ROOTOPTPKG)/tests/mergeq + +PROG = mqt +OBJS = mqt.o mergeq.o + +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/cmd/Makefile.ctf +include $(SRC)/test/Makefile.com + +CMDS = $(PROG:%=$(TESTDIR)/%) +$(CMDS) := FILEMODE = 0555 + +CPPFLAGS += -I$(SRC)/lib/mergeq -D_REENTRANT +LDLIBS += -lumem + +all: $(PROG) + +install: all $(CMDS) + +lint: lint_SRCS + +clobber: clean + -$(RM) $(PROG) + +clean: + -$(RM) $(OBJS) + +%.o: %.c + $(COMPILE.c) -o $@ -c $< + $(POST_PROCESS_O) + +%.o: $(SRC)/lib/mergeq/%.c + $(COMPILE.c) -o $@ -c $< + $(POST_PROCESS_O) + +$(PROG): $(OBJS) + $(LINK.c) $(OBJS) -o $@ $(LDLIBS) + $(POST_PROCESS) + +$(CMDS): $(TESTDIR) $(PROG) + +$(TESTDIR): + $(INS.dir) + +$(TESTDIR)/%: % + $(INS.file) diff --git a/usr/src/test/util-tests/tests/mergeq/mqt.c b/usr/src/test/util-tests/tests/mergeq/mqt.c new file mode 100644 index 0000000000..e61e9173d2 --- /dev/null +++ b/usr/src/test/util-tests/tests/mergeq/mqt.c @@ -0,0 +1,217 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2015 Joyent, Inc. + */ + +/* + * mergeq testing routines + */ + +#include +#include +#include +#include +#include + +const char * +_umem_debug_init() +{ + return ("default,verbose"); +} + +const char * +_umem_logging_init(void) +{ + return ("fail,contents"); +} + +void * +mergeq_alloc(size_t size) +{ + return (malloc(size)); +} + +/*ARGSUSED*/ +void +mergeq_free(void *buf, size_t size) +{ + free(buf); +} + +static int +mqt_int(void *first, void *second, void **outp, void *arg) +{ + uintptr_t a, b, c; + a = (uintptr_t)first; + b = (uintptr_t)second; + c = a + b; + *outp = (void *)c; + + return (0); +} + +static int +mqt_append(void *first, void *second, void **outp, void *arg) +{ + char *out; + + /* Yes, this leaks, don't worry about it for the test */ + if (asprintf(&out, "%s%s", first, second) != -1) { + *outp = out; + return (0); + } + return (-1); +} + +static int +mqt_fatal(void *first, void *second, void **outp, void *arg) +{ + return (-1); +} + +/* + * Test structures and cases. We really want mq_args to be a flexible array + * member, but then we cant initialize it. Thus we set a fixed size number of + * entries. + */ +typedef struct mq_test { + const char *mq_desc; /* test description/name */ + mergeq_proc_f *mq_proc; /* processing function */ + int mq_rval; /* mergeq_merge return value */ + int mq_uerr; /* user error, if any */ + boolean_t mq_strcmp; /* use strcmp rather than == */ + void *mq_result; /* expected result */ + void **mq_args; /* argument array */ +} mq_test_t; + +static void *mqt_empty_args[] = { NULL }; +static void *mqt_single_args[] = { (void *)42, NULL }; +static void *mqt_double_args[] = { (void *)42, (void *)27, NULL }; +static void *mqt_wrap_args[] = { + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, NULL +}; +static void *mqt_grow_args[] = { + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, NULL +}; +static void *mqt_order_args[] = { "l", "e", "g", "e", "n", "d", " ", "o", "f", + " ", "z", "e", "l", "d", "a", NULL }; + + +static mq_test_t mq_tests[] = { + { "empty", mqt_int, 0, 0, B_FALSE, NULL, mqt_empty_args }, + { "single", mqt_int, 0, 0, B_FALSE, (void *)42, mqt_single_args }, + { "double", mqt_int, 0, 0, B_FALSE, (void *)69, mqt_double_args }, + { "wrap", mqt_int, 0, 0, B_FALSE, (void *)64, mqt_wrap_args }, + { "grow", mqt_int, 0, 0, B_FALSE, (void *)92, mqt_grow_args }, + { "fatal", mqt_fatal, MERGEQ_UERROR, -1, B_FALSE, NULL, + mqt_double_args }, + { "order", mqt_append, 0, 0, B_TRUE, "alegend of zeld", mqt_order_args } +}; + +#define NMQ_TESTS (sizeof (mq_tests) / sizeof (mq_test_t)) + +static void +mq_test_run(mergeq_t *mqp, mq_test_t *mqt) +{ + int ret, err; + void **itemp = mqt->mq_args; + void *out; + + while (*itemp != NULL) { + if ((ret = mergeq_add(mqp, *itemp)) != 0) { + (void) fprintf(stderr, + "test %s: failed to add item: %s\n", + mqt->mq_desc, strerror(errno)); + exit(1); + } + itemp++; + } + + ret = mergeq_merge(mqp, mqt->mq_proc, NULL, &out, &err); + if (ret != mqt->mq_rval) { + (void) fprintf(stderr, "test %s: got incorrect rval. " + "Expected %d, got %d\n", mqt->mq_desc, mqt->mq_rval, ret); + exit(1); + } + + if (ret == MERGEQ_UERROR && err != mqt->mq_uerr) { + (void) fprintf(stderr, "test %s: got incorrect user error. " + "Expected %d, got %d\n", mqt->mq_desc, mqt->mq_uerr, err); + exit(1); + } + + if (ret == 0) { + if (mqt->mq_strcmp == B_TRUE && + strcmp(out, mqt->mq_result) != 0) { + (void) fprintf(stderr, "test %s: got unexpected " + "result: %s, expected %s\n", mqt->mq_desc, out, + mqt->mq_result); + exit(1); + } else if (mqt->mq_strcmp == B_FALSE && out != mqt->mq_result) { + (void) fprintf(stderr, "test %s: got unexpected " + "result: %p, expected %p\n", mqt->mq_desc, out, + mqt->mq_result); + exit(1); + } + } +} + +int +main(void) +{ + int ret, i, t; + mergeq_t *mqp; + int nthreads[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, -1 }; + + for (t = 0; nthreads[t] != -1; t++) { + printf("Beginning tests with %d threads\n", nthreads[t]); + if ((ret = mergeq_init(&mqp, nthreads[t])) != 0) { + fprintf(stderr, "failed to init mergeq: %s\n", + strerror(errno)); + return (1); + } + + for (i = 0; i < NMQ_TESTS; i++) { + mq_test_run(mqp, &mq_tests[i]); + } + + mergeq_fini(mqp); + } + + return (0); +} diff --git a/usr/src/test/util-tests/tests/workq/Makefile b/usr/src/test/util-tests/tests/workq/Makefile new file mode 100644 index 0000000000..ab5455fd86 --- /dev/null +++ b/usr/src/test/util-tests/tests/workq/Makefile @@ -0,0 +1,64 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2015 Joyent, Inc. +# + +include $(SRC)/Makefile.master + +ROOTOPTPKG = $(ROOT)/opt/util-tests +TESTDIR = $(ROOTOPTPKG)/tests/mergeq + +PROG = wqt +OBJS = wqt.o workq.o + +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/cmd/Makefile.ctf +include $(SRC)/test/Makefile.com + +CMDS = $(PROG:%=$(TESTDIR)/%) +$(CMDS) := FILEMODE = 0555 + +CPPFLAGS += -I$(SRC)/lib/mergeq -D_REENTRANT +LDLIBS += -lumem + +all: $(PROG) + +install: all $(CMDS) + +lint: lint_SRCS + +clobber: clean + -$(RM) $(PROG) + +clean: + -$(RM) $(OBJS) + +%.o: %.c + $(COMPILE.c) -o $@ -c $< + $(POST_PROCESS_O) + +%.o: $(SRC)/lib/mergeq/%.c + $(COMPILE.c) -o $@ -c $< + $(POST_PROCESS_O) + +$(PROG): $(OBJS) + $(LINK.c) $(OBJS) -o $@ $(LDLIBS) + $(POST_PROCESS) + +$(CMDS): $(TESTDIR) $(PROG) + +$(TESTDIR): + $(INS.dir) + +$(TESTDIR)/%: % + $(INS.file) diff --git a/usr/src/test/util-tests/tests/workq/wqt.c b/usr/src/test/util-tests/tests/workq/wqt.c new file mode 100644 index 0000000000..bda0b4a9e5 --- /dev/null +++ b/usr/src/test/util-tests/tests/workq/wqt.c @@ -0,0 +1,196 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2015 Joyent, Inc. + */ + +/* + * workq testing routines + * + * What we want to guarantee is that every function is executed exactly once. To + * that end we have the callback function basically increment a global in the + * test around a mutex. + */ + +#include +#include +#include +#include +#include +#include +#include + +mutex_t wqt_lock = ERRORCHECKMUTEX; +uintptr_t wqt_count; + +const char * +_umem_debug_init() +{ + return ("default,verbose"); +} + +const char * +_umem_logging_init(void) +{ + return ("fail,contents"); +} + +void * +workq_alloc(size_t size) +{ + return (malloc(size)); +} + +/*ARGSUSED*/ +void +workq_free(void *buf, size_t size) +{ + free(buf); +} + +/*ARGSUSED*/ +int +wqt_fatal(void *item, void *arg) +{ + return (-1); +} + +int +wqt_add(void *item, void *arg) +{ + uintptr_t a = (uintptr_t)item; + + mutex_enter(&wqt_lock); + wqt_count += a; + mutex_exit(&wqt_lock); + + return (0); +} + +typedef struct wq_test { + const char *wq_desc; /* test description/name */ + workq_proc_f *wq_proc; /* processing function */ + int wq_rval; /* workq_work return value */ + int wq_uerr; /* user error, if any */ + uintptr_t wq_sum; /* expected sum */ + void **wq_args; /* argument array */ +} wq_test_t; + +static void *wqt_empty_args[] = { NULL }; +static void *wqt_single_args[] = { (void *)42, NULL }; +static void *wqt_double_args[] = { (void *)42, (void *)27, NULL }; +static void *wqt_wrap_args[] = { + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, NULL +}; +static void *wqt_grow_args[] = { + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, NULL +}; + +static wq_test_t wq_tests[] = { + { "empty", wqt_add, 0, 0, NULL, wqt_empty_args }, + { "single", wqt_add, 0, 0, 42, wqt_single_args }, + { "double", wqt_add, 0, 0, 69, wqt_double_args }, + { "wrap", wqt_add, 0, 0, 64, wqt_wrap_args }, + { "grow", wqt_add, 0, 0, 92, wqt_grow_args }, + { "fatal", wqt_fatal, WORKQ_UERROR, -1, -1, wqt_double_args } +}; + +#define NWQ_TESTS (sizeof (wq_tests) / sizeof (wq_test_t)) + +static void +wq_test_run(workq_t *wqp, wq_test_t *wqt) +{ + int ret, err; + void **itemp = wqt->wq_args; + + while (*itemp != NULL) { + if ((ret = workq_add(wqp, *itemp)) != 0) { + (void) fprintf(stderr, "test %s: failed to add item: " + "%s\n", wqt->wq_desc, strerror(errno)); + exit(1); + } + itemp++; + } + + wqt_count = 0; + ret = workq_work(wqp, wqt->wq_proc, NULL, &err); + if (ret != wqt->wq_rval) { + (void) fprintf(stderr, "test %s: got incorrect rval. " + "Expected %d, got %d (%d)\n", wqt->wq_desc, wqt->wq_rval, + ret, errno); + exit(1); + } + + if (ret == WORKQ_UERROR && err != wqt->wq_uerr) { + (void) fprintf(stderr, "test %s: got incorrect user error. " + "Expected %d, got %d\n", wqt->wq_desc, wqt->wq_uerr, err); + exit(1); + } + + if (ret == 0 && wqt_count != wqt->wq_sum) { + (void) fprintf(stderr, "test %s: got unexpected " + "result: %d, expected %d\n", wqt->wq_desc, wqt_count, + wqt->wq_sum); + exit(1); + } +} + +int +main(void) +{ + int ret, i, t; + workq_t *wqp; + int nthreads[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, -1 }; + + for (t = 0; nthreads[t] != -1; t++) { + printf("Beginning tests with %d threads\n", nthreads[t]); + if ((ret = workq_init(&wqp, nthreads[t])) != 0) { + fprintf(stderr, "failed to init workq: %s\n", + strerror(errno)); + return (1); + } + + for (i = 0; i < NWQ_TESTS; i++) { + wq_test_run(wqp, &wq_tests[i]); + } + + workq_fini(wqp); + } + + + return (0); +} diff --git a/usr/src/tools/ctf/Makefile b/usr/src/tools/ctf/Makefile index dee410e27c..3ea3da7ca1 100644 --- a/usr/src/tools/ctf/Makefile +++ b/usr/src/tools/ctf/Makefile @@ -26,7 +26,9 @@ include ../Makefile.tools -SUBDIRS = cvt dump stabs ctfstrip +SUBDIRS = stabs ctfstrip libctf ctfdiff ctfdump +$(BUILD_OLD_CTF_TOOLS)SUBDIRS += cvt +$(BUILD_NEW_CTF_TOOLS)SUBDIRS += ctfmerge ctfconvert .PARALLEL: $(SUBDIRS) @@ -38,6 +40,11 @@ lint := TARGET= lint .KEEP_STATE: +ctfmerge: libctf +ctfdiff: libctf +ctfdump: libctf +ctfconvert: libctf + all clean clobber install lint: dwarf .WAIT $(SUBDIRS) dwarf $(SUBDIRS): FRC diff --git a/usr/src/tools/ctf/Makefile.ctf b/usr/src/tools/ctf/Makefile.ctf index 56e569a674..c07310eddf 100644 --- a/usr/src/tools/ctf/Makefile.ctf +++ b/usr/src/tools/ctf/Makefile.ctf @@ -29,12 +29,12 @@ include ../../../Makefile.tools # # A `make install' from the tools directory needs to work, even if the rest of # the tree hasn't been built. As such, we need to tell the ctf builds how -# to find the ctf specific headers located outside the tools subtree. We also +# to find the ctf specific headers located outside the tools subtree. We also # want to tell them how to get to the common tools source files. -# +# # For additonal details on the ordering of includes via -I, see the comments # in $(SRC)/tools/ctf/common/ctf_headers.h. -# +# HDRDIRS= \ -_gcc=-nostdinc \ @@ -42,6 +42,7 @@ HDRDIRS= \ -I$(SRC) \ -I/usr/include \ -I$(SRC)/uts/common \ + -I$(SRC)/common/ctf \ -I$(NATIVE_ADJUNCT)/include CPPFLAGS += $(HDRDIRS) diff --git a/usr/src/tools/ctf/common/ctf_headers.h b/usr/src/tools/ctf/common/ctf_headers.h index b00b8fd9a6..572fb03d4d 100644 --- a/usr/src/tools/ctf/common/ctf_headers.h +++ b/usr/src/tools/ctf/common/ctf_headers.h @@ -22,21 +22,21 @@ /* * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2018 Joyent, Inc. */ #ifndef _CTF_HEADERS_H #define _CTF_HEADERS_H -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Because the ON tools are executed on the system where they are built, * the tools need to include the headers installed on the build system, * rather than those in the ON source tree. However, some of the headers * required by the tools are part of the ON source tree, but not delivered - * as part of Solaris. These include the following: + * as part of illumos. These include the following: * * $(SRC)/lib/libctf/common/libctf.h + * $(SRC)/lib/libctf/common/libctf_impl.h * $(SRC)/uts/common/sys/ctf_api.h * $(SRC)/uts/common/sys/ctf.h * @@ -63,10 +63,22 @@ * This last -I include is needed in order to prevent a build failure * when is included via a nested #include rather than * an explicit path #include. + * + * We'll also include the local ccompile.h - older build systems often lack + * useful definitions like __unused. Finally, we'll also define ARRAY_SIZE: + * unfortunately, older systems sysmacros.h only have this defined for the + * kernel, and we can't easily pick it up otherwise. */ +#include #include #include +#include #include +#include + +#if !defined(ARRAY_SIZE) +#define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0])) +#endif #endif /* _CTF_HEADERS_H */ diff --git a/usr/src/tools/ctf/ctfconvert/Makefile b/usr/src/tools/ctf/ctfconvert/Makefile new file mode 100644 index 0000000000..07fadc5f8f --- /dev/null +++ b/usr/src/tools/ctf/ctfconvert/Makefile @@ -0,0 +1,44 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2001 by Sun Microsystems, Inc. +# All rights reserved. +# + +include ../../Makefile.tools + +SUBDIRS = $(MACH) + +all := TARGET= all +install := TARGET= install +clean := TARGET= clean +clobber := TARGET= clobber +lint := TARGET= lint + +.KEEP_STATE: + +install all clean clobber lint: $(SUBDIRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: diff --git a/usr/src/tools/ctf/ctfconvert/Makefile.com b/usr/src/tools/ctf/ctfconvert/Makefile.com new file mode 100644 index 0000000000..33268bd979 --- /dev/null +++ b/usr/src/tools/ctf/ctfconvert/Makefile.com @@ -0,0 +1,44 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +PROG = ctfconvert +SRCS = ctfconvert.c + +include ../../Makefile.ctf + +CFLAGS += $(CCVERBOSE) +LDLIBS += -lctf -lelf + +LDFLAGS = \ + -L$(ROOTONBLDLIBMACH) \ + '-R$$ORIGIN/../../lib/$(MACH)' \ + +CPPFLAGS += -include ../../common/ctf_headers.h + +OBJS = $(SRCS:%.c=%.o) + +all: $(PROG) + +$(PROG): $(OBJS) + $(LINK.c) $(OBJS) -o $@ $(LDLIBS) + $(POST_PROCESS) + +%.o: $(SRC)/cmd/ctfconvert/%.c + $(COMPILE.c) $< + +$(ROOTONBLDMACHPROG): $(PROG) + +install: $(ROOTONBLDMACHPROG) + +clean: + $(RM) $(OBJS) $(LINTFILES) + +include $(SRC)/tools/Makefile.targ diff --git a/usr/src/tools/ctf/ctfconvert/i386/Makefile b/usr/src/tools/ctf/ctfconvert/i386/Makefile new file mode 100644 index 0000000000..cd5462bee3 --- /dev/null +++ b/usr/src/tools/ctf/ctfconvert/i386/Makefile @@ -0,0 +1,27 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2001 by Sun Microsystems, Inc. +# All rights reserved. +# + +include ../Makefile.com diff --git a/usr/src/tools/ctf/ctfconvert/sparc/Makefile b/usr/src/tools/ctf/ctfconvert/sparc/Makefile new file mode 100644 index 0000000000..cd5462bee3 --- /dev/null +++ b/usr/src/tools/ctf/ctfconvert/sparc/Makefile @@ -0,0 +1,27 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2001 by Sun Microsystems, Inc. +# All rights reserved. +# + +include ../Makefile.com diff --git a/usr/src/tools/ctf/ctfdiff/Makefile b/usr/src/tools/ctf/ctfdiff/Makefile new file mode 100644 index 0000000000..07fadc5f8f --- /dev/null +++ b/usr/src/tools/ctf/ctfdiff/Makefile @@ -0,0 +1,44 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2001 by Sun Microsystems, Inc. +# All rights reserved. +# + +include ../../Makefile.tools + +SUBDIRS = $(MACH) + +all := TARGET= all +install := TARGET= install +clean := TARGET= clean +clobber := TARGET= clobber +lint := TARGET= lint + +.KEEP_STATE: + +install all clean clobber lint: $(SUBDIRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: diff --git a/usr/src/tools/ctf/ctfdiff/Makefile.com b/usr/src/tools/ctf/ctfdiff/Makefile.com new file mode 100644 index 0000000000..3c5e19fb6e --- /dev/null +++ b/usr/src/tools/ctf/ctfdiff/Makefile.com @@ -0,0 +1,44 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +PROG = ctfdiff +SRCS = ctfdiff.c + +include ../../Makefile.ctf + +CFLAGS += $(CCVERBOSE) +LDLIBS += -lctf + +LDFLAGS = \ + -L$(ROOTONBLDLIBMACH) \ + '-R$$ORIGIN/../../lib/$(MACH)' \ + +CPPFLAGS += -include ../../common/ctf_headers.h + +OBJS = $(SRCS:%.c=%.o) + +all: $(PROG) + +$(PROG): $(OBJS) + $(LINK.c) $(OBJS) -o $@ $(LDLIBS) + $(POST_PROCESS) + +%.o: $(SRC)/cmd/ctfdiff/%.c + $(COMPILE.c) $< + +$(ROOTONBLDMACHPROG): $(PROG) + +install: $(ROOTONBLDMACHPROG) + +clean: + $(RM) $(OBJS) $(LINTFILES) + +include $(SRC)/tools/Makefile.targ diff --git a/usr/src/tools/ctf/ctfdiff/i386/Makefile b/usr/src/tools/ctf/ctfdiff/i386/Makefile new file mode 100644 index 0000000000..89525f10f4 --- /dev/null +++ b/usr/src/tools/ctf/ctfdiff/i386/Makefile @@ -0,0 +1,16 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015, Joyent, Inc. +# + +include ../Makefile.com diff --git a/usr/src/tools/ctf/ctfdiff/sparc/Makefile b/usr/src/tools/ctf/ctfdiff/sparc/Makefile new file mode 100644 index 0000000000..89525f10f4 --- /dev/null +++ b/usr/src/tools/ctf/ctfdiff/sparc/Makefile @@ -0,0 +1,16 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015, Joyent, Inc. +# + +include ../Makefile.com diff --git a/usr/src/tools/ctf/ctfdump/Makefile b/usr/src/tools/ctf/ctfdump/Makefile new file mode 100644 index 0000000000..20d304216a --- /dev/null +++ b/usr/src/tools/ctf/ctfdump/Makefile @@ -0,0 +1,33 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015, Joyent, Inc. +# + +include ../../Makefile.tools + +SUBDIRS = $(MACH) + +all := TARGET= all +install := TARGET= install +clean := TARGET= clean +clobber := TARGET= clobber +lint := TARGET= lint + +.KEEP_STATE: + +install all clean clobber lint: $(SUBDIRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: diff --git a/usr/src/tools/ctf/ctfdump/Makefile.com b/usr/src/tools/ctf/ctfdump/Makefile.com new file mode 100644 index 0000000000..66e7a170c4 --- /dev/null +++ b/usr/src/tools/ctf/ctfdump/Makefile.com @@ -0,0 +1,47 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# +# Copyright 2018 Joyent, Inc. + +PROG = ctfdump +SRCS = ctfdump.c + +include ../../Makefile.ctf + +CSTD = $(CSTD_GNU99) +C99LMODE = -Xc99=%all +CFLAGS += $(CCVERBOSE) +LDLIBS += -lctf + +LDFLAGS = \ + -L$(ROOTONBLDLIBMACH) \ + '-R$$ORIGIN/../../lib/$(MACH)' \ + +CPPFLAGS += -include ../../common/ctf_headers.h + +OBJS = $(SRCS:%.c=%.o) + +all: $(PROG) + +$(PROG): $(OBJS) + $(LINK.c) $(OBJS) -o $@ $(LDLIBS) + $(POST_PROCESS) + +%.o: $(SRC)/cmd/ctfdump/%.c + $(COMPILE.c) $< + +$(ROOTONBLDMACHPROG): $(PROG) + +install: $(ROOTONBLDMACHPROG) + +clean: + $(RM) $(OBJS) $(LINTFILES) + +include $(SRC)/tools/Makefile.targ diff --git a/usr/src/tools/ctf/ctfdump/i386/Makefile b/usr/src/tools/ctf/ctfdump/i386/Makefile new file mode 100644 index 0000000000..89525f10f4 --- /dev/null +++ b/usr/src/tools/ctf/ctfdump/i386/Makefile @@ -0,0 +1,16 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015, Joyent, Inc. +# + +include ../Makefile.com diff --git a/usr/src/tools/ctf/ctfdump/sparc/Makefile b/usr/src/tools/ctf/ctfdump/sparc/Makefile new file mode 100644 index 0000000000..89525f10f4 --- /dev/null +++ b/usr/src/tools/ctf/ctfdump/sparc/Makefile @@ -0,0 +1,16 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015, Joyent, Inc. +# + +include ../Makefile.com diff --git a/usr/src/tools/ctf/ctfmerge/Makefile b/usr/src/tools/ctf/ctfmerge/Makefile new file mode 100644 index 0000000000..07fadc5f8f --- /dev/null +++ b/usr/src/tools/ctf/ctfmerge/Makefile @@ -0,0 +1,44 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2001 by Sun Microsystems, Inc. +# All rights reserved. +# + +include ../../Makefile.tools + +SUBDIRS = $(MACH) + +all := TARGET= all +install := TARGET= install +clean := TARGET= clean +clobber := TARGET= clobber +lint := TARGET= lint + +.KEEP_STATE: + +install all clean clobber lint: $(SUBDIRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: diff --git a/usr/src/tools/ctf/ctfmerge/Makefile.com b/usr/src/tools/ctf/ctfmerge/Makefile.com new file mode 100644 index 0000000000..2702fa9d13 --- /dev/null +++ b/usr/src/tools/ctf/ctfmerge/Makefile.com @@ -0,0 +1,46 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +PROG = ctfmerge +SRCS = ctfmerge.c + +include ../../Makefile.ctf + +CFLAGS += $(CCVERBOSE) +LDLIBS += -lctf -lelf + +LDFLAGS += \ + -L$(ROOTONBLDLIBMACH) \ + '-R$$ORIGIN/../../lib/$(MACH)' \ + +CPPFLAGS += -include ../../common/ctf_headers.h +CERRWARN += -_gcc=-Wno-unused-variable +CERRWARN += -_gcc=-Wno-uninitialized + +OBJS = $(SRCS:%.c=%.o) + +all: $(PROG) + +$(PROG): $(OBJS) + $(LINK.c) $(OBJS) -o $@ $(LDLIBS) + $(POST_PROCESS) + +%.o: $(SRC)/cmd/ctfmerge/%.c + $(COMPILE.c) $< + +$(ROOTONBLDMACHPROG): $(PROG) + +install: $(ROOTONBLDMACHPROG) + +clean: + $(RM) $(OBJS) $(LINTFILES) + +include $(SRC)/tools/Makefile.targ diff --git a/usr/src/tools/ctf/ctfmerge/i386/Makefile b/usr/src/tools/ctf/ctfmerge/i386/Makefile new file mode 100644 index 0000000000..cd5462bee3 --- /dev/null +++ b/usr/src/tools/ctf/ctfmerge/i386/Makefile @@ -0,0 +1,27 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2001 by Sun Microsystems, Inc. +# All rights reserved. +# + +include ../Makefile.com diff --git a/usr/src/tools/ctf/ctfmerge/sparc/Makefile b/usr/src/tools/ctf/ctfmerge/sparc/Makefile new file mode 100644 index 0000000000..cd5462bee3 --- /dev/null +++ b/usr/src/tools/ctf/ctfmerge/sparc/Makefile @@ -0,0 +1,27 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2001 by Sun Microsystems, Inc. +# All rights reserved. +# + +include ../Makefile.com diff --git a/usr/src/tools/ctf/cvt/Makefile.com b/usr/src/tools/ctf/cvt/Makefile.com index 5cdccf6dfc..052cf02cc4 100644 --- a/usr/src/tools/ctf/cvt/Makefile.com +++ b/usr/src/tools/ctf/cvt/Makefile.com @@ -32,6 +32,7 @@ PROG=ctfconvert ctfmerge GENSRCS= \ alist.c \ + altexec.c \ barrier.c \ ctf.c \ fifo.c \ @@ -71,7 +72,7 @@ DWARFLDFLAGS = \ -L$(ROOTONBLDLIBMACH) \ '-R$$ORIGIN/../../lib/$(MACH)' \ -ldwarf -DWARFCPPFLAGS = -I../../dwarf/common +DWARFCPPFLAGS = -I$(SRC)/lib/libdwarf/common LDFLAGS += -L$(NATIVE_ADJUNCT)/lib LDLIBS += -lz -lelf diff --git a/usr/src/tools/ctf/cvt/altexec.c b/usr/src/tools/ctf/cvt/altexec.c new file mode 100644 index 0000000000..c986c0731a --- /dev/null +++ b/usr/src/tools/ctf/cvt/altexec.c @@ -0,0 +1,45 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Alternate execution engine for CTF tools + */ + +#include +#include +#include + +#include "ctftools.h" + +void +ctf_altexec(const char *env, int argc, char **argv) +{ + const char *alt; + char *altexec; + + alt = getenv(env); + if (alt == NULL || *alt == '\0') + return; + + altexec = strdup(alt); + if (altexec == NULL) + terminate("failed to allocate memory for altexec\n"); + + if (unsetenv(env) != 0) + aborterr("failed to remove %s from environment", env); + + (void) execv(altexec, argv); + terminate("failed to altexec %s", altexec); +} diff --git a/usr/src/tools/ctf/cvt/ctfconvert.c b/usr/src/tools/ctf/cvt/ctfconvert.c index 36496c5e9d..af005e1934 100644 --- a/usr/src/tools/ctf/cvt/ctfconvert.c +++ b/usr/src/tools/ctf/cvt/ctfconvert.c @@ -146,6 +146,7 @@ main(int argc, char **argv) { tdata_t *filetd, *mstrtd; char *label = NULL; + char *altexec; int verbose = 0; int ignore_non_c = 0; int c; @@ -156,12 +157,21 @@ main(int argc, char **argv) progname = basename(argv[0]); + ctf_altexec("CTFCONVERT_ALTEXEC", argc, argv); + if (getenv("CTFCONVERT_DEBUG_LEVEL")) debug_level = atoi(getenv("CTFCONVERT_DEBUG_LEVEL")); if (getenv("CTFCONVERT_DEBUG_PARSE")) debug_parse = atoi(getenv("CTFCONVERT_DEBUG_PARSE")); - while ((c = getopt(argc, argv, ":l:L:o:ivs")) != EOF) { + if ((altexec = getenv("CTFCONVERT_ALTEXEC")) != NULL) { + (void) unsetenv("CTFCONVERT_ALTEXEC"); + (void) execv(altexec, argv); + (void) fprintf(stderr, "ctfconvert altexec failed to " + "run %s: %s\n", altexec, strerror(errno)); + } + + while ((c = getopt(argc, argv, ":l:L:o:givs")) != EOF) { switch (c) { case 'l': label = optarg; diff --git a/usr/src/tools/ctf/cvt/ctfmerge.c b/usr/src/tools/ctf/cvt/ctfmerge.c index 1d6d751d99..d2db789e5f 100644 --- a/usr/src/tools/ctf/cvt/ctfmerge.c +++ b/usr/src/tools/ctf/cvt/ctfmerge.c @@ -748,6 +748,8 @@ main(int argc, char **argv) progname = basename(argv[0]); + ctf_altexec("CTFMERGE_ALTEXEC", argc, argv); + if (getenv("CTFMERGE_DEBUG_LEVEL")) debug_level = atoi(getenv("CTFMERGE_DEBUG_LEVEL")); diff --git a/usr/src/tools/ctf/cvt/ctftools.h b/usr/src/tools/ctf/cvt/ctftools.h index 79746cba52..7547ce389f 100644 --- a/usr/src/tools/ctf/cvt/ctftools.h +++ b/usr/src/tools/ctf/cvt/ctftools.h @@ -442,6 +442,9 @@ void warning(char *, ...); void vadebug(int, char *, va_list); void debug(int, char *, ...); +/* altexec.c */ +void ctf_altexec(const char *, int argc, char **); + #ifdef __cplusplus } #endif diff --git a/usr/src/tools/ctf/dump/Makefile b/usr/src/tools/ctf/dump/Makefile deleted file mode 100644 index 16d8280cdd..0000000000 --- a/usr/src/tools/ctf/dump/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright (c) 2001 by Sun Microsystems, Inc. -# All rights reserved. -# -#ident "%Z%%M% %I% %E% SMI" - -include ../../Makefile.tools - -SUBDIRS = $(MACH) - -all := TARGET= all -install := TARGET= install -clean := TARGET= clean -clobber := TARGET= clobber -lint := TARGET= lint - -.KEEP_STATE: - -install all clean clobber lint: $(SUBDIRS) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: diff --git a/usr/src/tools/ctf/dump/Makefile.com b/usr/src/tools/ctf/dump/Makefile.com deleted file mode 100644 index 9877fa06a3..0000000000 --- a/usr/src/tools/ctf/dump/Makefile.com +++ /dev/null @@ -1,67 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -.KEEP_STATE: -.SUFFIXES: - -PROG = ctfdump -SRCS = dump.c utils.c symbol.c - -include ../../Makefile.ctf - -LDFLAGS += -L$(NATIVE_ADJUNCT)/lib -LDLIBS += -lelf -lz - -OBJS = $(SRCS:%.c=%.o) -LINTFILES = $(SRCS:%.c=%.ln) - -CERRWARN += -_gcc=-Wno-uninitialized - -.NO_PARALLEL: -.PARALLEL: $(OBJS) $(LINTFILES) - -all: $(PROG) - -$(PROG): $(OBJS) - $(LINK.c) $(OBJS) -o $@ $(LDLIBS) - $(POST_PROCESS) - -%.o: ../%.c - $(COMPILE.c) $< - -$(ROOTONBLDMACHPROG): $(PROG) - -install: $(ROOTONBLDMACHPROG) - -clean: - $(RM) $(OBJS) $(LINTFILES) - -%.ln: ../%.c - $(LINT.c) -c $< - -lint: $(LINTFILES) - $(LINT) $(LINTFLAGS) $(LINTFILES) $(LDLIBS) - -include ../../Makefile.ctf.targ diff --git a/usr/src/tools/ctf/dump/dump.c b/usr/src/tools/ctf/dump/dump.c deleted file mode 100644 index 5579bae596..0000000000 --- a/usr/src/tools/ctf/dump/dump.c +++ /dev/null @@ -1,1028 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "ctf_headers.h" -#include "utils.h" -#include "symbol.h" - -#define WARN(x) { warn(x); return (E_ERROR); } - -/* - * Flags that indicate what data is to be displayed. An explicit `all' value is - * provided to allow the code to distinguish between a request for everything - * (currently requested by invoking ctfdump without flags) and individual - * requests for all of the types of data (an invocation with all flags). In the - * former case, we want to be able to implicitly adjust the definition of `all' - * based on the CTF version of the file being dumped. For example, if a v2 file - * is being dumped, `all' includes F_LABEL - a request to dump the label - * section. If a v1 file is being dumped, `all' does not include F_LABEL, - * because v1 CTF doesn't support labels. We need to be able to distinguish - * between `ctfdump foo', which has an implicit request for labels if `foo' - * supports them, and `ctfdump -l foo', which has an explicity request. In the - * latter case, we exit with an error if `foo' is a v1 CTF file. - */ -static enum { - F_DATA = 0x01, /* show data object section */ - F_FUNC = 0x02, /* show function section */ - F_HDR = 0x04, /* show header */ - F_STR = 0x08, /* show string table */ - F_TYPES = 0x10, /* show type section */ - F_STATS = 0x20, /* show statistics */ - F_LABEL = 0x40, /* show label section */ - F_ALL = 0x80, /* explicit request for `all' */ - F_ALLMSK = 0xff /* show all sections and statistics */ -} flags = 0; - -static struct { - ulong_t s_ndata; /* total number of data objects */ - ulong_t s_nfunc; /* total number of functions */ - ulong_t s_nargs; /* total number of function arguments */ - ulong_t s_argmax; /* longest argument list */ - ulong_t s_ntypes; /* total number of types */ - ulong_t s_types[16]; /* number of types by kind */ - ulong_t s_nsmem; /* total number of struct members */ - ulong_t s_nsbytes; /* total size of all structs */ - ulong_t s_smmax; /* largest struct in terms of members */ - ulong_t s_sbmax; /* largest struct in terms of bytes */ - ulong_t s_numem; /* total number of union members */ - ulong_t s_nubytes; /* total size of all unions */ - ulong_t s_ummax; /* largest union in terms of members */ - ulong_t s_ubmax; /* largest union in terms of bytes */ - ulong_t s_nemem; /* total number of enum members */ - ulong_t s_emmax; /* largest enum in terms of members */ - ulong_t s_nstr; /* total number of strings */ - size_t s_strlen; /* total length of all strings */ - size_t s_strmax; /* longest string length */ -} stats; - -typedef struct ctf_data { - caddr_t cd_ctfdata; /* Pointer to the CTF data */ - size_t cd_ctflen; /* Length of CTF data */ - - /* - * cd_symdata will be non-NULL if the CTF data is being retrieved from - * an ELF file with a symbol table. cd_strdata and cd_nsyms should be - * used only if cd_symdata is non-NULL. - */ - Elf_Data *cd_symdata; /* Symbol table */ - Elf_Data *cd_strdata; /* Symbol table strings */ - int cd_nsyms; /* Number of symbol table entries */ -} ctf_data_t; - -static const char * -ref_to_str(uint_t name, const ctf_header_t *hp, const ctf_data_t *cd) -{ - size_t offset = CTF_NAME_OFFSET(name); - const char *s = cd->cd_ctfdata + hp->cth_stroff + offset; - - if (CTF_NAME_STID(name) != CTF_STRTAB_0) - return ("<< ??? - name in external strtab >>"); - - if (offset >= hp->cth_strlen) - return ("<< ??? - name exceeds strlab len >>"); - - if (hp->cth_stroff + offset >= cd->cd_ctflen) - return ("<< ??? - file truncated >>"); - - if (s[0] == '\0') - return ("(anon)"); - - return (s); -} - -static const char * -int_encoding_to_str(uint_t encoding) -{ - static char buf[32]; - - if (encoding == 0 || (encoding & ~(CTF_INT_SIGNED | CTF_INT_CHAR | - CTF_INT_BOOL | CTF_INT_VARARGS)) != 0) - (void) snprintf(buf, sizeof (buf), " 0x%x", encoding); - else { - buf[0] = '\0'; - if (encoding & CTF_INT_SIGNED) - (void) strcat(buf, " SIGNED"); - if (encoding & CTF_INT_CHAR) - (void) strcat(buf, " CHAR"); - if (encoding & CTF_INT_BOOL) - (void) strcat(buf, " BOOL"); - if (encoding & CTF_INT_VARARGS) - (void) strcat(buf, " VARARGS"); - } - - return (buf + 1); -} - -static const char * -fp_encoding_to_str(uint_t encoding) -{ - static const char *const encs[] = { - NULL, "SINGLE", "DOUBLE", "COMPLEX", "DCOMPLEX", "LDCOMPLEX", - "LDOUBLE", "INTERVAL", "DINTERVAL", "LDINTERVAL", "IMAGINARY", - "DIMAGINARY", "LDIMAGINARY" - }; - - static char buf[16]; - - if (encoding < 1 || encoding >= (sizeof (encs) / sizeof (char *))) { - (void) snprintf(buf, sizeof (buf), "%u", encoding); - return (buf); - } - - return (encs[encoding]); -} - -static void -print_line(const char *s) -{ - static const char line[] = "----------------------------------------" - "----------------------------------------"; - (void) printf("\n%s%.*s\n\n", s, (int)(78 - strlen(s)), line); -} - -static int -print_header(const ctf_header_t *hp, const ctf_data_t *cd) -{ - print_line("- CTF Header "); - - (void) printf(" cth_magic = 0x%04x\n", hp->cth_magic); - (void) printf(" cth_version = %u\n", hp->cth_version); - (void) printf(" cth_flags = 0x%02x\n", hp->cth_flags); - (void) printf(" cth_parlabel = %s\n", - ref_to_str(hp->cth_parlabel, hp, cd)); - (void) printf(" cth_parname = %s\n", - ref_to_str(hp->cth_parname, hp, cd)); - (void) printf(" cth_lbloff = %u\n", hp->cth_lbloff); - (void) printf(" cth_objtoff = %u\n", hp->cth_objtoff); - (void) printf(" cth_funcoff = %u\n", hp->cth_funcoff); - (void) printf(" cth_typeoff = %u\n", hp->cth_typeoff); - (void) printf(" cth_stroff = %u\n", hp->cth_stroff); - (void) printf(" cth_strlen = %u\n", hp->cth_strlen); - - return (E_SUCCESS); -} - -static int -print_labeltable(const ctf_header_t *hp, const ctf_data_t *cd) -{ - /* LINTED - pointer alignment */ - const ctf_lblent_t *ctl = (ctf_lblent_t *)(cd->cd_ctfdata + - hp->cth_lbloff); - ulong_t i, n = (hp->cth_objtoff - hp->cth_lbloff) / sizeof (*ctl); - - print_line("- Label Table "); - - if (hp->cth_lbloff & 3) - WARN("cth_lbloff is not aligned properly\n"); - if (hp->cth_lbloff >= cd->cd_ctflen) - WARN("file is truncated or cth_lbloff is corrupt\n"); - if (hp->cth_objtoff >= cd->cd_ctflen) - WARN("file is truncated or cth_objtoff is corrupt\n"); - if (hp->cth_lbloff > hp->cth_objtoff) - WARN("file is corrupt -- cth_lbloff > cth_objtoff\n"); - - for (i = 0; i < n; i++, ctl++) { - (void) printf(" %5u %s\n", ctl->ctl_typeidx, - ref_to_str(ctl->ctl_label, hp, cd)); - } - - return (E_SUCCESS); -} - -/* - * Given the current symbol index (-1 to start at the beginning of the symbol - * table) and the type of symbol to match, this function returns the index of - * the next matching symbol (if any), and places the name of that symbol in - * *namep. If no symbol is found, -1 is returned. - */ -static int -next_sym(const ctf_data_t *cd, const int symidx, const uchar_t matchtype, - char **namep) -{ - int i; - - for (i = symidx + 1; i < cd->cd_nsyms; i++) { - GElf_Sym sym; - char *name; - int type; - - if (gelf_getsym(cd->cd_symdata, i, &sym) == 0) - return (-1); - - name = (char *)cd->cd_strdata->d_buf + sym.st_name; - type = GELF_ST_TYPE(sym.st_info); - - /* - * Skip various types of symbol table entries. - */ - if (type != matchtype || ignore_symbol(&sym, name)) - continue; - - /* Found one */ - *namep = name; - return (i); - } - - return (-1); -} - -static int -read_data(const ctf_header_t *hp, const ctf_data_t *cd) -{ - /* LINTED - pointer alignment */ - const ushort_t *idp = (ushort_t *)(cd->cd_ctfdata + hp->cth_objtoff); - ulong_t n = (hp->cth_funcoff - hp->cth_objtoff) / sizeof (ushort_t); - - if (flags != F_STATS) - print_line("- Data Objects "); - - if (hp->cth_objtoff & 1) - WARN("cth_objtoff is not aligned properly\n"); - if (hp->cth_objtoff >= cd->cd_ctflen) - WARN("file is truncated or cth_objtoff is corrupt\n"); - if (hp->cth_funcoff >= cd->cd_ctflen) - WARN("file is truncated or cth_funcoff is corrupt\n"); - if (hp->cth_objtoff > hp->cth_funcoff) - WARN("file is corrupt -- cth_objtoff > cth_funcoff\n"); - - if (flags != F_STATS) { - int symidx, len, i; - char *name = NULL; - - for (symidx = -1, i = 0; i < n; i++) { - int nextsym; - - if (cd->cd_symdata == NULL || (nextsym = next_sym(cd, - symidx, STT_OBJECT, &name)) < 0) - name = NULL; - else - symidx = nextsym; - - len = printf(" [%u] %u", i, *idp++); - if (name != NULL) - (void) printf("%*s%s (%u)", (15 - len), "", - name, symidx); - (void) putchar('\n'); - } - } - - stats.s_ndata = n; - return (E_SUCCESS); -} - -static int -read_funcs(const ctf_header_t *hp, const ctf_data_t *cd) -{ - /* LINTED - pointer alignment */ - const ushort_t *fp = (ushort_t *)(cd->cd_ctfdata + hp->cth_funcoff); - - /* LINTED - pointer alignment */ - const ushort_t *end = (ushort_t *)(cd->cd_ctfdata + hp->cth_typeoff); - - ulong_t id; - int symidx; - - if (flags != F_STATS) - print_line("- Functions "); - - if (hp->cth_funcoff & 1) - WARN("cth_funcoff is not aligned properly\n"); - if (hp->cth_funcoff >= cd->cd_ctflen) - WARN("file is truncated or cth_funcoff is corrupt\n"); - if (hp->cth_typeoff >= cd->cd_ctflen) - WARN("file is truncated or cth_typeoff is corrupt\n"); - if (hp->cth_funcoff > hp->cth_typeoff) - WARN("file is corrupt -- cth_funcoff > cth_typeoff\n"); - - for (symidx = -1, id = 0; fp < end; id++) { - ushort_t info = *fp++; - ushort_t kind = CTF_INFO_KIND(info); - ushort_t n = CTF_INFO_VLEN(info); - ushort_t i; - int nextsym; - char *name; - - if (cd->cd_symdata == NULL || (nextsym = next_sym(cd, symidx, - STT_FUNC, &name)) < 0) - name = NULL; - else - symidx = nextsym; - - if (kind == CTF_K_UNKNOWN && n == 0) - continue; /* skip padding */ - - if (kind != CTF_K_FUNCTION) { - (void) printf(" [%lu] unexpected kind -- %u\n", - id, kind); - return (E_ERROR); - } - - if (fp + n > end) { - (void) printf(" [%lu] vlen %u extends past section " - "boundary\n", id, n); - return (E_ERROR); - } - - if (flags != F_STATS) { - (void) printf(" [%lu] FUNC ", id); - if (name != NULL) - (void) printf("(%s) ", name); - (void) printf("returns: %u args: (", *fp++); - - if (n != 0) { - (void) printf("%u", *fp++); - for (i = 1; i < n; i++) - (void) printf(", %u", *fp++); - } - - (void) printf(")\n"); - } else - fp += n + 1; /* skip to next function definition */ - - stats.s_nfunc++; - stats.s_nargs += n; - stats.s_argmax = MAX(stats.s_argmax, n); - } - - return (E_SUCCESS); -} - -static int -read_types(const ctf_header_t *hp, const ctf_data_t *cd) -{ - /* LINTED - pointer alignment */ - const ctf_type_t *tp = (ctf_type_t *)(cd->cd_ctfdata + hp->cth_typeoff); - - /* LINTED - pointer alignment */ - const ctf_type_t *end = (ctf_type_t *)(cd->cd_ctfdata + hp->cth_stroff); - - ulong_t id; - - if (flags != F_STATS) - print_line("- Types "); - - if (hp->cth_typeoff & 3) - WARN("cth_typeoff is not aligned properly\n"); - if (hp->cth_typeoff >= cd->cd_ctflen) - WARN("file is truncated or cth_typeoff is corrupt\n"); - if (hp->cth_stroff >= cd->cd_ctflen) - WARN("file is truncated or cth_stroff is corrupt\n"); - if (hp->cth_typeoff > hp->cth_stroff) - WARN("file is corrupt -- cth_typeoff > cth_stroff\n"); - - id = 1; - if (hp->cth_parlabel || hp->cth_parname) - id += 1 << CTF_PARENT_SHIFT; - - for (/* */; tp < end; id++) { - ulong_t i, n = CTF_INFO_VLEN(tp->ctt_info); - size_t size, increment, vlen = 0; - int kind = CTF_INFO_KIND(tp->ctt_info); - - union { - const void *ptr; - const ctf_array_t *ap; - const ctf_member_t *mp; - const ctf_lmember_t *lmp; - const ctf_enum_t *ep; - const ushort_t *argp; - } u; - - if (flags != F_STATS) { - (void) printf(" %c%lu%c ", - "[<"[CTF_INFO_ISROOT(tp->ctt_info)], id, - "]>"[CTF_INFO_ISROOT(tp->ctt_info)]); - } - - if (tp->ctt_size == CTF_LSIZE_SENT) { - increment = sizeof (ctf_type_t); - size = (size_t)CTF_TYPE_LSIZE(tp); - } else { - increment = sizeof (ctf_stype_t); - size = tp->ctt_size; - } - u.ptr = (caddr_t)tp + increment; - - switch (kind) { - case CTF_K_INTEGER: - if (flags != F_STATS) { - uint_t encoding = *((const uint_t *)u.ptr); - - (void) printf("INTEGER %s encoding=%s offset=%u" - " bits=%u", ref_to_str(tp->ctt_name, hp, - cd), int_encoding_to_str( - CTF_INT_ENCODING(encoding)), - CTF_INT_OFFSET(encoding), - CTF_INT_BITS(encoding)); - } - vlen = sizeof (uint_t); - break; - - case CTF_K_FLOAT: - if (flags != F_STATS) { - uint_t encoding = *((const uint_t *)u.ptr); - - (void) printf("FLOAT %s encoding=%s offset=%u " - "bits=%u", ref_to_str(tp->ctt_name, hp, - cd), fp_encoding_to_str( - CTF_FP_ENCODING(encoding)), - CTF_FP_OFFSET(encoding), - CTF_FP_BITS(encoding)); - } - vlen = sizeof (uint_t); - break; - - case CTF_K_POINTER: - if (flags != F_STATS) { - (void) printf("POINTER %s refers to %u", - ref_to_str(tp->ctt_name, hp, cd), - tp->ctt_type); - } - break; - - case CTF_K_ARRAY: - if (flags != F_STATS) { - (void) printf("ARRAY %s content: %u index: %u " - "nelems: %u\n", ref_to_str(tp->ctt_name, - hp, cd), u.ap->cta_contents, - u.ap->cta_index, u.ap->cta_nelems); - } - vlen = sizeof (ctf_array_t); - break; - - case CTF_K_FUNCTION: - if (flags != F_STATS) { - (void) printf("FUNCTION %s returns: %u args: (", - ref_to_str(tp->ctt_name, hp, cd), - tp->ctt_type); - - if (n != 0) { - (void) printf("%u", *u.argp++); - for (i = 1; i < n; i++, u.argp++) - (void) printf(", %u", *u.argp); - } - - (void) printf(")"); - } - - vlen = sizeof (ushort_t) * (n + (n & 1)); - break; - - case CTF_K_STRUCT: - case CTF_K_UNION: - if (kind == CTF_K_STRUCT) { - stats.s_nsmem += n; - stats.s_smmax = MAX(stats.s_smmax, n); - stats.s_nsbytes += size; - stats.s_sbmax = MAX(stats.s_sbmax, size); - - if (flags != F_STATS) - (void) printf("STRUCT"); - } else { - stats.s_numem += n; - stats.s_ummax = MAX(stats.s_ummax, n); - stats.s_nubytes += size; - stats.s_ubmax = MAX(stats.s_ubmax, size); - - if (flags != F_STATS) - (void) printf("UNION"); - } - - if (flags != F_STATS) { - (void) printf(" %s (%d bytes)\n", - ref_to_str(tp->ctt_name, hp, cd), size); - - if (size >= CTF_LSTRUCT_THRESH) { - for (i = 0; i < n; i++, u.lmp++) { - (void) printf( - "\t%s type=%u off=%llu\n", - ref_to_str(u.lmp->ctlm_name, - hp, cd), u.lmp->ctlm_type, - CTF_LMEM_OFFSET(u.lmp)); - } - } else { - for (i = 0; i < n; i++, u.mp++) { - (void) printf( - "\t%s type=%u off=%u\n", - ref_to_str(u.mp->ctm_name, - hp, cd), u.mp->ctm_type, - u.mp->ctm_offset); - } - } - } - - vlen = n * (size >= CTF_LSTRUCT_THRESH ? - sizeof (ctf_lmember_t) : sizeof (ctf_member_t)); - break; - - case CTF_K_ENUM: - if (flags != F_STATS) { - (void) printf("ENUM %s\n", - ref_to_str(tp->ctt_name, hp, cd)); - - for (i = 0; i < n; i++, u.ep++) { - (void) printf("\t%s = %d\n", - ref_to_str(u.ep->cte_name, hp, cd), - u.ep->cte_value); - } - } - - stats.s_nemem += n; - stats.s_emmax = MAX(stats.s_emmax, n); - - vlen = sizeof (ctf_enum_t) * n; - break; - - case CTF_K_FORWARD: - if (flags != F_STATS) { - (void) printf("FORWARD %s", - ref_to_str(tp->ctt_name, hp, cd)); - } - break; - - case CTF_K_TYPEDEF: - if (flags != F_STATS) { - (void) printf("TYPEDEF %s refers to %u", - ref_to_str(tp->ctt_name, hp, cd), - tp->ctt_type); - } - break; - - case CTF_K_VOLATILE: - if (flags != F_STATS) { - (void) printf("VOLATILE %s refers to %u", - ref_to_str(tp->ctt_name, hp, cd), - tp->ctt_type); - } - break; - - case CTF_K_CONST: - if (flags != F_STATS) { - (void) printf("CONST %s refers to %u", - ref_to_str(tp->ctt_name, hp, cd), - tp->ctt_type); - } - break; - - case CTF_K_RESTRICT: - if (flags != F_STATS) { - (void) printf("RESTRICT %s refers to %u", - ref_to_str(tp->ctt_name, hp, cd), - tp->ctt_type); - } - break; - - case CTF_K_UNKNOWN: - break; /* hole in type id space */ - - default: - (void) printf("unexpected kind %u\n", kind); - return (E_ERROR); - } - - if (flags != F_STATS) - (void) printf("\n"); - - stats.s_ntypes++; - stats.s_types[kind]++; - - tp = (ctf_type_t *)((uintptr_t)tp + increment + vlen); - } - - return (E_SUCCESS); -} - -static int -read_strtab(const ctf_header_t *hp, const ctf_data_t *cd) -{ - size_t n, off, len = hp->cth_strlen; - const char *s = cd->cd_ctfdata + hp->cth_stroff; - - if (flags != F_STATS) - print_line("- String Table "); - - if (hp->cth_stroff >= cd->cd_ctflen) - WARN("file is truncated or cth_stroff is corrupt\n"); - if (hp->cth_stroff + hp->cth_strlen > cd->cd_ctflen) - WARN("file is truncated or cth_strlen is corrupt\n"); - - for (off = 0; len != 0; off += n) { - if (flags != F_STATS) { - (void) printf(" [%lu] %s\n", (ulong_t)off, - s[0] == '\0' ? "\\0" : s); - } - n = strlen(s) + 1; - len -= n; - s += n; - - stats.s_nstr++; - stats.s_strlen += n; - stats.s_strmax = MAX(stats.s_strmax, n); - } - - return (E_SUCCESS); -} - -static void -long_stat(const char *name, ulong_t value) -{ - (void) printf(" %-36s= %lu\n", name, value); -} - -static void -fp_stat(const char *name, float value) -{ - (void) printf(" %-36s= %.2f\n", name, value); -} - -static int -print_stats(void) -{ - print_line("- CTF Statistics "); - - long_stat("total number of data objects", stats.s_ndata); - (void) printf("\n"); - - long_stat("total number of functions", stats.s_nfunc); - long_stat("total number of function arguments", stats.s_nargs); - long_stat("maximum argument list length", stats.s_argmax); - - if (stats.s_nfunc != 0) { - fp_stat("average argument list length", - (float)stats.s_nargs / (float)stats.s_nfunc); - } - - (void) printf("\n"); - - long_stat("total number of types", stats.s_ntypes); - long_stat("total number of integers", stats.s_types[CTF_K_INTEGER]); - long_stat("total number of floats", stats.s_types[CTF_K_FLOAT]); - long_stat("total number of pointers", stats.s_types[CTF_K_POINTER]); - long_stat("total number of arrays", stats.s_types[CTF_K_ARRAY]); - long_stat("total number of func types", stats.s_types[CTF_K_FUNCTION]); - long_stat("total number of structs", stats.s_types[CTF_K_STRUCT]); - long_stat("total number of unions", stats.s_types[CTF_K_UNION]); - long_stat("total number of enums", stats.s_types[CTF_K_ENUM]); - long_stat("total number of forward tags", stats.s_types[CTF_K_FORWARD]); - long_stat("total number of typedefs", stats.s_types[CTF_K_TYPEDEF]); - long_stat("total number of volatile types", - stats.s_types[CTF_K_VOLATILE]); - long_stat("total number of const types", stats.s_types[CTF_K_CONST]); - long_stat("total number of restrict types", - stats.s_types[CTF_K_RESTRICT]); - long_stat("total number of unknowns (holes)", - stats.s_types[CTF_K_UNKNOWN]); - - (void) printf("\n"); - - long_stat("total number of struct members", stats.s_nsmem); - long_stat("maximum number of struct members", stats.s_smmax); - long_stat("total size of all structs", stats.s_nsbytes); - long_stat("maximum size of a struct", stats.s_sbmax); - - if (stats.s_types[CTF_K_STRUCT] != 0) { - fp_stat("average number of struct members", - (float)stats.s_nsmem / (float)stats.s_types[CTF_K_STRUCT]); - fp_stat("average size of a struct", (float)stats.s_nsbytes / - (float)stats.s_types[CTF_K_STRUCT]); - } - - (void) printf("\n"); - - long_stat("total number of union members", stats.s_numem); - long_stat("maximum number of union members", stats.s_ummax); - long_stat("total size of all unions", stats.s_nubytes); - long_stat("maximum size of a union", stats.s_ubmax); - - if (stats.s_types[CTF_K_UNION] != 0) { - fp_stat("average number of union members", - (float)stats.s_numem / (float)stats.s_types[CTF_K_UNION]); - fp_stat("average size of a union", (float)stats.s_nubytes / - (float)stats.s_types[CTF_K_UNION]); - } - - (void) printf("\n"); - - long_stat("total number of enum members", stats.s_nemem); - long_stat("maximum number of enum members", stats.s_emmax); - - if (stats.s_types[CTF_K_ENUM] != 0) { - fp_stat("average number of enum members", - (float)stats.s_nemem / (float)stats.s_types[CTF_K_ENUM]); - } - - (void) printf("\n"); - - long_stat("total number of unique strings", stats.s_nstr); - long_stat("bytes of string data", stats.s_strlen); - long_stat("maximum string length", stats.s_strmax); - - if (stats.s_nstr != 0) { - fp_stat("average string length", - (float)stats.s_strlen / (float)stats.s_nstr); - } - - (void) printf("\n"); - return (E_SUCCESS); -} - -static int -print_usage(FILE *fp, int verbose) -{ - (void) fprintf(fp, "Usage: %s [-dfhlsSt] [-u file] file\n", getpname()); - - if (verbose) { - (void) fprintf(fp, - "\t-d dump data object section\n" - "\t-f dump function section\n" - "\t-h dump file header\n" - "\t-l dump label table\n" - "\t-s dump string table\n" - "\t-S dump statistics\n" - "\t-t dump type section\n" - "\t-u save uncompressed CTF to a file\n"); - } - - return (E_USAGE); -} - -static Elf_Scn * -findelfscn(Elf *elf, GElf_Ehdr *ehdr, char *secname) -{ - GElf_Shdr shdr; - Elf_Scn *scn; - char *name; - - for (scn = NULL; (scn = elf_nextscn(elf, scn)) != NULL; ) { - if (gelf_getshdr(scn, &shdr) != NULL && (name = - elf_strptr(elf, ehdr->e_shstrndx, shdr.sh_name)) != NULL && - strcmp(name, secname) == 0) - return (scn); - } - - return (NULL); -} - -int -main(int argc, char *argv[]) -{ - const char *filename = NULL; - const char *ufile = NULL; - int error = 0; - int c, fd, ufd; - - ctf_data_t cd; - const ctf_preamble_t *pp; - ctf_header_t *hp; - Elf *elf; - GElf_Ehdr ehdr; - - (void) elf_version(EV_CURRENT); - - for (opterr = 0; optind < argc; optind++) { - while ((c = getopt(argc, argv, "dfhlsStu:")) != (int)EOF) { - switch (c) { - case 'd': - flags |= F_DATA; - break; - case 'f': - flags |= F_FUNC; - break; - case 'h': - flags |= F_HDR; - break; - case 'l': - flags |= F_LABEL; - break; - case 's': - flags |= F_STR; - break; - case 'S': - flags |= F_STATS; - break; - case 't': - flags |= F_TYPES; - break; - case 'u': - ufile = optarg; - break; - default: - if (optopt == '?') - return (print_usage(stdout, 1)); - warn("illegal option -- %c\n", optopt); - return (print_usage(stderr, 0)); - } - } - - if (optind < argc) { - if (filename != NULL) - return (print_usage(stderr, 0)); - filename = argv[optind]; - } - } - - if (filename == NULL) - return (print_usage(stderr, 0)); - - if (flags == 0 && ufile == NULL) - flags = F_ALLMSK; - - if ((fd = open(filename, O_RDONLY)) == -1) - die("failed to open %s", filename); - - if ((elf = elf_begin(fd, ELF_C_READ, NULL)) != NULL && - gelf_getehdr(elf, &ehdr) != NULL) { - - Elf_Data *dp; - Elf_Scn *ctfscn = findelfscn(elf, &ehdr, ".SUNW_ctf"); - Elf_Scn *symscn; - GElf_Shdr ctfshdr; - - if (ctfscn == NULL || (dp = elf_getdata(ctfscn, NULL)) == NULL) - die("%s does not contain .SUNW_ctf data\n", filename); - - cd.cd_ctfdata = dp->d_buf; - cd.cd_ctflen = dp->d_size; - - /* - * If the sh_link field of the CTF section header is non-zero - * it indicates which section contains the symbol table that - * should be used. We default to the .symtab section if sh_link - * is zero or if there's an error reading the section header. - */ - if (gelf_getshdr(ctfscn, &ctfshdr) != NULL && - ctfshdr.sh_link != 0) { - symscn = elf_getscn(elf, ctfshdr.sh_link); - } else { - symscn = findelfscn(elf, &ehdr, ".symtab"); - } - - /* If we found a symbol table, find the corresponding strings */ - if (symscn != NULL) { - GElf_Shdr shdr; - Elf_Scn *symstrscn; - - if (gelf_getshdr(symscn, &shdr) != NULL) { - symstrscn = elf_getscn(elf, shdr.sh_link); - - cd.cd_nsyms = shdr.sh_size / shdr.sh_entsize; - cd.cd_symdata = elf_getdata(symscn, NULL); - cd.cd_strdata = elf_getdata(symstrscn, NULL); - } - } - } else { - struct stat st; - - if (fstat(fd, &st) == -1) - die("failed to fstat %s", filename); - - cd.cd_ctflen = st.st_size; - cd.cd_ctfdata = mmap(NULL, cd.cd_ctflen, PROT_READ, - MAP_PRIVATE, fd, 0); - if (cd.cd_ctfdata == MAP_FAILED) - die("failed to mmap %s", filename); - } - - /* - * Get a pointer to the CTF data buffer and interpret the first portion - * as a ctf_header_t. Validate the magic number and size. - */ - - if (cd.cd_ctflen < sizeof (ctf_preamble_t)) - die("%s does not contain a CTF preamble\n", filename); - - /* LINTED - pointer alignment */ - pp = (const ctf_preamble_t *)cd.cd_ctfdata; - - if (pp->ctp_magic != CTF_MAGIC) - die("%s does not appear to contain CTF data\n", filename); - - if (pp->ctp_version == CTF_VERSION) { - /* LINTED - pointer alignment */ - hp = (ctf_header_t *)cd.cd_ctfdata; - cd.cd_ctfdata = (caddr_t)cd.cd_ctfdata + sizeof (ctf_header_t); - - if (cd.cd_ctflen < sizeof (ctf_header_t)) { - die("%s does not contain a v%d CTF header\n", filename, - CTF_VERSION); - } - - } else { - die("%s contains unsupported CTF version %d\n", filename, - pp->ctp_version); - } - - /* - * If the data buffer is compressed, then malloc a buffer large enough - * to hold the decompressed data, and use zlib to decompress it. - */ - if (hp->cth_flags & CTF_F_COMPRESS) { - z_stream zstr; - void *buf; - int rc; - - if ((buf = malloc(hp->cth_stroff + hp->cth_strlen)) == NULL) - die("failed to allocate decompression buffer"); - - bzero(&zstr, sizeof (z_stream)); - zstr.next_in = (void *)cd.cd_ctfdata; - zstr.avail_in = cd.cd_ctflen; - zstr.next_out = buf; - zstr.avail_out = hp->cth_stroff + hp->cth_strlen; - - if ((rc = inflateInit(&zstr)) != Z_OK) - die("failed to initialize zlib: %s\n", zError(rc)); - - if ((rc = inflate(&zstr, Z_FINISH)) != Z_STREAM_END) - die("failed to decompress CTF data: %s\n", zError(rc)); - - if ((rc = inflateEnd(&zstr)) != Z_OK) - die("failed to finish decompression: %s\n", zError(rc)); - - if (zstr.total_out != hp->cth_stroff + hp->cth_strlen) - die("CTF data is corrupt -- short decompression\n"); - - cd.cd_ctfdata = buf; - cd.cd_ctflen = hp->cth_stroff + hp->cth_strlen; - } - - if (flags & F_HDR) - error |= print_header(hp, &cd); - if (flags & (F_LABEL)) - error |= print_labeltable(hp, &cd); - if (flags & (F_DATA | F_STATS)) - error |= read_data(hp, &cd); - if (flags & (F_FUNC | F_STATS)) - error |= read_funcs(hp, &cd); - if (flags & (F_TYPES | F_STATS)) - error |= read_types(hp, &cd); - if (flags & (F_STR | F_STATS)) - error |= read_strtab(hp, &cd); - if (flags & F_STATS) - error |= print_stats(); - - /* - * If the -u option is specified, write the uncompressed CTF data to a - * raw CTF file. CTF data can already be extracted compressed by - * applying elfdump -w -N .SUNW_ctf to an ELF file, so we don't bother. - */ - if (ufile != NULL) { - ctf_header_t h; - - bcopy(hp, &h, sizeof (h)); - h.cth_flags &= ~CTF_F_COMPRESS; - - if ((ufd = open(ufile, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0 || - write(ufd, &h, sizeof (h)) != sizeof (h) || - write(ufd, cd.cd_ctfdata, cd.cd_ctflen) != cd.cd_ctflen) { - warn("failed to write CTF data to '%s'", ufile); - error |= E_ERROR; - } - - (void) close(ufd); - } - - if (elf != NULL) - (void) elf_end(elf); - - (void) close(fd); - return (error); -} diff --git a/usr/src/tools/ctf/dump/i386/Makefile b/usr/src/tools/ctf/dump/i386/Makefile deleted file mode 100644 index 94e5883ae2..0000000000 --- a/usr/src/tools/ctf/dump/i386/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright (c) 2001 by Sun Microsystems, Inc. -# All rights reserved. -# -#ident "%Z%%M% %I% %E% SMI" - -include ../Makefile.com diff --git a/usr/src/tools/ctf/dump/sparc/Makefile b/usr/src/tools/ctf/dump/sparc/Makefile deleted file mode 100644 index 94e5883ae2..0000000000 --- a/usr/src/tools/ctf/dump/sparc/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright (c) 2001 by Sun Microsystems, Inc. -# All rights reserved. -# -#ident "%Z%%M% %I% %E% SMI" - -include ../Makefile.com diff --git a/usr/src/tools/ctf/dwarf/Makefile.com b/usr/src/tools/ctf/dwarf/Makefile.com index 2e18b40fe4..67ffd64a62 100644 --- a/usr/src/tools/ctf/dwarf/Makefile.com +++ b/usr/src/tools/ctf/dwarf/Makefile.com @@ -69,11 +69,10 @@ OBJECTS=dwarf_abbrev.o \ include $(SRC)/lib/Makefile.lib -SRCS= $(PICS:%.o=../common/%.c) -FILEMODE = 0755 - -SRCDIR = ../common/ +FILEMODE = 0755 +SRCDIR = $(SRC)/lib/libdwarf/common/ +SRCS = $(PICS:%.o=$(SRCDIR)/%.c) CPPFLAGS += -I$(SRCDIR) -DELF_TARGET_ALL=1 CERRWARN += -_gcc=-Wno-unused diff --git a/usr/src/tools/ctf/dwarf/THIRDPARTYLICENSE b/usr/src/tools/ctf/dwarf/THIRDPARTYLICENSE deleted file mode 100644 index b9320c2d56..0000000000 --- a/usr/src/tools/ctf/dwarf/THIRDPARTYLICENSE +++ /dev/null @@ -1,30 +0,0 @@ - Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, - USA. - - Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan diff --git a/usr/src/tools/ctf/dwarf/THIRDPARTYLICENSE.descrip b/usr/src/tools/ctf/dwarf/THIRDPARTYLICENSE.descrip deleted file mode 100644 index 73abaac973..0000000000 --- a/usr/src/tools/ctf/dwarf/THIRDPARTYLICENSE.descrip +++ /dev/null @@ -1 +0,0 @@ -LIBDWARF LIBRARY THAT SUPPORTS THE DWARF OPEN SOURCE STANDARD diff --git a/usr/src/tools/ctf/dwarf/common/cmplrs/dwarf_addr_finder.h b/usr/src/tools/ctf/dwarf/common/cmplrs/dwarf_addr_finder.h deleted file mode 100644 index 0eda6d1c44..0000000000 --- a/usr/src/tools/ctf/dwarf/common/cmplrs/dwarf_addr_finder.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - dwarf_addr_finder.h - $Source: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/include/cmplrs/RCS/dwarf_addr_finder.h,v $ - $Date: 2002/06/11 17:49:06 $ - - Defines user interface. - -*/ - -/* return codes for functions -*/ -#define DW_DLV_NO_ENTRY -1 -#define DW_DLV_OK 0 -#define DW_DLV_ERROR 1 - - -/* the following are the 'section' number passed to the called-back - function. - The called-back application must translate this to the - appropriate elf section number/pointer. - - Putting this burden on the application avoids having to store - the numbers in the Dwarf_Debug structure (thereby saving space - for most consumers). -*/ -#define DW_SECTION_INFO 0 -#define DW_SECTION_FRAME 1 -#define DW_SECTION_ARANGES 2 -#define DW_SECTION_LINE 3 -#define DW_SECTION_LOC 4 /* .debug_loc */ - -/* section is one of the above codes: it specifies a section. - secoff is the offset in the dwarf section. - existingAddr is the value at the specified offset (so the - called back routine can sanity check the proceedings). - It's up to the caller to know the size of an address (4 or 8) - and update the right number of bytes. -*/ -typedef int (*Dwarf_addr_callback_func) (int /*section*/, - Dwarf_Off /*secoff*/, Dwarf_Addr /*existingAddr*/); - -/* call this to do the work: it calls back thru cb_func - once per each address to be modified. - Once this returns you are done. - Returns DW_DLV_OK if finished ok. - Returns DW_DLV_ERROR if there was some kind of error, in which - the dwarf error number was passed back thu the dwerr ptr. - Returns DW_DLV_NO_ENTRY if there are no relevant dwarf sections, - so there were no addresses to be modified (and none - called back). -*/ -int _dwarf_addr_finder(dwarf_elf_handle elf_file_ptr, - Dwarf_addr_callback_func cb_func, - int *dwerr); - diff --git a/usr/src/tools/ctf/dwarf/common/config.h b/usr/src/tools/ctf/dwarf/common/config.h deleted file mode 100644 index 42b286cfda..0000000000 --- a/usr/src/tools/ctf/dwarf/common/config.h +++ /dev/null @@ -1,143 +0,0 @@ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.in by autoheader. */ - -/* Define if building universal (internal helper macro) */ -/* #undef AC_APPLE_UNIVERSAL_BUILD */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ALLOCA_H 1 - -/* Define 1 if want to allow producer to build with 32/64bit section offsets - per dwarf3 */ -#define HAVE_DWARF2_99_EXTENSION 1 - -/* Define to 1 if the elf64_getehdr function is in libelf.a. */ -#define HAVE_ELF64_GETEHDR 1 - -/* Define to 1 if the elf64_getshdr function is in libelf.a. */ -#define HAVE_ELF64_GETSHDR 1 - -/* Define 1 if Elf64_Rela defined. */ -#define HAVE_ELF64_RELA 1 - -/* Define 1 if Elf64_Sym defined. */ -#define HAVE_ELF64_SYM 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ELFACCESS_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ELF_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LIBELF_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LIBELF_LIBELF_H */ - -/* Define 1 if off64 is defined via libelf with GNU_SOURCE. */ -#define HAVE_LIBELF_OFF64_OK 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define 1 if need nonstandard printf format for 64bit */ -/* #undef HAVE_NONSTANDARD_PRINTF_64_FORMAT */ - -/* Define 1 to default to old DW_FRAME_CFA_COL */ -/* #undef HAVE_OLD_FRAME_CFA_COL */ - -/* Define 1 if plain libelf builds. */ -#define HAVE_RAW_LIBELF_OK 1 - -/* Define 1 if R_IA_64_DIR32LSB is defined (might be enum value). */ -/* #undef HAVE_R_IA_64_DIR32LSB */ - -/* Define 1 if want producer to build with IRIX offset sizes */ -/* #undef HAVE_SGI_IRIX_OFFSETS */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define 1 if want producer to build with only 32bit section offsets */ -/* #undef HAVE_STRICT_DWARF2_32BIT_OFFSET */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_IA64_ELF_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define 1 if want to allow Windows full path detection */ -/* #undef HAVE_WINDOWS_PATH */ - -/* See if __uint32_t is predefined in the compiler. */ -/* #undef HAVE___UINT32_T */ - -/* Define 1 if __uint32_t is in sgidefs.h. */ -/* #undef HAVE___UINT32_T_IN_SGIDEFS_H */ - -/* Define 1 if sys/types.h defines __uint32_t. */ -/* #undef HAVE___UINT32_T_IN_SYS_TYPES_H */ - -/* See if __uint64_t is predefined in the compiler. */ -/* #undef HAVE___UINT64_T */ - -/* Define 1 if is in sgidefs.h. */ -/* #undef HAVE___UINT64_T_IN_SGIDEFS_H */ - -/* Define 1 if sys/types.h defines __uint64_t. */ -/* #undef HAVE___UINT64_T_IN_SYS_TYPES_H */ - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "" - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# if defined(__sparc) -# define WORDS_BIGENDIAN 1 -# else -# undef WORDS_BIGENDIAN -# endif -#endif diff --git a/usr/src/tools/ctf/dwarf/common/dwarf.h b/usr/src/tools/ctf/dwarf/common/dwarf.h deleted file mode 100644 index b064c4d86b..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf.h +++ /dev/null @@ -1,1078 +0,0 @@ -/* - Copyright (C) 2000,2001,2003,2004,2005,2006 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. - Portions Copyright 2007-2010 David Anderson. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - -#ifndef __DWARF_H -#define __DWARF_H -#ifdef __cplusplus -extern "C" { -#endif - -/* - dwarf.h DWARF debugging information values - $Revision: 1.41 $ $Date: 2006/04/17 00:09:56 $ - - The comment "DWARF3" appears where there are - new entries from DWARF3 as of 2004, "DWARF3f" - where there are new entries as of the November 2005 - public review document and other comments apply - where extension entries appear. - - Extensions part of DWARF4 are marked DWARF4. - - A few extension names have omitted the 'vendor id' - (See chapter 7, "Vendor Extensibility"). Please - always use a 'vendor id' string in extension names. - - Vendors should use a vendor string in names and - whereever possible avoid duplicating values used by - other vendor extensions - -*/ - - -#define DW_TAG_array_type 0x01 -#define DW_TAG_class_type 0x02 -#define DW_TAG_entry_point 0x03 -#define DW_TAG_enumeration_type 0x04 -#define DW_TAG_formal_parameter 0x05 -#define DW_TAG_imported_declaration 0x08 -#define DW_TAG_label 0x0a -#define DW_TAG_lexical_block 0x0b -#define DW_TAG_member 0x0d -#define DW_TAG_pointer_type 0x0f -#define DW_TAG_reference_type 0x10 -#define DW_TAG_compile_unit 0x11 -#define DW_TAG_string_type 0x12 -#define DW_TAG_structure_type 0x13 -#define DW_TAG_subroutine_type 0x15 -#define DW_TAG_typedef 0x16 -#define DW_TAG_union_type 0x17 -#define DW_TAG_unspecified_parameters 0x18 -#define DW_TAG_variant 0x19 -#define DW_TAG_common_block 0x1a -#define DW_TAG_common_inclusion 0x1b -#define DW_TAG_inheritance 0x1c -#define DW_TAG_inlined_subroutine 0x1d -#define DW_TAG_module 0x1e -#define DW_TAG_ptr_to_member_type 0x1f -#define DW_TAG_set_type 0x20 -#define DW_TAG_subrange_type 0x21 -#define DW_TAG_with_stmt 0x22 -#define DW_TAG_access_declaration 0x23 -#define DW_TAG_base_type 0x24 -#define DW_TAG_catch_block 0x25 -#define DW_TAG_const_type 0x26 -#define DW_TAG_constant 0x27 -#define DW_TAG_enumerator 0x28 -#define DW_TAG_file_type 0x29 -#define DW_TAG_friend 0x2a -#define DW_TAG_namelist 0x2b - /* Early releases of this header had the following - misspelled with a trailing 's' */ -#define DW_TAG_namelist_item 0x2c /* DWARF3/2 spelling */ -#define DW_TAG_namelist_items 0x2c /* SGI misspelling/typo */ -#define DW_TAG_packed_type 0x2d -#define DW_TAG_subprogram 0x2e - /* The DWARF2 document had two spellings of the following - two TAGs, DWARF3 specifies the longer spelling. */ -#define DW_TAG_template_type_parameter 0x2f /* DWARF3/2 spelling*/ -#define DW_TAG_template_type_param 0x2f /* DWARF2 spelling*/ -#define DW_TAG_template_value_parameter 0x30 /* DWARF3/2 spelling*/ -#define DW_TAG_template_value_param 0x30 /* DWARF2 spelling*/ -#define DW_TAG_thrown_type 0x31 -#define DW_TAG_try_block 0x32 -#define DW_TAG_variant_part 0x33 -#define DW_TAG_variable 0x34 -#define DW_TAG_volatile_type 0x35 -#define DW_TAG_dwarf_procedure 0x36 /* DWARF3 */ -#define DW_TAG_restrict_type 0x37 /* DWARF3 */ -#define DW_TAG_interface_type 0x38 /* DWARF3 */ -#define DW_TAG_namespace 0x39 /* DWARF3 */ -#define DW_TAG_imported_module 0x3a /* DWARF3 */ -#define DW_TAG_unspecified_type 0x3b /* DWARF3 */ -#define DW_TAG_partial_unit 0x3c /* DWARF3 */ -#define DW_TAG_imported_unit 0x3d /* DWARF3 */ - /* Do not use DW_TAG_mutable_type */ -#define DW_TAG_mutable_type 0x3e /* Withdrawn from DWARF3 by DWARF3f. */ -#define DW_TAG_condition 0x3f /* DWARF3f */ -#define DW_TAG_shared_type 0x40 /* DWARF3f */ -#define DW_TAG_type_unit 0x41 /* DWARF4 */ -#define DW_TAG_rvalue_reference_type 0x42 /* DWARF4 */ -#define DW_TAG_template_alias 0x43 /* DWARF4 */ -#define DW_TAG_lo_user 0x4080 - -#define DW_TAG_MIPS_loop 0x4081 - -/* HP extensions: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz */ -#define DW_TAG_HP_array_descriptor 0x4090 /* HP */ - -/* GNU extensions. The first 3 missing the GNU_. */ -#define DW_TAG_format_label 0x4101 /* GNU. Fortran. */ -#define DW_TAG_function_template 0x4102 /* GNU. For C++ */ -#define DW_TAG_class_template 0x4103 /* GNU. For C++ */ -#define DW_TAG_GNU_BINCL 0x4104 /* GNU */ -#define DW_TAG_GNU_EINCL 0x4105 /* GNU */ - - -/* GNU extension. http://gcc.gnu.org/wiki/TemplateParmsDwarf */ -#define DW_TAG_GNU_template_template_parameter 0x4106 /* GNU */ -#define DW_TAG_GNU_template_template_param 0x4106 /* GNU */ -#define DW_TAG_GNU_template_parameter_pack 0x4107 /* GNU */ -#define DW_TAG_GNU_formal_parameter_pack 0x4108 /* GNU */ - -/* ALTIUM extensions */ - /* DSP-C/Starcore __circ qualifier */ -#define DW_TAG_ALTIUM_circ_type 0x5101 /* ALTIUM */ - /* Starcore __mwa_circ qualifier */ -#define DW_TAG_ALTIUM_mwa_circ_type 0x5102 /* ALTIUM */ - /* Starcore __rev_carry qualifier */ -#define DW_TAG_ALTIUM_rev_carry_type 0x5103 /* ALTIUM */ - /* M16 __rom qualifier */ -#define DW_TAG_ALTIUM_rom 0x5111 /* ALTIUM */ - -/* The following 3 are extensions to support UPC */ -#define DW_TAG_upc_shared_type 0x8765 /* UPC */ -#define DW_TAG_upc_strict_type 0x8766 /* UPC */ -#define DW_TAG_upc_relaxed_type 0x8767 /* UPC */ - -/* PGI (STMicroelectronics) extensions. */ -#define DW_TAG_PGI_kanji_type 0xa000 /* PGI */ -#define DW_TAG_PGI_interface_block 0xa020 /* PGI */ -/* The following are SUN extensions */ -#define DW_TAG_SUN_function_template 0x4201 /* SUN */ -#define DW_TAG_SUN_class_template 0x4202 /* SUN */ -#define DW_TAG_SUN_struct_template 0x4203 /* SUN */ -#define DW_TAG_SUN_union_template 0x4204 /* SUN */ -#define DW_TAG_SUN_indirect_inheritance 0x4205 /* SUN */ -#define DW_TAG_SUN_codeflags 0x4206 /* SUN */ -#define DW_TAG_SUN_memop_info 0x4207 /* SUN */ -#define DW_TAG_SUN_omp_child_func 0x4208 /* SUN */ -#define DW_TAG_SUN_rtti_descriptor 0x4209 /* SUN */ -#define DW_TAG_SUN_dtor_info 0x420a /* SUN */ -#define DW_TAG_SUN_dtor 0x420b /* SUN */ -#define DW_TAG_SUN_f90_interface 0x420c /* SUN */ -#define DW_TAG_SUN_fortran_vax_structure 0x420d /* SUN */ -#define DW_TAG_SUN_hi 0x42ff /* SUN */ - - -#define DW_TAG_hi_user 0xffff - -#define DW_children_no 0 -#define DW_children_yes 1 - - - -#define DW_FORM_addr 0x01 -#define DW_FORM_block2 0x03 -#define DW_FORM_block4 0x04 -#define DW_FORM_data2 0x05 -#define DW_FORM_data4 0x06 -#define DW_FORM_data8 0x07 -#define DW_FORM_string 0x08 -#define DW_FORM_block 0x09 -#define DW_FORM_block1 0x0a -#define DW_FORM_data1 0x0b -#define DW_FORM_flag 0x0c -#define DW_FORM_sdata 0x0d -#define DW_FORM_strp 0x0e -#define DW_FORM_udata 0x0f -#define DW_FORM_ref_addr 0x10 -#define DW_FORM_ref1 0x11 -#define DW_FORM_ref2 0x12 -#define DW_FORM_ref4 0x13 -#define DW_FORM_ref8 0x14 -#define DW_FORM_ref_udata 0x15 -#define DW_FORM_indirect 0x16 -#define DW_FORM_sec_offset 0x17 /* DWARF4 */ -#define DW_FORM_exprloc 0x18 /* DWARF4 */ -#define DW_FORM_flag_present 0x19 /* DWARF4 */ -/* 0x1a thru 0x1f were left unused accidentally. Reserved for future use. */ -#define DW_FORM_ref_sig8 0x20 /* DWARF4 */ - -#define DW_AT_sibling 0x01 -#define DW_AT_location 0x02 -#define DW_AT_name 0x03 -#define DW_AT_ordering 0x09 -#define DW_AT_subscr_data 0x0a -#define DW_AT_byte_size 0x0b -#define DW_AT_bit_offset 0x0c -#define DW_AT_bit_size 0x0d -#define DW_AT_element_list 0x0f -#define DW_AT_stmt_list 0x10 -#define DW_AT_low_pc 0x11 -#define DW_AT_high_pc 0x12 -#define DW_AT_language 0x13 -#define DW_AT_member 0x14 -#define DW_AT_discr 0x15 -#define DW_AT_discr_value 0x16 -#define DW_AT_visibility 0x17 -#define DW_AT_import 0x18 -#define DW_AT_string_length 0x19 -#define DW_AT_common_reference 0x1a -#define DW_AT_comp_dir 0x1b -#define DW_AT_const_value 0x1c -#define DW_AT_containing_type 0x1d -#define DW_AT_default_value 0x1e -#define DW_AT_inline 0x20 -#define DW_AT_is_optional 0x21 -#define DW_AT_lower_bound 0x22 -#define DW_AT_producer 0x25 -#define DW_AT_prototyped 0x27 -#define DW_AT_return_addr 0x2a -#define DW_AT_start_scope 0x2c -#define DW_AT_bit_stride 0x2e /* DWARF3 name */ -#define DW_AT_stride_size 0x2e /* DWARF2 name */ -#define DW_AT_upper_bound 0x2f -#define DW_AT_abstract_origin 0x31 -#define DW_AT_accessibility 0x32 -#define DW_AT_address_class 0x33 -#define DW_AT_artificial 0x34 -#define DW_AT_base_types 0x35 -#define DW_AT_calling_convention 0x36 -#define DW_AT_count 0x37 -#define DW_AT_data_member_location 0x38 -#define DW_AT_decl_column 0x39 -#define DW_AT_decl_file 0x3a -#define DW_AT_decl_line 0x3b -#define DW_AT_declaration 0x3c -#define DW_AT_discr_list 0x3d -#define DW_AT_encoding 0x3e -#define DW_AT_external 0x3f -#define DW_AT_frame_base 0x40 -#define DW_AT_friend 0x41 -#define DW_AT_identifier_case 0x42 -#define DW_AT_macro_info 0x43 -#define DW_AT_namelist_item 0x44 -#define DW_AT_priority 0x45 -#define DW_AT_segment 0x46 -#define DW_AT_specification 0x47 -#define DW_AT_static_link 0x48 -#define DW_AT_type 0x49 -#define DW_AT_use_location 0x4a -#define DW_AT_variable_parameter 0x4b -#define DW_AT_virtuality 0x4c -#define DW_AT_vtable_elem_location 0x4d -#define DW_AT_allocated 0x4e /* DWARF3 */ -#define DW_AT_associated 0x4f /* DWARF3 */ -#define DW_AT_data_location 0x50 /* DWARF3 */ -#define DW_AT_byte_stride 0x51 /* DWARF3f */ -#define DW_AT_stride 0x51 /* DWARF3 (do not use) */ -#define DW_AT_entry_pc 0x52 /* DWARF3 */ -#define DW_AT_use_UTF8 0x53 /* DWARF3 */ -#define DW_AT_extension 0x54 /* DWARF3 */ -#define DW_AT_ranges 0x55 /* DWARF3 */ -#define DW_AT_trampoline 0x56 /* DWARF3 */ -#define DW_AT_call_column 0x57 /* DWARF3 */ -#define DW_AT_call_file 0x58 /* DWARF3 */ -#define DW_AT_call_line 0x59 /* DWARF3 */ -#define DW_AT_description 0x5a /* DWARF3 */ -#define DW_AT_binary_scale 0x5b /* DWARF3f */ -#define DW_AT_decimal_scale 0x5c /* DWARF3f */ -#define DW_AT_small 0x5d /* DWARF3f */ -#define DW_AT_decimal_sign 0x5e /* DWARF3f */ -#define DW_AT_digit_count 0x5f /* DWARF3f */ -#define DW_AT_picture_string 0x60 /* DWARF3f */ -#define DW_AT_mutable 0x61 /* DWARF3f */ -#define DW_AT_threads_scaled 0x62 /* DWARF3f */ -#define DW_AT_explicit 0x63 /* DWARF3f */ -#define DW_AT_object_pointer 0x64 /* DWARF3f */ -#define DW_AT_endianity 0x65 /* DWARF3f */ -#define DW_AT_elemental 0x66 /* DWARF3f */ -#define DW_AT_pure 0x67 /* DWARF3f */ -#define DW_AT_recursive 0x68 /* DWARF3f */ -#define DW_AT_signature 0x69 /* DWARF4 */ -#define DW_AT_main_subprogram 0x6a /* DWARF4 */ -#define DW_AT_data_bit_offset 0x6b /* DWARF4 */ -#define DW_AT_const_expr 0x6c /* DWARF4 */ -#define DW_AT_enum_class 0x6d /* DWARF4 */ -#define DW_AT_linkage_name 0x6e /* DWARF4 */ - -/* In extensions, we attempt to include the vendor extension - in the name even when the vendor leaves it out. */ - -/* HP extensions. */ -#define DW_AT_HP_block_index 0x2000 /* HP */ - -/* Follows extension so dwarfdump prints the most-likely-useful name. */ -#define DW_AT_lo_user 0x2000 - -#define DW_AT_MIPS_fde 0x2001 /* MIPS/SGI */ -#define DW_AT_MIPS_loop_begin 0x2002 /* MIPS/SGI */ -#define DW_AT_MIPS_tail_loop_begin 0x2003 /* MIPS/SGI */ -#define DW_AT_MIPS_epilog_begin 0x2004 /* MIPS/SGI */ -#define DW_AT_MIPS_loop_unroll_factor 0x2005 /* MIPS/SGI */ -#define DW_AT_MIPS_software_pipeline_depth 0x2006 /* MIPS/SGI */ -#define DW_AT_MIPS_linkage_name 0x2007 /* MIPS/SGI, GNU, and others.*/ -#define DW_AT_MIPS_stride 0x2008 /* MIPS/SGI */ -#define DW_AT_MIPS_abstract_name 0x2009 /* MIPS/SGI */ -#define DW_AT_MIPS_clone_origin 0x200a /* MIPS/SGI */ -#define DW_AT_MIPS_has_inlines 0x200b /* MIPS/SGI */ -#define DW_AT_MIPS_stride_byte 0x200c /* MIPS/SGI */ -#define DW_AT_MIPS_stride_elem 0x200d /* MIPS/SGI */ -#define DW_AT_MIPS_ptr_dopetype 0x200e /* MIPS/SGI */ -#define DW_AT_MIPS_allocatable_dopetype 0x200f /* MIPS/SGI */ -#define DW_AT_MIPS_assumed_shape_dopetype 0x2010 /* MIPS/SGI */ -#define DW_AT_MIPS_assumed_size 0x2011 /* MIPS/SGI */ - -/* HP extensions. */ -#define DW_AT_HP_unmodifiable 0x2001 /* conflict: MIPS */ -#define DW_AT_HP_actuals_stmt_list 0x2010 /* conflict: MIPS */ -#define DW_AT_HP_proc_per_section 0x2011 /* conflict: MIPS */ -#define DW_AT_HP_raw_data_ptr 0x2012 /* HP */ -#define DW_AT_HP_pass_by_reference 0x2013 /* HP */ -#define DW_AT_HP_opt_level 0x2014 /* HP */ -#define DW_AT_HP_prof_version_id 0x2015 /* HP */ -#define DW_AT_HP_opt_flags 0x2016 /* HP */ -#define DW_AT_HP_cold_region_low_pc 0x2017 /* HP */ -#define DW_AT_HP_cold_region_high_pc 0x2018 /* HP */ -#define DW_AT_HP_all_variables_modifiable 0x2019 /* HP */ -#define DW_AT_HP_linkage_name 0x201a /* HP */ -#define DW_AT_HP_prof_flags 0x201b /* HP */ - -#define DW_AT_CPQ_discontig_ranges 0x2001 /* COMPAQ/HP */ -#define DW_AT_CPQ_semantic_events 0x2002 /* COMPAQ/HP */ -#define DW_AT_CPQ_split_lifetimes_var 0x2003 /* COMPAQ/HP */ -#define DW_AT_CPQ_split_lifetimes_rtn 0x2004 /* COMPAQ/HP */ -#define DW_AT_CPQ_prologue_length 0x2005 /* COMPAQ/HP */ - -#define DW_AT_INTEL_other_endian 0x2026 /* Intel, 1 if byte swapped. */ - -/* GNU extensions. */ -#define DW_AT_sf_names 0x2101 /* GNU */ -#define DW_AT_src_info 0x2102 /* GNU */ -#define DW_AT_mac_info 0x2103 /* GNU */ -#define DW_AT_src_coords 0x2104 /* GNU */ -#define DW_AT_body_begin 0x2105 /* GNU */ -#define DW_AT_body_end 0x2106 /* GNU */ -#define DW_AT_GNU_vector 0x2107 /* GNU */ -#define DW_AT_GNU_template_name 0x2108 /* GNU */ - -/* ALTIUM extension: ALTIUM Compliant location lists (flag) */ -#define DW_AT_ALTIUM_loclist 0x2300 /* ALTIUM */ - -/* Sun extensions */ -#define DW_AT_SUN_template 0x2201 /* SUN */ -#define DW_AT_VMS_rtnbeg_pd_address 0x2201 /* VMS */ -#define DW_AT_SUN_alignment 0x2202 /* SUN */ -#define DW_AT_SUN_vtable 0x2203 /* SUN */ -#define DW_AT_SUN_count_guarantee 0x2204 /* SUN */ -#define DW_AT_SUN_command_line 0x2205 /* SUN */ -#define DW_AT_SUN_vbase 0x2206 /* SUN */ -#define DW_AT_SUN_compile_options 0x2207 /* SUN */ -#define DW_AT_SUN_language 0x2208 /* SUN */ -#define DW_AT_SUN_browser_file 0x2209 /* SUN */ -#define DW_AT_SUN_vtable_abi 0x2210 /* SUN */ -#define DW_AT_SUN_func_offsets 0x2211 /* SUN */ -#define DW_AT_SUN_cf_kind 0x2212 /* SUN */ -#define DW_AT_SUN_vtable_index 0x2213 /* SUN */ -#define DW_AT_SUN_omp_tpriv_addr 0x2214 /* SUN */ -#define DW_AT_SUN_omp_child_func 0x2215 /* SUN */ -#define DW_AT_SUN_func_offset 0x2216 /* SUN */ -#define DW_AT_SUN_memop_type_ref 0x2217 /* SUN */ -#define DW_AT_SUN_profile_id 0x2218 /* SUN */ -#define DW_AT_SUN_memop_signature 0x2219 /* SUN */ -#define DW_AT_SUN_obj_dir 0x2220 /* SUN */ -#define DW_AT_SUN_obj_file 0x2221 /* SUN */ -#define DW_AT_SUN_original_name 0x2222 /* SUN */ -#define DW_AT_SUN_hwcprof_signature 0x2223 /* SUN */ -#define DW_AT_SUN_amd64_parmdump 0x2224 /* SUN */ -#define DW_AT_SUN_part_link_name 0x2225 /* SUN */ -#define DW_AT_SUN_link_name 0x2226 /* SUN */ -#define DW_AT_SUN_pass_with_const 0x2227 /* SUN */ -#define DW_AT_SUN_return_with_const 0x2228 /* SUN */ -#define DW_AT_SUN_import_by_name 0x2229 /* SUN */ -#define DW_AT_SUN_f90_pointer 0x222a /* SUN */ -#define DW_AT_SUN_pass_by_ref 0x222b /* SUN */ -#define DW_AT_SUN_f90_allocatable 0x222c /* SUN */ -#define DW_AT_SUN_f90_assumed_shape_array 0x222d /* SUN */ -#define DW_AT_SUN_c_vla 0x222e /* SUN */ -#define DW_AT_SUN_return_value_ptr 0x2230 /* SUN */ -#define DW_AT_SUN_dtor_start 0x2231 /* SUN */ -#define DW_AT_SUN_dtor_length 0x2232 /* SUN */ -#define DW_AT_SUN_dtor_state_initial 0x2233 /* SUN */ -#define DW_AT_SUN_dtor_state_final 0x2234 /* SUN */ -#define DW_AT_SUN_dtor_state_deltas 0x2235 /* SUN */ -#define DW_AT_SUN_import_by_lname 0x2236 /* SUN */ -#define DW_AT_SUN_f90_use_only 0x2237 /* SUN */ -#define DW_AT_SUN_namelist_spec 0x2238 /* SUN */ -#define DW_AT_SUN_is_omp_child_func 0x2239 /* SUN */ -#define DW_AT_SUN_fortran_main_alias 0x223a /* SUN */ -#define DW_AT_SUN_fortran_based 0x223b /* SUN */ - -/* UPC extension */ -#define DW_AT_upc_threads_scaled 0x3210 /* UPC */ - -/* PGI (STMicroelectronics) extensions. */ -#define DW_AT_PGI_lbase 0x3a00 /* PGI. Block, constant, reference. This attribute is an ASTPLAB extension used to describe the array local base. */ -#define DW_AT_PGI_soffset 0x3a01 /* PGI. Block, constant, reference. ASTPLAB adds this attribute to describe the section offset, or the offset to the first element in the dimension. */ -#define DW_AT_PGI_lstride 0x3a02 /* PGI. Block, constant, reference. ASTPLAB adds this attribute to describe the linear stride or the distance between elements in the dimension. */ - -/* Apple Extensions for closures */ -#define DW_AT_APPLE_closure 0x3fe4 /* Apple */ -/* Apple Extensions for Objective-C runtime info */ -#define DW_AT_APPLE_major_runtime_vers 0x3fe5 /* Apple */ -#define DW_AT_APPLE_runtime_class 0x3fe6 /* Apple */ - - -#define DW_AT_hi_user 0x3fff - -#define DW_OP_addr 0x03 -#define DW_OP_deref 0x06 -#define DW_OP_const1u 0x08 -#define DW_OP_const1s 0x09 -#define DW_OP_const2u 0x0a -#define DW_OP_const2s 0x0b -#define DW_OP_const4u 0x0c -#define DW_OP_const4s 0x0d -#define DW_OP_const8u 0x0e -#define DW_OP_const8s 0x0f -#define DW_OP_constu 0x10 -#define DW_OP_consts 0x11 -#define DW_OP_dup 0x12 -#define DW_OP_drop 0x13 -#define DW_OP_over 0x14 -#define DW_OP_pick 0x15 -#define DW_OP_swap 0x16 -#define DW_OP_rot 0x17 -#define DW_OP_xderef 0x18 -#define DW_OP_abs 0x19 -#define DW_OP_and 0x1a -#define DW_OP_div 0x1b -#define DW_OP_minus 0x1c -#define DW_OP_mod 0x1d -#define DW_OP_mul 0x1e -#define DW_OP_neg 0x1f -#define DW_OP_not 0x20 -#define DW_OP_or 0x21 -#define DW_OP_plus 0x22 -#define DW_OP_plus_uconst 0x23 -#define DW_OP_shl 0x24 -#define DW_OP_shr 0x25 -#define DW_OP_shra 0x26 -#define DW_OP_xor 0x27 -#define DW_OP_bra 0x28 -#define DW_OP_eq 0x29 -#define DW_OP_ge 0x2a -#define DW_OP_gt 0x2b -#define DW_OP_le 0x2c -#define DW_OP_lt 0x2d -#define DW_OP_ne 0x2e -#define DW_OP_skip 0x2f -#define DW_OP_lit0 0x30 -#define DW_OP_lit1 0x31 -#define DW_OP_lit2 0x32 -#define DW_OP_lit3 0x33 -#define DW_OP_lit4 0x34 -#define DW_OP_lit5 0x35 -#define DW_OP_lit6 0x36 -#define DW_OP_lit7 0x37 -#define DW_OP_lit8 0x38 -#define DW_OP_lit9 0x39 -#define DW_OP_lit10 0x3a -#define DW_OP_lit11 0x3b -#define DW_OP_lit12 0x3c -#define DW_OP_lit13 0x3d -#define DW_OP_lit14 0x3e -#define DW_OP_lit15 0x3f -#define DW_OP_lit16 0x40 -#define DW_OP_lit17 0x41 -#define DW_OP_lit18 0x42 -#define DW_OP_lit19 0x43 -#define DW_OP_lit20 0x44 -#define DW_OP_lit21 0x45 -#define DW_OP_lit22 0x46 -#define DW_OP_lit23 0x47 -#define DW_OP_lit24 0x48 -#define DW_OP_lit25 0x49 -#define DW_OP_lit26 0x4a -#define DW_OP_lit27 0x4b -#define DW_OP_lit28 0x4c -#define DW_OP_lit29 0x4d -#define DW_OP_lit30 0x4e -#define DW_OP_lit31 0x4f -#define DW_OP_reg0 0x50 -#define DW_OP_reg1 0x51 -#define DW_OP_reg2 0x52 -#define DW_OP_reg3 0x53 -#define DW_OP_reg4 0x54 -#define DW_OP_reg5 0x55 -#define DW_OP_reg6 0x56 -#define DW_OP_reg7 0x57 -#define DW_OP_reg8 0x58 -#define DW_OP_reg9 0x59 -#define DW_OP_reg10 0x5a -#define DW_OP_reg11 0x5b -#define DW_OP_reg12 0x5c -#define DW_OP_reg13 0x5d -#define DW_OP_reg14 0x5e -#define DW_OP_reg15 0x5f -#define DW_OP_reg16 0x60 -#define DW_OP_reg17 0x61 -#define DW_OP_reg18 0x62 -#define DW_OP_reg19 0x63 -#define DW_OP_reg20 0x64 -#define DW_OP_reg21 0x65 -#define DW_OP_reg22 0x66 -#define DW_OP_reg23 0x67 -#define DW_OP_reg24 0x68 -#define DW_OP_reg25 0x69 -#define DW_OP_reg26 0x6a -#define DW_OP_reg27 0x6b -#define DW_OP_reg28 0x6c -#define DW_OP_reg29 0x6d -#define DW_OP_reg30 0x6e -#define DW_OP_reg31 0x6f -#define DW_OP_breg0 0x70 -#define DW_OP_breg1 0x71 -#define DW_OP_breg2 0x72 -#define DW_OP_breg3 0x73 -#define DW_OP_breg4 0x74 -#define DW_OP_breg5 0x75 -#define DW_OP_breg6 0x76 -#define DW_OP_breg7 0x77 -#define DW_OP_breg8 0x78 -#define DW_OP_breg9 0x79 -#define DW_OP_breg10 0x7a -#define DW_OP_breg11 0x7b -#define DW_OP_breg12 0x7c -#define DW_OP_breg13 0x7d -#define DW_OP_breg14 0x7e -#define DW_OP_breg15 0x7f -#define DW_OP_breg16 0x80 -#define DW_OP_breg17 0x81 -#define DW_OP_breg18 0x82 -#define DW_OP_breg19 0x83 -#define DW_OP_breg20 0x84 -#define DW_OP_breg21 0x85 -#define DW_OP_breg22 0x86 -#define DW_OP_breg23 0x87 -#define DW_OP_breg24 0x88 -#define DW_OP_breg25 0x89 -#define DW_OP_breg26 0x8a -#define DW_OP_breg27 0x8b -#define DW_OP_breg28 0x8c -#define DW_OP_breg29 0x8d -#define DW_OP_breg30 0x8e -#define DW_OP_breg31 0x8f -#define DW_OP_regx 0x90 -#define DW_OP_fbreg 0x91 -#define DW_OP_bregx 0x92 -#define DW_OP_piece 0x93 -#define DW_OP_deref_size 0x94 -#define DW_OP_xderef_size 0x95 -#define DW_OP_nop 0x96 -#define DW_OP_push_object_address 0x97 /* DWARF3 */ -#define DW_OP_call2 0x98 /* DWARF3 */ -#define DW_OP_call4 0x99 /* DWARF3 */ -#define DW_OP_call_ref 0x9a /* DWARF3 */ -#define DW_OP_form_tls_address 0x9b /* DWARF3f */ -#define DW_OP_call_frame_cfa 0x9c /* DWARF3f */ -#define DW_OP_bit_piece 0x9d /* DWARF3f */ -#define DW_OP_implicit_value 0x9e /* DWARF4 */ -#define DW_OP_stack_value 0x9f /* DWARF4 */ - - - /* GNU extensions. */ -#define DW_OP_GNU_push_tls_address 0xe0 /* GNU */ - -/* Follows extension so dwarfdump prints the most-likely-useful name. */ -#define DW_OP_lo_user 0xe0 - - /* HP extensions. */ -#define DW_OP_HP_unknown 0xe0 /* HP conflict: GNU */ -#define DW_OP_HP_is_value 0xe1 /* HP */ -#define DW_OP_HP_fltconst4 0xe2 /* HP */ -#define DW_OP_HP_fltconst8 0xe3 /* HP */ -#define DW_OP_HP_mod_range 0xe4 /* HP */ -#define DW_OP_HP_unmod_range 0xe5 /* HP */ -#define DW_OP_HP_tls 0xe6 /* HP */ - -#define DW_OP_INTEL_bit_piece 0xe8 /* Intel: made obsolete by DW_OP_bit_piece above. */ - - - /* Apple extension. */ -#define DW_OP_APPLE_uninit 0xf0 /* Apple */ - -#define DW_OP_hi_user 0xff - -#define DW_ATE_address 0x1 -#define DW_ATE_boolean 0x2 -#define DW_ATE_complex_float 0x3 -#define DW_ATE_float 0x4 -#define DW_ATE_signed 0x5 -#define DW_ATE_signed_char 0x6 -#define DW_ATE_unsigned 0x7 -#define DW_ATE_unsigned_char 0x8 -#define DW_ATE_imaginary_float 0x9 /* DWARF3 */ -#define DW_ATE_packed_decimal 0xa /* DWARF3f */ -#define DW_ATE_numeric_string 0xb /* DWARF3f */ -#define DW_ATE_edited 0xc /* DWARF3f */ -#define DW_ATE_signed_fixed 0xd /* DWARF3f */ -#define DW_ATE_unsigned_fixed 0xe /* DWARF3f */ -#define DW_ATE_decimal_float 0xf /* DWARF3f */ - - -/* ALTIUM extensions. x80, x81 */ -#define DW_ATE_ALTIUM_fract 0x80 /* ALTIUM __fract type */ - -/* Follows extension so dwarfdump prints the most-likely-useful name. */ -#define DW_ATE_lo_user 0x80 - -/* Shown here to help dwarfdump build script. */ -#define DW_ATE_ALTIUM_accum 0x81 /* ALTIUM __accum type */ - -/* HP Floating point extensions. */ -#define DW_ATE_HP_float80 0x80 /* (80 bit). HP */ - - -#define DW_ATE_HP_complex_float80 0x81 /* Complex (80 bit). HP */ -#define DW_ATE_HP_float128 0x82 /* (128 bit). HP */ -#define DW_ATE_HP_complex_float128 0x83 /* Complex (128 bit). HP */ -#define DW_ATE_HP_floathpintel 0x84 /* (82 bit IA64). HP */ -#define DW_ATE_HP_imaginary_float80 0x85 /* HP */ -#define DW_ATE_HP_imaginary_float128 0x86 /* HP */ - -/* Sun extensions */ -#define DW_ATE_SUN_interval_float 0x91 -#define DW_ATE_SUN_imaginary_float 0x92 /* Obsolete: See DW_ATE_imaginary_float */ - -#define DW_ATE_hi_user 0xff - - -/* Decimal Sign codes. */ -#define DW_DS_unsigned 0x01 /* DWARF3f */ -#define DW_DS_leading_overpunch 0x02 /* DWARF3f */ -#define DW_DS_trailing_overpunch 0x03 /* DWARF3f */ -#define DW_DS_leading_separate 0x04 /* DWARF3f */ - -#define DW_DS_trailing_separate 0x05 /* DWARF3f */ - -/* Endian code name. */ -#define DW_END_default 0x00 /* DWARF3f */ -#define DW_END_big 0x01 /* DWARF3f */ -#define DW_END_little 0x02 /* DWARF3f */ - -#define DW_END_lo_user 0x40 /* DWARF3f */ -#define DW_END_hi_user 0xff /* DWARF3f */ - -/* For use with DW_TAG_SUN_codeflags - * If DW_TAG_SUN_codeflags is accepted as a dwarf standard, then - * standard dwarf ATCF entries start at 0x01 - */ -#define DW_ATCF_lo_user 0x40 /* SUN */ -#define DW_ATCF_SUN_mop_bitfield 0x41 /* SUN */ -#define DW_ATCF_SUN_mop_spill 0x42 /* SUN */ -#define DW_ATCF_SUN_mop_scopy 0x43 /* SUN */ -#define DW_ATCF_SUN_func_start 0x44 /* SUN */ -#define DW_ATCF_SUN_end_ctors 0x45 /* SUN */ -#define DW_ATCF_SUN_branch_target 0x46 /* SUN */ -#define DW_ATCF_SUN_mop_stack_probe 0x47 /* SUN */ -#define DW_ATCF_SUN_func_epilog 0x48 /* SUN */ -#define DW_ATCF_hi_user 0xff /* SUN */ - -/* Accessibility code name. */ -#define DW_ACCESS_public 0x01 -#define DW_ACCESS_protected 0x02 -#define DW_ACCESS_private 0x03 - -/* Visibility code name. */ -#define DW_VIS_local 0x01 -#define DW_VIS_exported 0x02 -#define DW_VIS_qualified 0x03 - -/* Virtuality code name. */ -#define DW_VIRTUALITY_none 0x00 -#define DW_VIRTUALITY_virtual 0x01 -#define DW_VIRTUALITY_pure_virtual 0x02 - -#define DW_LANG_C89 0x0001 -#define DW_LANG_C 0x0002 -#define DW_LANG_Ada83 0x0003 -#define DW_LANG_C_plus_plus 0x0004 -#define DW_LANG_Cobol74 0x0005 -#define DW_LANG_Cobol85 0x0006 -#define DW_LANG_Fortran77 0x0007 -#define DW_LANG_Fortran90 0x0008 -#define DW_LANG_Pascal83 0x0009 -#define DW_LANG_Modula2 0x000a -#define DW_LANG_Java 0x000b /* DWARF3 */ -#define DW_LANG_C99 0x000c /* DWARF3 */ -#define DW_LANG_Ada95 0x000d /* DWARF3 */ -#define DW_LANG_Fortran95 0x000e /* DWARF3 */ -#define DW_LANG_PLI 0x000f /* DWARF3 */ -#define DW_LANG_ObjC 0x0010 /* DWARF3f */ -#define DW_LANG_ObjC_plus_plus 0x0011 /* DWARF3f */ -#define DW_LANG_UPC 0x0012 /* DWARF3f */ -#define DW_LANG_D 0x0013 /* DWARF3f */ -#define DW_LANG_Python 0x0014 /* DWARF4 */ -/* The following 2 are not yet formally approved October 2010, but - it seems extremely likely they will be approved as the committee - chair agrees these should be ok and no one on the committee - has objected. */ -#define DW_LANG_OpenCL 0x0015 /* Provisionally DWARF5 */ -#define DW_LANG_Go 0x0016 /* Provisionally DWARF5 */ -#define DW_LANG_lo_user 0x8000 -#define DW_LANG_Mips_Assembler 0x8001 /* MIPS */ -#define DW_LANG_Upc 0x8765 /* UPC, use - DW_LANG_UPC instead. */ -/* ALTIUM extension */ -#define DW_LANG_ALTIUM_Assembler 0x9101 /* ALTIUM */ - -/* Sun extensions */ -#define DW_LANG_SUN_Assembler 0x9001 /* SUN */ - -#define DW_LANG_hi_user 0xffff - -/* Identifier case name. */ -#define DW_ID_case_sensitive 0x00 -#define DW_ID_up_case 0x01 -#define DW_ID_down_case 0x02 -#define DW_ID_case_insensitive 0x03 - -/* Calling Convention Name. */ -#define DW_CC_normal 0x01 -#define DW_CC_program 0x02 -#define DW_CC_nocall 0x03 -#define DW_CC_lo_user 0x40 - -/* ALTIUM extensions. */ -/* Function is an interrupt handler, return address on system stack. */ -#define DW_CC_ALTIUM_interrupt 0x65 /* ALTIUM*/ - -/* Near function model, return address on system stack. */ -#define DW_CC_ALTIUM_near_system_stack 0x66 /*ALTIUM */ - -/* Near function model, return address on user stack. */ -#define DW_CC_ALTIUM_near_user_stack 0x67 /* ALTIUM */ - -/* Huge function model, return address on user stack. */ -#define DW_CC_ALTIUM_huge_user_stack 0x68 /* ALTIUM */ - - -#define DW_CC_hi_user 0xff - -/* Inline Code Name. */ -#define DW_INL_not_inlined 0x00 -#define DW_INL_inlined 0x01 -#define DW_INL_declared_not_inlined 0x02 -#define DW_INL_declared_inlined 0x03 - -/* Ordering Name. */ -#define DW_ORD_row_major 0x00 -#define DW_ORD_col_major 0x01 - -/* Discriminant Descriptor Name. */ -#define DW_DSC_label 0x00 -#define DW_DSC_range 0x01 - -/* Line number standard opcode name. */ -#define DW_LNS_copy 0x01 -#define DW_LNS_advance_pc 0x02 -#define DW_LNS_advance_line 0x03 -#define DW_LNS_set_file 0x04 -#define DW_LNS_set_column 0x05 -#define DW_LNS_negate_stmt 0x06 -#define DW_LNS_set_basic_block 0x07 -#define DW_LNS_const_add_pc 0x08 -#define DW_LNS_fixed_advance_pc 0x09 -#define DW_LNS_set_prologue_end 0x0a /* DWARF3 */ -#define DW_LNS_set_epilogue_begin 0x0b /* DWARF3 */ -#define DW_LNS_set_isa 0x0c /* DWARF3 */ - -/* Line number extended opcode name. */ -#define DW_LNE_end_sequence 0x01 -#define DW_LNE_set_address 0x02 -#define DW_LNE_define_file 0x03 -#define DW_LNE_set_discriminator 0x04 /* DWARF4 */ - -/* HP extensions. */ -#define DW_LNE_HP_negate_is_UV_update 0x11 /* 17 HP */ -#define DW_LNE_HP_push_context 0x12 /* 18 HP */ -#define DW_LNE_HP_pop_context 0x13 /* 19 HP */ -#define DW_LNE_HP_set_file_line_column 0x14 /* 20 HP */ -#define DW_LNE_HP_set_routine_name 0x15 /* 21 HP */ -#define DW_LNE_HP_set_sequence 0x16 /* 22 HP */ -#define DW_LNE_HP_negate_post_semantics 0x17 /* 23 HP */ -#define DW_LNE_HP_negate_function_exit 0x18 /* 24 HP */ -#define DW_LNE_HP_negate_front_end_logical 0x19 /* 25 HP */ -#define DW_LNE_HP_define_proc 0x20 /* 32 HP */ - -#define DW_LNE_lo_user 0x80 /* DWARF3 */ -#define DW_LNE_hi_user 0xff /* DWARF3 */ - -/* These are known values for DW_LNS_set_isa. */ -#define DW_ISA_UNKNOWN 0 -/* The following two are ARM specific. */ -#define DW_ISA_ARM_thumb 1 /* ARM ISA */ -#define DW_ISA_ARM_arm 2 /* ARM ISA */ - -/* Macro information. */ -#define DW_MACINFO_define 0x01 -#define DW_MACINFO_undef 0x02 -#define DW_MACINFO_start_file 0x03 -#define DW_MACINFO_end_file 0x04 -#define DW_MACINFO_vendor_ext 0xff - -/* CFA operator compaction (a space saving measure, see - the DWARF standard) means DW_CFA_extended and DW_CFA_nop - have the same value here. */ -#define DW_CFA_advance_loc 0x40 -#define DW_CFA_offset 0x80 -#define DW_CFA_restore 0xc0 -#define DW_CFA_extended 0 - -#define DW_CFA_nop 0x00 -#define DW_CFA_set_loc 0x01 -#define DW_CFA_advance_loc1 0x02 -#define DW_CFA_advance_loc2 0x03 -#define DW_CFA_advance_loc4 0x04 -#define DW_CFA_offset_extended 0x05 -#define DW_CFA_restore_extended 0x06 -#define DW_CFA_undefined 0x07 -#define DW_CFA_same_value 0x08 -#define DW_CFA_register 0x09 -#define DW_CFA_remember_state 0x0a -#define DW_CFA_restore_state 0x0b -#define DW_CFA_def_cfa 0x0c -#define DW_CFA_def_cfa_register 0x0d -#define DW_CFA_def_cfa_offset 0x0e -#define DW_CFA_def_cfa_expression 0x0f /* DWARF3 */ -#define DW_CFA_expression 0x10 /* DWARF3 */ -#define DW_CFA_offset_extended_sf 0x11 /* DWARF3 */ -#define DW_CFA_def_cfa_sf 0x12 /* DWARF3 */ -#define DW_CFA_def_cfa_offset_sf 0x13 /* DWARF3 */ -#define DW_CFA_val_offset 0x14 /* DWARF3f */ -#define DW_CFA_val_offset_sf 0x15 /* DWARF3f */ -#define DW_CFA_val_expression 0x16 /* DWARF3f */ - -#define DW_CFA_lo_user 0x1c -#define DW_CFA_low_user 0x1c /* Incorrect spelling, do not use. */ - -/* SGI/MIPS extension. */ -#define DW_CFA_MIPS_advance_loc8 0x1d /* MIPS */ - -/* GNU extensions. */ -#define DW_CFA_GNU_window_save 0x2d /* GNU */ -#define DW_CFA_GNU_args_size 0x2e /* GNU */ -#define DW_CFA_GNU_negative_offset_extended 0x2f /* GNU */ - -#define DW_CFA_high_user 0x3f - -/* GNU exception header encoding. See the Generic - Elf Specification of the Linux Standard Base (LSB). - http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html - The upper 4 bits indicate how the value is to be applied. - The lower 4 bits indicate the format of the data. -*/ -#define DW_EH_PE_absptr 0x00 /* GNU */ -#define DW_EH_PE_uleb128 0x01 /* GNU */ -#define DW_EH_PE_udata2 0x02 /* GNU */ -#define DW_EH_PE_udata4 0x03 /* GNU */ -#define DW_EH_PE_udata8 0x04 /* GNU */ -#define DW_EH_PE_sleb128 0x09 /* GNU */ -#define DW_EH_PE_sdata2 0x0A /* GNU */ -#define DW_EH_PE_sdata4 0x0B /* GNU */ -#define DW_EH_PE_sdata8 0x0C /* GNU */ - -#define DW_EH_PE_pcrel 0x10 /* GNU */ -#define DW_EH_PE_textrel 0x20 /* GNU */ -#define DW_EH_PE_datarel 0x30 /* GNU */ -#define DW_EH_PE_funcrel 0x40 /* GNU */ -#define DW_EH_PE_aligned 0x50 /* GNU */ - -#define DW_EH_PE_omit 0xff /* GNU. Means no value present. */ - - -/* Mapping from machine registers and pseudo-regs into the .debug_frame table. - DW_FRAME entries are machine specific. These describe - MIPS/SGI R3000, R4K, R4400 and all later MIPS/SGI IRIX machines. - They describe a mapping from hardware register number to - the number used in the table to identify that register. - - The CFA (Canonical Frame Address) described in DWARF is called - the Virtual Frame Pointer on MIPS/SGI machines. - - The DW_FRAME* names here are MIPS/SGI specfic. - Libdwarf interfaces defined in 2008 make the - frame definitions - here (and the fixed table sizes they imply) obsolete. - They are left here for compatibility. -*/ -/* Default column used for CFA in the libdwarf reader client. - Assumes reg 0 never appears as - a register in DWARF information. Usable for MIPS, - but never a good idea, really. */ -#define DW_FRAME_CFA_COL 0 - -#define DW_FRAME_REG1 1 /* integer reg 1 */ -#define DW_FRAME_REG2 2 /* integer reg 2 */ -#define DW_FRAME_REG3 3 /* integer reg 3 */ -#define DW_FRAME_REG4 4 /* integer reg 4 */ -#define DW_FRAME_REG5 5 /* integer reg 5 */ -#define DW_FRAME_REG6 6 /* integer reg 6 */ -#define DW_FRAME_REG7 7 /* integer reg 7 */ -#define DW_FRAME_REG8 8 /* integer reg 8 */ -#define DW_FRAME_REG9 9 /* integer reg 9 */ -#define DW_FRAME_REG10 10 /* integer reg 10 */ -#define DW_FRAME_REG11 11 /* integer reg 11 */ -#define DW_FRAME_REG12 12 /* integer reg 12 */ -#define DW_FRAME_REG13 13 /* integer reg 13 */ -#define DW_FRAME_REG14 14 /* integer reg 14 */ -#define DW_FRAME_REG15 15 /* integer reg 15 */ -#define DW_FRAME_REG16 16 /* integer reg 16 */ -#define DW_FRAME_REG17 17 /* integer reg 17 */ -#define DW_FRAME_REG18 18 /* integer reg 18 */ -#define DW_FRAME_REG19 19 /* integer reg 19 */ -#define DW_FRAME_REG20 20 /* integer reg 20 */ -#define DW_FRAME_REG21 21 /* integer reg 21 */ -#define DW_FRAME_REG22 22 /* integer reg 22 */ -#define DW_FRAME_REG23 23 /* integer reg 23 */ -#define DW_FRAME_REG24 24 /* integer reg 24 */ -#define DW_FRAME_REG25 25 /* integer reg 25 */ -#define DW_FRAME_REG26 26 /* integer reg 26 */ -#define DW_FRAME_REG27 27 /* integer reg 27 */ -#define DW_FRAME_REG28 28 /* integer reg 28 */ -#define DW_FRAME_REG29 29 /* integer reg 29 */ -#define DW_FRAME_REG30 30 /* integer reg 30 */ -#define DW_FRAME_REG31 31 /* integer reg 31, aka ra */ - - /* MIPS1, 2 have only some of these 64-bit registers. - ** MIPS1 save/restore takes 2 instructions per 64-bit reg, and - ** in that case, the register is considered stored after the second - ** swc1. - */ -#define DW_FRAME_FREG0 32 /* 64-bit floating point reg 0 */ -#define DW_FRAME_FREG1 33 /* 64-bit floating point reg 1 */ -#define DW_FRAME_FREG2 34 /* 64-bit floating point reg 2 */ -#define DW_FRAME_FREG3 35 /* 64-bit floating point reg 3 */ -#define DW_FRAME_FREG4 36 /* 64-bit floating point reg 4 */ -#define DW_FRAME_FREG5 37 /* 64-bit floating point reg 5 */ -#define DW_FRAME_FREG6 38 /* 64-bit floating point reg 6 */ -#define DW_FRAME_FREG7 39 /* 64-bit floating point reg 7 */ -#define DW_FRAME_FREG8 40 /* 64-bit floating point reg 8 */ -#define DW_FRAME_FREG9 41 /* 64-bit floating point reg 9 */ -#define DW_FRAME_FREG10 42 /* 64-bit floating point reg 10 */ -#define DW_FRAME_FREG11 43 /* 64-bit floating point reg 11 */ -#define DW_FRAME_FREG12 44 /* 64-bit floating point reg 12 */ -#define DW_FRAME_FREG13 45 /* 64-bit floating point reg 13 */ -#define DW_FRAME_FREG14 46 /* 64-bit floating point reg 14 */ -#define DW_FRAME_FREG15 47 /* 64-bit floating point reg 15 */ -#define DW_FRAME_FREG16 48 /* 64-bit floating point reg 16 */ -#define DW_FRAME_FREG17 49 /* 64-bit floating point reg 17 */ -#define DW_FRAME_FREG18 50 /* 64-bit floating point reg 18 */ -#define DW_FRAME_FREG19 51 /* 64-bit floating point reg 19 */ -#define DW_FRAME_FREG20 52 /* 64-bit floating point reg 20 */ -#define DW_FRAME_FREG21 53 /* 64-bit floating point reg 21 */ -#define DW_FRAME_FREG22 54 /* 64-bit floating point reg 22 */ -#define DW_FRAME_FREG23 55 /* 64-bit floating point reg 23 */ -#define DW_FRAME_FREG24 56 /* 64-bit floating point reg 24 */ -#define DW_FRAME_FREG25 57 /* 64-bit floating point reg 25 */ -#define DW_FRAME_FREG26 58 /* 64-bit floating point reg 26 */ -#define DW_FRAME_FREG27 59 /* 64-bit floating point reg 27 */ -#define DW_FRAME_FREG28 60 /* 64-bit floating point reg 28 */ -#define DW_FRAME_FREG29 61 /* 64-bit floating point reg 29 */ -#define DW_FRAME_FREG30 62 /* 64-bit floating point reg 30 */ -#define DW_FRAME_FREG31 63 /* 64-bit floating point reg 31 */ - -/* ***IMPORTANT NOTE, TARGET DEPENDENCY **** - The following 4 #defines are dependent on - the target cpu(s) that you apply libdwarf to. - Ensure that DW_FRAME_UNDEFINED_VAL and DW_FRAME_SAME_VAL - do not conflict with the range [0-DW_FRAME_STATIC_LINK]. - The value 63 works for MIPS cpus at least up to the R16000. - - For a cpu with more than 63 real registers - DW_FRAME_HIGHEST_NORMAL_REGISTER - must be increased for things to work properly! - Also ensure that DW_FRAME_UNDEFINED_VAL DW_FRAME_SAME_VAL - are not in the range [0-DW_FRAME_STATIC_LINK] - - Having DW_FRAME_HIGHEST_NORMAL_REGISTER be higher than - is strictly needed is safe. - -*/ - -#ifndef DW_FRAME_HIGHEST_NORMAL_REGISTER -#define DW_FRAME_HIGHEST_NORMAL_REGISTER 63 -#endif -/* This is the number of columns in the Frame Table. - This constant should - be kept in sync with DW_REG_TABLE_SIZE defined in libdwarf.h - It must also be large enough to be beyond the highest - compiler-defined-register (meaning DW_FRAME_RA_COL DW_FRAME_STATIC_LINK - in the MIPS/IRIX case */ -#ifndef DW_FRAME_LAST_REG_NUM -#define DW_FRAME_LAST_REG_NUM (DW_FRAME_HIGHEST_NORMAL_REGISTER + 3) -#endif - - -/* Column recording ra (return address from a function call). - This is common to many architectures, but as a 'simple register' - is not necessarily adequate for all architectures. - For MIPS/IRIX this register number is actually recorded on disk - in the .debug_frame section. - */ -#define DW_FRAME_RA_COL (DW_FRAME_HIGHEST_NORMAL_REGISTER + 1) - -/* Column recording static link applicable to up-level - addressing, as in IRIX mp code, pascal, etc. - This is common to many architectures but - is not necessarily adequate for all architectures. - For MIPS/IRIX this register number is actually recorded on disk - in the .debug_frame section. -*/ -#define DW_FRAME_STATIC_LINK (DW_FRAME_HIGHEST_NORMAL_REGISTER + 2) - - - -/* - DW_FRAME_UNDEFINED_VAL and DW_FRAME_SAME_VAL are - never on disk, just generated by libdwarf. See libdwarf.h - for their values. -*/ - - - -#define DW_CHILDREN_no 0x00 -#define DW_CHILDREN_yes 0x01 - -#define DW_ADDR_none 0 - -#ifdef __cplusplus -} -#endif -#endif /* __DWARF_H */ diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_abbrev.c b/usr/src/tools/ctf/dwarf/common/dwarf_abbrev.c deleted file mode 100644 index c2ae361f33..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_abbrev.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - - Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the above address. -*/ - - - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include "dwarf_abbrev.h" - -int -dwarf_get_abbrev(Dwarf_Debug dbg, - Dwarf_Unsigned offset, - Dwarf_Abbrev * returned_abbrev, - Dwarf_Unsigned * length, - Dwarf_Unsigned * abbr_count, Dwarf_Error * error) -{ - Dwarf_Small *abbrev_ptr = 0; - Dwarf_Small *abbrev_section_end = 0; - Dwarf_Half attr = 0; - Dwarf_Half attr_form = 0; - Dwarf_Abbrev ret_abbrev = 0; - Dwarf_Unsigned labbr_count = 0; - Dwarf_Unsigned utmp = 0; - - - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - if (dbg->de_debug_abbrev.dss_data == 0) { - /* Loads abbrev section (and .debug_info as we do those - together). */ - int res = _dwarf_load_debug_info(dbg, error); - - if (res != DW_DLV_OK) { - return res; - } - } - - if (offset >= dbg->de_debug_abbrev.dss_size) { - return (DW_DLV_NO_ENTRY); - } - - - ret_abbrev = (Dwarf_Abbrev) _dwarf_get_alloc(dbg, DW_DLA_ABBREV, 1); - if (ret_abbrev == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - ret_abbrev->ab_dbg = dbg; - if (returned_abbrev == 0 || abbr_count == 0) { - dwarf_dealloc(dbg, ret_abbrev, DW_DLA_ABBREV); - _dwarf_error(dbg, error, DW_DLE_DWARF_ABBREV_NULL); - return (DW_DLV_ERROR); - } - - - *abbr_count = 0; - if (length != NULL) - *length = 1; - - abbrev_ptr = dbg->de_debug_abbrev.dss_data + offset; - abbrev_section_end = - dbg->de_debug_abbrev.dss_data + dbg->de_debug_abbrev.dss_size; - - DECODE_LEB128_UWORD(abbrev_ptr, utmp); - ret_abbrev->ab_code = (Dwarf_Word) utmp; - if (ret_abbrev->ab_code == 0) { - *returned_abbrev = ret_abbrev; - *abbr_count = 0; - if (length) { - *length = 1; - } - return (DW_DLV_OK); - } - - DECODE_LEB128_UWORD(abbrev_ptr, utmp); - ret_abbrev->ab_tag = utmp; - ret_abbrev->ab_has_child = *(abbrev_ptr++); - ret_abbrev->ab_abbrev_ptr = abbrev_ptr; - - do { - Dwarf_Unsigned utmp2; - - DECODE_LEB128_UWORD(abbrev_ptr, utmp2); - attr = (Dwarf_Half) utmp2; - DECODE_LEB128_UWORD(abbrev_ptr, utmp2); - attr_form = (Dwarf_Half) utmp2; - - if (attr != 0) - (labbr_count)++; - - } while (abbrev_ptr < abbrev_section_end && - (attr != 0 || attr_form != 0)); - - if (abbrev_ptr > abbrev_section_end) { - dwarf_dealloc(dbg, ret_abbrev, DW_DLA_ABBREV); - _dwarf_error(dbg, error, DW_DLE_ABBREV_DECODE_ERROR); - return (DW_DLV_ERROR); - } - - if (length != NULL) - *length = abbrev_ptr - dbg->de_debug_abbrev.dss_data - offset; - - *returned_abbrev = ret_abbrev; - *abbr_count = labbr_count; - return (DW_DLV_OK); -} - -int -dwarf_get_abbrev_code(Dwarf_Abbrev abbrev, - Dwarf_Unsigned * returned_code, - Dwarf_Error * error) -{ - if (abbrev == NULL) { - _dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL); - return (DW_DLV_ERROR); - } - - *returned_code = abbrev->ab_code; - return (DW_DLV_OK); -} - -/* DWARF defines DW_TAG_hi_user as 0xffff so no tag should be - over 16 bits. */ -int -dwarf_get_abbrev_tag(Dwarf_Abbrev abbrev, - Dwarf_Half * returned_tag, Dwarf_Error * error) -{ - if (abbrev == NULL) { - _dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL); - return (DW_DLV_ERROR); - } - - *returned_tag = abbrev->ab_tag; - return (DW_DLV_OK); -} - - -int -dwarf_get_abbrev_children_flag(Dwarf_Abbrev abbrev, - Dwarf_Signed * returned_flag, - Dwarf_Error * error) -{ - if (abbrev == NULL) { - _dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL); - return (DW_DLV_ERROR); - } - - *returned_flag = abbrev->ab_has_child; - return (DW_DLV_OK); -} - - -int -dwarf_get_abbrev_entry(Dwarf_Abbrev abbrev, - Dwarf_Signed index, - Dwarf_Half * returned_attr_num, - Dwarf_Signed * form, - Dwarf_Off * offset, Dwarf_Error * error) -{ - Dwarf_Byte_Ptr abbrev_ptr = 0; - Dwarf_Byte_Ptr abbrev_end = 0; - Dwarf_Byte_Ptr mark_abbrev_ptr = 0; - Dwarf_Half attr = 0; - Dwarf_Half attr_form = 0; - - if (index < 0) - return (DW_DLV_NO_ENTRY); - - if (abbrev == NULL) { - _dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL); - return (DW_DLV_ERROR); - } - - if (abbrev->ab_code == 0) { - return (DW_DLV_NO_ENTRY); - } - - if (abbrev->ab_dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - - abbrev_ptr = abbrev->ab_abbrev_ptr; - abbrev_end = - abbrev->ab_dbg->de_debug_abbrev.dss_data + - abbrev->ab_dbg->de_debug_abbrev.dss_size; - - for (attr = 1, attr_form = 1; - index >= 0 && abbrev_ptr < abbrev_end && (attr != 0 || - attr_form != 0); - index--) { - Dwarf_Unsigned utmp4; - - mark_abbrev_ptr = abbrev_ptr; - DECODE_LEB128_UWORD(abbrev_ptr, utmp4); - attr = (Dwarf_Half) utmp4; - DECODE_LEB128_UWORD(abbrev_ptr, utmp4); - attr_form = (Dwarf_Half) utmp4; - } - - if (abbrev_ptr >= abbrev_end) { - _dwarf_error(abbrev->ab_dbg, error, DW_DLE_ABBREV_DECODE_ERROR); - return (DW_DLV_ERROR); - } - - if (index >= 0) { - return (DW_DLV_NO_ENTRY); - } - - if (form != NULL) - *form = attr_form; - if (offset != NULL) - *offset = mark_abbrev_ptr - abbrev->ab_dbg->de_debug_abbrev.dss_data; - - *returned_attr_num = (attr); - return DW_DLV_OK; -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_abbrev.h b/usr/src/tools/ctf/dwarf/common/dwarf_abbrev.h deleted file mode 100644 index b525924c83..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_abbrev.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - - Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2008-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - - -/* In a given CU, one of these is (eventually) set up - for every abbreviation we need to find (and for all. - those ealier in the abbreviations for that CU). - So we don't want elements needlessly big. -*/ -struct Dwarf_Abbrev_s { - /* No TAG should exceed DW_TAG_hi_user, 0xffff, but - we do allow a larger value here. */ - Dwarf_Word ab_tag; - /* Abbreviations are numbered (normally sequentially from - 1 and so 16 bits is not enough! */ - Dwarf_Word ab_code; - Dwarf_Small ab_has_child; - Dwarf_Byte_Ptr ab_abbrev_ptr; - Dwarf_Debug ab_dbg; -}; diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_addr_finder.c b/usr/src/tools/ctf/dwarf/common/dwarf_addr_finder.c deleted file mode 100644 index 2fadefc1ea..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_addr_finder.c +++ /dev/null @@ -1,685 +0,0 @@ -/* - - Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* This code used by SGI-IRIX rqs processing, not needed by - any other system or application. -*/ - -#include "config.h" -#include "libdwarfdefs.h" -#ifdef HAVE_ELF_H -#include -#endif -#include -#include -#include "dwarf_base_types.h" -#include "dwarf_alloc.h" -#include "dwarf_opaque.h" -#include "dwarf_arange.h" -#include "dwarf_line.h" -#include "dwarf_frame.h" -#include -#include "dwarf_error.h" - -typedef unsigned long long ull; - -static int do_this_die_and_dealloc(Dwarf_Debug dbg, Dwarf_Die die, - int *errval); -static int - handle_debug_info(Dwarf_Debug dbg, int *errval); -static int - handle_debug_frame(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func, int *errval); -static int - handle_debug_aranges(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func, int *errval); -static int - handle_debug_line(Dwarf_Debug dbg, Dwarf_Die cu_die, Dwarf_addr_callback_func cb_func, int *errval); -static int - handle_debug_loc(void); - - -static Dwarf_addr_callback_func send_addr_note; - -int -_dwarf_addr_finder(dwarf_elf_handle elf_file_ptr, - Dwarf_addr_callback_func cb_func, int *dwerr) -{ - - Dwarf_Error err = 0; - Dwarf_Debug dbg = 0; - int res = 0; - int errval = 0; - int sections_found = 0; - - res = dwarf_elf_init(elf_file_ptr, DW_DLC_READ, /* errhand */ 0, - /* errarg */ 0, &dbg, &err); - if (res == DW_DLV_ERROR) { - int errv = (int) dwarf_errno(err); - - return errv; - } - if (res == DW_DLV_NO_ENTRY) { - return res; - } - - send_addr_note = cb_func; - - res = handle_debug_info(dbg, &errval); - switch (res) { - case DW_DLV_OK: - ++sections_found; - break; - case DW_DLV_NO_ENTRY: - - break; - default: - case DW_DLV_ERROR: - dwarf_finish(dbg, &err); - *dwerr = errval; - return res; - } - - res = handle_debug_aranges(dbg, cb_func, &errval); - switch (res) { - case DW_DLV_OK: - ++sections_found; - break; - case DW_DLV_NO_ENTRY: - break; - default: - case DW_DLV_ERROR: - dwarf_finish(dbg, &err); - *dwerr = errval; - return res; - } - res = handle_debug_frame(dbg, cb_func, &errval); - switch (res) { - case DW_DLV_OK: - ++sections_found; - break; - case DW_DLV_NO_ENTRY: - break; - default: - case DW_DLV_ERROR: - dwarf_finish(dbg, &err); - *dwerr = errval; - return res; - } - - res = handle_debug_loc(); /* does nothing */ - switch (res) { - case DW_DLV_OK: - ++sections_found; - break; - case DW_DLV_NO_ENTRY: - break; - default: - case DW_DLV_ERROR: - /* IMPOSSIBLE : handle_debug_loc cannot return this */ - dwarf_finish(dbg, &err); - *dwerr = errval; - return res; - } - - - - *dwerr = 0; - res = dwarf_finish(dbg, &err); - if (res == DW_DLV_ERROR) { - *dwerr = (int) dwarf_errno(err); - return DW_DLV_ERROR; - } - if (sections_found == 0) { - return DW_DLV_NO_ENTRY; - } - return DW_DLV_OK; - -} - -/* - Return DW_DLV_OK, ERROR, or NO_ENTRY. -*/ -static int -handle_debug_info(Dwarf_Debug dbg, int *errval) -{ - Dwarf_Unsigned nxtoff = 1; - Dwarf_Unsigned hdr_length; - Dwarf_Half version_stamp; - Dwarf_Unsigned abbrev_offset; - Dwarf_Half addr_size; - Dwarf_Error err; - int terminate_now = 0; - int res = 0; - Dwarf_Die sibdie; - int sibres; - int nres = DW_DLV_OK; - - - for (nres = dwarf_next_cu_header(dbg, &hdr_length, &version_stamp, - &abbrev_offset, - &addr_size, &nxtoff, &err); - terminate_now == 0 && nres == DW_DLV_OK; - nres = dwarf_next_cu_header(dbg, &hdr_length, &version_stamp, - &abbrev_offset, - &addr_size, &nxtoff, &err) - ) { - - Dwarf_Die curdie = 0; - - /* try to get the compilation unit die */ - sibres = dwarf_siblingof(dbg, curdie, &sibdie, &err); - if (sibres == DW_DLV_OK) { - res = do_this_die_and_dealloc(dbg, sibdie, errval); - switch (res) { - case DW_DLV_OK: - break; - case DW_DLV_NO_ENTRY: - break; - default: - case DW_DLV_ERROR: - return DW_DLV_ERROR; - } - } else if (sibres == DW_DLV_ERROR) { - *errval = (int) dwarf_errno(err); - return DW_DLV_ERROR; - } else { - /* NO ENTRY! */ - /* impossible? */ - } - - } - if (nres == DW_DLV_ERROR) { - int localerr = (int) dwarf_errno(err); - - *errval = localerr; - return DW_DLV_ERROR; - } - return DW_DLV_OK; -} - -static int - might_have_addr[] = { - DW_AT_high_pc, - DW_AT_low_pc, -}; -static int - might_have_locdesc[] = { - DW_AT_segment, - DW_AT_return_addr, - DW_AT_frame_base, - DW_AT_static_link, - DW_AT_data_member_location, - DW_AT_string_length, - DW_AT_location, - DW_AT_use_location, - DW_AT_vtable_elem_location, -}; - -/* - Return DW_DLV_OK if handling this went ok. -*/ -static int -handle_attr_addr(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attrnum, - Dwarf_Error * perr) -{ - int res = DW_DLV_OK; - Dwarf_Off offset; - Dwarf_Addr addr; - Dwarf_Half form; - int ares; - - Dwarf_Attribute attr; - - ares = dwarf_attr(die, attrnum, &attr, perr); - if (ares == DW_DLV_OK) { - int formres = dwarf_whatform(attr, &form, perr); - - switch (formres) { - case DW_DLV_OK: - break; - case DW_DLV_ERROR: - case DW_DLV_NO_ENTRY: /* impossible. */ - return formres; - - } - - switch (form) { - case DW_FORM_ref_addr: - case DW_FORM_addr: - res = dwarf_attr_offset(die, attr, &offset, perr); - if (res == DW_DLV_OK) { - ares = dwarf_formaddr(attr, &addr, perr); - if (ares == DW_DLV_OK) { - send_addr_note(DW_SECTION_INFO, offset, addr); - } else if (ares == DW_DLV_ERROR) { - return ares; - } /* no entry: ok. */ - } else { - res = DW_DLV_ERROR; /* NO_ENTRY is impossible. */ - } - break; - - default: - /* surprising! An error? */ - - ; /* do nothing */ - } - dwarf_dealloc(dbg, attr, DW_DLA_ATTR); - - } else { - res = ares; - } - return res; -} - -/* - Return DW_DLV_OK if handling this went ok. -*/ -static int -handle_attr_locdesc(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attrnum, - Dwarf_Error * perr) -{ - int retval = DW_DLV_OK; - Dwarf_Attribute attr; - Dwarf_Locdesc *llbuf; - Dwarf_Signed i; - Dwarf_Off offset; - Dwarf_Loc *locp; - unsigned int entindx; - int res; - int ares; - - - ares = dwarf_attr(die, attrnum, &attr, perr); - if (ares == DW_DLV_OK) { - Dwarf_Half form; - int fres = dwarf_whatform(attr, &form, perr); - - if (fres == DW_DLV_OK) { - switch (form) { - case DW_FORM_block1: - case DW_FORM_block2: - case DW_FORM_block4: - /* must be location description */ - res = dwarf_attr_offset(die, attr, &offset, perr); - llbuf = 0; - if (res == DW_DLV_OK) { - Dwarf_Signed count; - int lres = dwarf_loclist(attr, &llbuf, &count, perr); - if (lres != DW_DLV_OK) { - return lres; - } - if (count != 1) { - /* this cannot happen! */ - /* perr? */ - _dwarf_error(dbg, perr, - DW_DLE_LOCDESC_COUNT_WRONG); - retval = DW_DLV_ERROR; - return retval; - } - for (i = 0; i < count; ++i) { - unsigned int ents = llbuf[i].ld_cents; - - locp = llbuf[i].ld_s; - for (entindx = 0; entindx < ents; entindx++) { - Dwarf_Loc *llocp; - - llocp = locp + entindx; - if (llocp->lr_atom == DW_OP_addr) { - send_addr_note(DW_SECTION_INFO, offset + - llocp->lr_offset + 1 - /* The offset is the - offset of the atom, - ** and we know the - addr is 1 past it. */ - , llocp->lr_number); - } - } - } - - - if (count > 0) { - for (i = 0; i < count; ++i) { - dwarf_dealloc(dbg, llbuf[i].ld_s, - DW_DLA_LOC_BLOCK); - } - dwarf_dealloc(dbg, llbuf, DW_DLA_LOCDESC); - } - } else { - retval = res; - } - break; - - default: - /* must be a const offset in debug_loc */ - ; /* do nothing */ - } - dwarf_dealloc(dbg, attr, DW_DLA_ATTR); - } /* else error or no entry */ - retval = fres; - } else { - retval = ares; - } - return retval; -} - -/* - Return DW_DLV_OK, or DW_DLV_ERROR - - Handle the addrs in a single die. -*/ -static int -process_this_die_attrs(Dwarf_Debug dbg, Dwarf_Die newdie, int *errval) -{ - Dwarf_Error err; - Dwarf_Half i; - Dwarf_Half newattrnum; - int res; - int tres; - Dwarf_Half ltag; - - Dwarf_Off doff; - int doffres = dwarf_dieoffset(newdie, &doff, &err); - - if (doffres != DW_DLV_OK) { - if (doffres == DW_DLV_ERROR) { - *errval = (int) dwarf_errno(err); - } - return doffres; - } - tres = dwarf_tag(newdie, <ag, &err); - if (tres != DW_DLV_OK) { - return tres; - } - if (DW_TAG_compile_unit == ltag) { - /* because of the way the dwarf_line code works, we do lines - only per compile unit. This may turn out to be wrong if - we have lines left unconnected to a CU. of course such - lines will not, at present, be used by gnome. This is - not ideal as coded due to the dwarf_line.c issue. */ - int lres = handle_debug_line(dbg, newdie, send_addr_note, errval); - if (lres == DW_DLV_ERROR) { - return lres; - } - } - - for (i = 0; i < sizeof(might_have_addr) / sizeof(int); i++) { - int resattr; - Dwarf_Bool hasattr; - - newattrnum = might_have_addr[i]; - err = 0; - resattr = dwarf_hasattr(newdie, newattrnum, &hasattr, &err); - if (DW_DLV_OK == resattr) { - if (hasattr) { - res = handle_attr_addr(dbg, newdie, newattrnum, &err); - if (res != DW_DLV_OK) { - *errval = (int) dwarf_errno(err); - return DW_DLV_ERROR; - } - } - } else { - if (resattr == DW_DLV_ERROR) { - *errval = (int) dwarf_errno(err); - return resattr; - } - } - } - for (i = 0; i < sizeof(might_have_locdesc) / sizeof(int); i++) { - int resattr; - Dwarf_Bool hasattr; - - newattrnum = might_have_locdesc[i]; - err = 0; - resattr = dwarf_hasattr(newdie, newattrnum, &hasattr, &err); - if (DW_DLV_OK == resattr) { - if (hasattr) { - res = - handle_attr_locdesc(dbg, newdie, newattrnum, &err); - if (res != DW_DLV_OK) { - *errval = (int) dwarf_errno(err); - return DW_DLV_ERROR; - } - } - } else { - if (resattr == DW_DLV_ERROR) { - *errval = (int) dwarf_errno(err); - return resattr; - } - } - } - - return DW_DLV_OK; -} - -/* - Handle siblings as a list, - Do children by recursing. - Effectively this is walking the tree preorder. - - This dealloc's any die passed to it, so the - caller should not do that dealloc. - It seems more logical to have the one causing - the alloc to do the dealloc, but that way this - routine became a mess. - -*/ -static int -do_this_die_and_dealloc(Dwarf_Debug dbg, Dwarf_Die die, int *errval) -{ - - Dwarf_Die prevdie = 0; - Dwarf_Die newdie = die; - Dwarf_Error err = 0; - int res = 0; - int sibres = DW_DLV_OK; - int tres = DW_DLV_OK; - Dwarf_Die sibdie; - - while (sibres == DW_DLV_OK) { - Dwarf_Die ch_die; - - - res = process_this_die_attrs(dbg, newdie, errval); - switch (res) { - case DW_DLV_OK: - break; - case DW_DLV_NO_ENTRY: - break; - default: - case DW_DLV_ERROR: - if (prevdie) { - dwarf_dealloc(dbg, prevdie, DW_DLA_DIE); - prevdie = 0; - } - return DW_DLV_ERROR; - } - - tres = dwarf_child(newdie, &ch_die, &err); - - if (tres == DW_DLV_OK) { - res = do_this_die_and_dealloc(dbg, ch_die, errval); - switch (res) { - case DW_DLV_OK: - break; - case DW_DLV_NO_ENTRY: - break; - default: - case DW_DLV_ERROR: - if (prevdie) { - dwarf_dealloc(dbg, prevdie, DW_DLA_DIE); - prevdie = 0; - } - return DW_DLV_ERROR; - } - } else if (tres == DW_DLV_ERROR) { - /* An error! */ - *errval = (int) dwarf_errno(err); - if (prevdie) { - dwarf_dealloc(dbg, prevdie, DW_DLA_DIE); - prevdie = 0; - } - dwarf_dealloc(dbg, err, DW_DLA_ERROR); - return DW_DLV_ERROR; - } /* else was NO ENTRY */ - prevdie = newdie; - sibdie = 0; - sibres = dwarf_siblingof(dbg, newdie, &sibdie, &err); - if (prevdie) { - dwarf_dealloc(dbg, prevdie, DW_DLA_DIE); - prevdie = 0; - } - newdie = sibdie; - - } - if (sibres == DW_DLV_NO_ENTRY) { - return DW_DLV_OK; - } - /* error. */ - *errval = (int) dwarf_errno(err); - if (prevdie) { - dwarf_dealloc(dbg, prevdie, DW_DLA_DIE); - prevdie = 0; - } - dwarf_dealloc(dbg, err, DW_DLA_ERROR); - return DW_DLV_ERROR; - -} - - -static int -handle_debug_frame(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func, - int *errval) -{ - int retval = DW_DLV_OK; - int res; - Dwarf_Error err; - Dwarf_Addr *addrlist; - Dwarf_Off *offsetlist; - Dwarf_Signed count; - int i; - - res = - _dwarf_frame_address_offsets(dbg, &addrlist, &offsetlist, - &count, &err); - if (res == DW_DLV_OK) { - for (i = 0; i < count; i++) { - cb_func(DW_SECTION_FRAME, offsetlist[i], addrlist[i]); - } - dwarf_dealloc(dbg, offsetlist, DW_DLA_ADDR); - dwarf_dealloc(dbg, addrlist, DW_DLA_ADDR); - } else if (res == DW_DLV_NO_ENTRY) { - retval = res; - } else { - *errval = (int) dwarf_errno(err); - retval = DW_DLV_ERROR; - } - return retval; - -} -static int -handle_debug_aranges(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func, - int *errval) -{ - int retval = DW_DLV_OK; - Dwarf_Error err; - Dwarf_Addr *aranges; - Dwarf_Signed count; - int indx; - Dwarf_Off *offsets; - - retval = - _dwarf_get_aranges_addr_offsets(dbg, &aranges, &offsets, &count, - &err); - if (retval == DW_DLV_OK) { - if (count == 0) { - retval = DW_DLV_NO_ENTRY; - } else { - for (indx = 0; indx < count; indx++) { - cb_func(DW_SECTION_ARANGES, offsets[indx], - aranges[indx]); - } - } - dwarf_dealloc(dbg, aranges, DW_DLA_ADDR); - dwarf_dealloc(dbg, offsets, DW_DLA_ADDR); - } else if (retval == DW_DLV_NO_ENTRY) { - ; /* do nothing */ - } else { - *errval = (int) dwarf_errno(err); - retval = DW_DLV_ERROR; - } - return retval; -} -static int -handle_debug_line(Dwarf_Debug dbg, Dwarf_Die cu_die, - Dwarf_addr_callback_func cb_func, int *errval) -{ - int retval = DW_DLV_OK; - int res; - Dwarf_Error err; - Dwarf_Addr *addrlist; - Dwarf_Off *offsetlist; - Dwarf_Unsigned count; - Dwarf_Unsigned i; - - res = - _dwarf_line_address_offsets(dbg, cu_die, &addrlist, &offsetlist, - &count, &err); - if (res == DW_DLV_OK) { - for (i = 0; i < count; i++) { - cb_func(DW_SECTION_LINE, offsetlist[i], addrlist[i]); - - } - dwarf_dealloc(dbg, offsetlist, DW_DLA_ADDR); - dwarf_dealloc(dbg, addrlist, DW_DLA_ADDR); - } else if (res == DW_DLV_NO_ENTRY) { - retval = res; - } else { - *errval = (int) dwarf_errno(err); - retval = DW_DLV_ERROR; - } - return retval; -} - -/* - We need to add support for this. Currently we do not - generate this section. - FIX! -*/ -static int -handle_debug_loc(void) -{ - int retval = DW_DLV_NO_ENTRY; - - return retval; -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_alloc.c b/usr/src/tools/ctf/dwarf/common/dwarf_alloc.c deleted file mode 100644 index ddb423e841..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_alloc.c +++ /dev/null @@ -1,1258 +0,0 @@ -/* - - Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the Crittenden Lane address. -*/ - - -#undef DEBUG - -#include "config.h" -#include "dwarf_incl.h" -#include - -#include -#include -#include "malloc_check.h" - -/* - These files are included to get the sizes - of structs to set the ah_bytes_one_struct field - of the Dwarf_Alloc_Hdr_s structs for each - allocation type. -*/ -#include "dwarf_line.h" -#include "dwarf_global.h" -#include "dwarf_arange.h" -#include "dwarf_abbrev.h" -#include "dwarf_die_deliv.h" -#include "dwarf_frame.h" -#include "dwarf_loc.h" -#include "dwarf_funcs.h" -#include "dwarf_types.h" -#include "dwarf_vars.h" -#include "dwarf_weaks.h" - - -static void _dwarf_free_special_error(Dwarf_Ptr space); - -#ifdef DWARF_SIMPLE_MALLOC -static void _dwarf_simple_malloc_add_to_list(Dwarf_Debug dbg, - Dwarf_Ptr addr, - unsigned long size, - short alloc_type); -static void _dwarf_simple_malloc_delete_from_list(Dwarf_Debug dbg, - Dwarf_Ptr space, - short alloc_type); -void _dwarf_simple_malloc_botch(int err); - -#endif /* DWARF_SIMPLE_MALLOC */ - - - - -/* - This macro adds the size of a pointer to the size of a - struct that is given to it. It rounds up the size to - be a multiple of the size of a pointer. This is done - so that every struct returned by _dwarf_get_alloc() - can be preceded by a pointer to the chunk it came from. - Before allocating, it checks if the size of struct is less than - the size of a pointer. If yes, it returns the size - of 2 pointers. The returned size should be at least - the size of 2 pointers, since the first points to the - chunk the struct was allocated from, and the second - is used to link the free list. - - We want DW_RESERVE to be at least the size of - a long long and at least the size of a pointer because - our struct has a long long and we want that aligned right. - Now Standard C defines long long as 8 bytes, so lets - make that standard. It will become unworkable when - long long or pointer grows beyound 8 bytes. - Unclear what to do with wierd requirements, like - 36 bit pointers. - - -*/ -#define DW_RESERVE 8 - -/* Round size up to the next multiple of DW_RESERVE bytes -*/ -#define ROUND_SIZE(inputsize) \ - (((inputsize) % (DW_RESERVE)) == 0 ? \ - (inputsize): \ - ((inputsize) + \ - (DW_RESERVE) - ((inputsize) % (DW_RESERVE)) )) - -#define ROUND_SIZE_WITH_POINTER(i_size) (ROUND_SIZE(i_size) + DW_RESERVE) - -/* SMALL_ALLOC is for trivia where allocation is a waste. - Things that should be removed, really. */ -#define SMALL_ALLOC 2 - -/* BASE_ALLOC is where a basic allocation makes sense, but 'not too large'. - No thorough evaluation of this value has been done, though - it was found wasteful of memory to have BASE_ALLOC be as large as - BIG_ALLOC. */ -#define BASE_ALLOC 64 - -/* BIG_ALLOC is where a larger-than-BASE_ALLOC - allocation makes sense, but still 'not too large'. - No thorough evaluation of this value has been done. */ -#define BIG_ALLOC 128 - -/* This translates into de_alloc_hdr index -** the 0,1,1 entries are special: they don't use the -** table values at all. -** Rearranging the DW_DLA values would break binary compatibility -** so that is not an option. -*/ -struct ial_s { - int ia_al_num; /* Index into de_alloc_hdr table. */ - - /* In bytes, one struct instance. This does not account for extra - space needed per block, but that (DW_RESERVE) will be added in - later where it is needed (DW_RESERVE space never added in here). - */ - int ia_struct_size; - - - /* Number of instances per alloc block. MUST be > 0. */ - int ia_base_count; - - int (*specialconstructor) (Dwarf_Debug, void *); - void (*specialdestructor) (void *); -}; - -static const -struct ial_s index_into_allocated[ALLOC_AREA_INDEX_TABLE_MAX] = { - {0, 1, 1, 0, 0}, /* none */ - {0, 1, 1, 0, 0}, /* 1 DW_DLA_STRING */ - {1, sizeof(Dwarf_Loc), BASE_ALLOC, 0, 0} - , /* 2 DW_DLA_LOC */ - {2, sizeof(Dwarf_Locdesc), BASE_ALLOC, 0, 0} - , /* 3 DW_DLA_LOCDESC */ - {0, 1, 1, 0, 0} - , /* not used *//* 4 DW_DLA_ELLIST */ - {0, 1, 1, 0, 0} - , /* not used *//* 5 DW_DLA_BOUNDS */ - {3, sizeof(Dwarf_Block), BASE_ALLOC, 0, 0} - , /* 6 DW_DLA_BLOCK */ - {0, 1, 1, 0, 0} - , /* the actual dwarf_debug structure *//* 7 DW_DLA_DEBUG */ - {4, sizeof(struct Dwarf_Die_s), BIG_ALLOC, 0, 0}, /* 8 DW_DLA_DIE - */ - {5, sizeof(struct Dwarf_Line_s), BIG_ALLOC, 0, 0}, /* 9 - DW_DLA_LINE */ - {6, sizeof(struct Dwarf_Attribute_s), BIG_ALLOC * 2, 0, 0}, - /* 10 DW_DLA_ATTR */ - {0, 1, 1, 0, 0}, /* not used *//* 11 DW_DLA_TYPE */ - {0, 1, 1, 0, 0}, /* not used *//* 12 DW_DLA_SUBSCR */ - {7, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0}, /* 13 - DW_DLA_GLOBAL - */ - {8, sizeof(struct Dwarf_Error_s), BASE_ALLOC, 0, 0}, /* 14 - DW_DLA_ERROR - */ - {0, 1, 1, 0, 0}, /* 15 DW_DLA_LIST */ - {0, 1, 1, 0, 0}, /* not used *//* 16 DW_DLA_LINEBUF */ - {9, sizeof(struct Dwarf_Arange_s), BASE_ALLOC, 0, 0}, /* 17 - DW_DLA_ARANGE - */ - {10, sizeof(struct Dwarf_Abbrev_s), BIG_ALLOC, 0, 0}, /* 18 - DW_DLA_ABBREV - */ - {11, sizeof(Dwarf_Frame_Op), BIG_ALLOC, 0, 0} - , /* 19 DW_DLA_FRAME_OP */ - {12, sizeof(struct Dwarf_Cie_s), BASE_ALLOC, 0, 0}, /* 20 - DW_DLA_CIE */ - {13, sizeof(struct Dwarf_Fde_s), BASE_ALLOC, 0, 0}, /* 21 DW_DLA_FDE */ - {0, 1, 1, 0, 0}, /* 22 DW_DLA_LOC_BLOCK */ - {0, 1, 1, 0, 0}, /* 23 DW_DLA_FRAME_BLOCK */ - {14, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0}, /* 24 DW_DLA_FUNC - UNUSED */ - {15, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0}, /* 25 - DW_DLA_TYPENAME - UNUSED */ - {16, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0}, /* 26 DW_DLA_VAR - UNUSED */ - {17, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0}, /* 27 DW_DLA_WEAK - UNUSED */ - {0, 1, 1, 0, 0}, /* 28 DW_DLA_ADDR */ - {0, 1,1,0,0 }, /* 29 DW_DLA_RANGES */ - - /* The following DW_DLA data types - are known only inside libdwarf. */ - - {18, sizeof(struct Dwarf_Abbrev_List_s), BIG_ALLOC, 0, 0}, - /* 30 DW_DLA_ABBREV_LIST */ - - {19, sizeof(struct Dwarf_Chain_s), BIG_ALLOC, 0, 0}, /* 31 DW_DLA_CHAIN */ - {20, sizeof(struct Dwarf_CU_Context_s), BASE_ALLOC, 0, 0}, - /* 32 DW_DLA_CU_CONTEXT */ - {21, sizeof(struct Dwarf_Frame_s), BASE_ALLOC, - _dwarf_frame_constructor, - _dwarf_frame_destructor}, /* 33 DW_DLA_FRAME */ - {22, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0}, - /* 34 DW_DLA_GLOBAL_CONTEXT */ - {23, sizeof(struct Dwarf_File_Entry_s), BASE_ALLOC, 0, 0}, /* 34 */ - /* 35 DW_DLA_FILE_ENTRY */ - {24, sizeof(struct Dwarf_Line_Context_s), BASE_ALLOC, 0, 0}, - /* 36 DW_DLA_LINE_CONTEXT */ - {25, sizeof(struct Dwarf_Loc_Chain_s), BASE_ALLOC, 0, 0}, /* 36 */ - /* 37 DW_DLA_LOC_CHAIN */ - - {26, sizeof(struct Dwarf_Hash_Table_s),BASE_ALLOC, 0, 0}, /* 37 */ - /* 38 DW_DLA_HASH_TABLE */ - -/* The following really use Global struct: used to be unique struct - per type, but now merged (11/99). The opaque types - are visible in the interface. The types for - DW_DLA_FUNC, - DW_DLA_TYPENAME, DW_DLA_VAR, DW_DLA_WEAK also use - the global types. - -*/ - {27, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0}, - /* 39 DW_DLA_FUNC_CONTEXT */ - {28, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0}, - /* 40 DW_DLA_TYPENAME_CONTEXT */ - {29, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0}, - /* 41 DW_DLA_VAR_CONTEXT */ - {30, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0}, - /* 42 DW_DLA_WEAK_CONTEXT */ - {31, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0}, - /* 43 DW_DLA_PUBTYPES_CONTEXT DWARF3 */ - - {0,1,1,0,0 }, - /* 44 DW_DLA_HASH_TABLE_ENTRY */ - - -}; - -#ifndef DWARF_SIMPLE_MALLOC - -/* - This function is given a pointer to the header - structure that is used to allocate 1 struct of - the type given by alloc_type. It first checks - if a struct is available in its free list. If - not, it checks if 1 is available in its blob, - which is a chunk of memory that is reserved for - its use. If not, it malloc's a chunk. The - initial part of it is used to store the end - address of the chunk, and also to keep track - of the number of free structs in that chunk. - This information is used for freeing the chunk - when all the structs in it are free. - - Assume all input arguments have been validated. - - This function can be used only to allocate 1 - struct of the given type. - - It returns a pointer to the struct that the - user can use. It returns NULL only when it - is out of free structs, and cannot malloc - any more. The struct returned is zero-ed. - - A pointer to the chunk that the struct belongs - to is stored in the bytes preceding the - returned address. Since this pointer it - never overwritten, when a struct is allocated - from the free_list this pointer does not - have to be written. In the 2 other cases, - where the struct is allocated from a new - chunk, or the blob, a pointer to the chunk - is written. -*/ -static Dwarf_Ptr -_dwarf_find_memory(Dwarf_Alloc_Hdr alloc_hdr) -{ - /* Pointer to the struct allocated. */ - Dwarf_Small *ret_mem = 0; - - /* Pointer to info about chunks allocated. */ - Dwarf_Alloc_Area alloc_area; - - /* Size of chunk malloc'ed when no free structs left. */ - Dwarf_Signed mem_block_size; - - /* Pointer to block malloc'ed. */ - Dwarf_Small *mem_block; - - /* - Check the alloc_area from which the last allocation was made - (most recent new block). If that is not successful, then search - the list of alloc_area's from alloc_header. */ - alloc_area = alloc_hdr->ah_last_alloc_area; - if (alloc_area == NULL || alloc_area->aa_free_structs_in_chunk == 0) - for (alloc_area = alloc_hdr->ah_alloc_area_head; - alloc_area != NULL; alloc_area = alloc_area->aa_next) { - - if (alloc_area->aa_free_structs_in_chunk > 0) { - break; /* found a free entry! */ - } - - } - - if (alloc_area != NULL) { - alloc_area->aa_free_structs_in_chunk--; - - if (alloc_area->aa_free_list != NULL) { - ret_mem = alloc_area->aa_free_list; - - /* - Update the free list. The initial part of the struct is - used to hold a pointer to the next struct on the free - list. In this way, the free list chain is maintained at - 0 memory cost. */ - alloc_area->aa_free_list = - ((Dwarf_Free_List) ret_mem)->fl_next; - } else if (alloc_area->aa_blob_start < alloc_area->aa_blob_end) { - ret_mem = alloc_area->aa_blob_start; - - /* - Store pointer to chunk this struct belongs to in the - first few bytes. Return pointer to bytes after this - pointer storage. */ - *(Dwarf_Alloc_Area *) ret_mem = alloc_area; - ret_mem += DW_RESERVE; - - alloc_area->aa_blob_start += alloc_hdr->ah_bytes_one_struct; - } else { - /* else fall thru , though it should be impossible to fall - thru. And represents a disastrous programming error if - we get here. */ -#ifdef DEBUG - fprintf(stderr, "libdwarf Internal error start %x end %x\n", - (int) alloc_area->aa_blob_start, - (int) alloc_area->aa_blob_end); -#endif - } - } - - /* New memory has to malloc'ed since there are no free structs. */ - if (ret_mem == 0) { - Dwarf_Word rounded_area_hdr_size; - - alloc_hdr->ah_chunks_allocated++; - - { /* this nonsense avoids a warning */ - /* CONSTCOND would be better */ - unsigned long v = sizeof(struct Dwarf_Alloc_Area_s); - - rounded_area_hdr_size = ROUND_SIZE(v); - } - - /* - Allocate memory to contain the required number of structs - and the Dwarf_Alloc_Area_s to control it. */ - mem_block_size = alloc_hdr->ah_bytes_malloc_per_chunk + - rounded_area_hdr_size; - - mem_block = malloc(mem_block_size); - if (mem_block == NULL) { - return (NULL); - } - - - /* - Attach the Dwarf_Alloc_Area_s struct to the list of chunks - malloc'ed for this struct type. Also initialize the fields - of the Dwarf_Alloc_Area_s. */ - alloc_area = (Dwarf_Alloc_Area) mem_block; - alloc_area->aa_prev = 0; - if (alloc_hdr->ah_alloc_area_head != NULL) { - alloc_hdr->ah_alloc_area_head->aa_prev = alloc_area; - } - alloc_area->aa_free_list = 0; - alloc_area->aa_next = alloc_hdr->ah_alloc_area_head; - alloc_hdr->ah_alloc_area_head = alloc_area; - - alloc_area->aa_alloc_hdr = alloc_hdr; - alloc_area->aa_free_structs_in_chunk = - (Dwarf_Sword) alloc_hdr->ah_structs_per_chunk - 1; - if (alloc_area->aa_free_structs_in_chunk < 1) { - /* If we get here, there is a disastrous programming error - somewhere. */ -#ifdef DEBUG - fprintf(stderr, - "libdwarf Internal error: free structs in chunk %d\n", - (int) alloc_area->aa_free_structs_in_chunk); -#endif - return NULL; - } - - /* - The struct returned begins immediately after the - Dwarf_Alloc_Area_s struct. */ - ret_mem = mem_block + rounded_area_hdr_size; - alloc_area->aa_blob_start = - ret_mem + alloc_hdr->ah_bytes_one_struct; - alloc_area->aa_blob_end = mem_block + mem_block_size; - - /* - Store pointer to chunk this struct belongs to in the first - few bytes. Return pointer to bytes after this pointer - storage. */ - *(Dwarf_Alloc_Area *) ret_mem = alloc_area; - ret_mem += DW_RESERVE; - } - - alloc_hdr->ah_last_alloc_area = alloc_area; - alloc_hdr->ah_struct_user_holds++; - memset(ret_mem, 0, alloc_hdr->ah_bytes_one_struct - DW_RESERVE); - return (ret_mem); -} - -#endif /* ndef DWARF_SIMPLE_MALLOC */ - -/* - This function returns a pointer to a region - of memory. For alloc_types that are not - strings or lists of pointers, only 1 struct - can be requested at a time. This is indicated - by an input count of 1. For strings, count - equals the length of the string it will - contain, i.e it the length of the string - plus 1 for the terminating null. For lists - of pointers, count is equal to the number of - pointers. For DW_DLA_FRAME_BLOCK, DW_DLA_RANGES, and - DW_DLA_LOC_BLOCK allocation types also, count - is the count of the number of structs needed. - - This function cannot be used to allocate a - Dwarf_Debug_s struct. - -*/ -Dwarf_Ptr -_dwarf_get_alloc(Dwarf_Debug dbg, - Dwarf_Small alloc_type, Dwarf_Unsigned count) -{ - Dwarf_Alloc_Hdr alloc_hdr; - - Dwarf_Ptr ret_mem; - - Dwarf_Signed size = 0; - unsigned int index; - unsigned int type = alloc_type; - - if (dbg == NULL) { - return (NULL); - } - - if (type >= ALLOC_AREA_INDEX_TABLE_MAX) { - /* internal error */ - return NULL; - } - index = index_into_allocated[type].ia_al_num; - /* zero also illegal but not tested for */ - - /* If the Dwarf_Debug is not fully set up, we will get index 0 for - any type and must do something. 'Not fully set up' can only - happen for DW_DLA_ERROR, I (davea) believe, and for that we call - special code here.. */ - - if (index == 0) { - if (alloc_type == DW_DLA_STRING) { - size = count; - } else if (alloc_type == DW_DLA_LIST) { - size = count * sizeof(Dwarf_Ptr); - } else if (alloc_type == DW_DLA_FRAME_BLOCK) { - size = count * sizeof(Dwarf_Frame_Op); - } else if (alloc_type == DW_DLA_LOC_BLOCK) { - size = count * sizeof(Dwarf_Loc); - } else if (alloc_type == DW_DLA_HASH_TABLE_ENTRY) { - size = count * sizeof(struct Dwarf_Hash_Table_Entry_s); - } else if (alloc_type == DW_DLA_ADDR) { - size = count * - (sizeof(Dwarf_Addr) > sizeof(Dwarf_Off) ? - sizeof(Dwarf_Addr) : sizeof(Dwarf_Off)); - } else if (alloc_type == DW_DLA_RANGES) { - size = count * sizeof(Dwarf_Ranges); - } else if (alloc_type == DW_DLA_ERROR) { - void *m = _dwarf_special_no_dbg_error_malloc(); - - dwarf_malloc_check_alloc_data(m, DW_DLA_ERROR); - return m; - - } else { - /* If we get here, there is a disastrous programming error - somewhere. */ -#ifdef DEBUG - fprintf(stderr, - "libdwarf Internal error: type %d unexpected\n", - (int) type); -#endif - } - } else { - alloc_hdr = &dbg->de_alloc_hdr[index]; - if (alloc_hdr->ah_bytes_one_struct > 0) { -#ifdef DWARF_SIMPLE_MALLOC - size = alloc_hdr->ah_bytes_one_struct; -#else - { - void *m = _dwarf_find_memory(alloc_hdr); - - dwarf_malloc_check_alloc_data(m, type); - if (index_into_allocated[type].specialconstructor) { - int res = - index_into_allocated[type]. - specialconstructor(dbg, m); - if (res != DW_DLV_OK) { - /* We leak what we allocated in - _dwarf_find_memory when constructor fails. */ - return NULL; - } - } - return m; - } -#endif - - } else { - /* Special case: should not really happen at all. */ - if (type == DW_DLA_ERROR) { - /* dwarf_init failure. Because dbg is incomplete we - won't use it to record the malloc. */ - void *m = _dwarf_special_no_dbg_error_malloc(); - - dwarf_malloc_check_alloc_data(m, DW_DLA_ERROR); - return m; - } else { - /* If we get here, there is a disastrous programming - error somewhere. */ -#ifdef DWARF_SIMPLE_MALLOC - _dwarf_simple_malloc_botch(3); -#endif -#ifdef DEBUG - fprintf(stderr, - "libdwarf Internal error: Type %d unexpected\n", - (int) type); -#endif - } - } - } - - ret_mem = malloc(size); -#ifdef DWARF_SIMPLE_MALLOC - _dwarf_simple_malloc_add_to_list(dbg, ret_mem, (unsigned long) size, - type); -#endif - if (ret_mem != NULL) - memset(ret_mem, 0, size); - - dwarf_malloc_check_alloc_data(ret_mem, type); - if (index_into_allocated[type].specialconstructor) { - int res = - index_into_allocated[type].specialconstructor(dbg, ret_mem); - if (res != DW_DLV_OK) { - /* We leak what we allocated in _dwarf_find_memory when - constructor fails. */ - return NULL; - } - } - - return (ret_mem); -} - - - -/* - This function is used to deallocate a region of memory - that was obtained by a call to _dwarf_get_alloc. Note - that though dwarf_dealloc() is a public function, - _dwarf_get_alloc() isn't. - - For lists, typically arrays of pointers, it is assumed - that the space was allocated by a direct call to malloc, - and so a straight free() is done. This is also the case - for variable length blocks such as DW_DLA_FRAME_BLOCK - and DW_DLA_LOC_BLOCK and DW_DLA_RANGES. - - For strings, the pointer might point to a string in - .debug_info or .debug_string. After this is checked, - and if found not to be the case, a free() is done, - again on the assumption that a malloc was used to - obtain the space. - - For other types of structs, a pointer to the chunk that - the struct was allocated out of, is present in the bytes - preceding the pointer passed in. For this chunk it is - checked whether all the structs in that chunk are now free. - If so, the entire chunk is free_ed. Otherwise, the space - is added to the free list for that chunk, and the free count - incremented. - - This function does not return anything. -*/ -void -dwarf_dealloc(Dwarf_Debug dbg, - Dwarf_Ptr space, Dwarf_Unsigned alloc_type) -{ - Dwarf_Alloc_Hdr alloc_hdr; - Dwarf_Alloc_Area alloc_area; - unsigned int type = alloc_type; - unsigned int index; - - if (space == NULL) { - return; - } - if (type == DW_DLA_ERROR) { - /* Get pointer to Dwarf_Alloc_Area this struct came from. See - dwarf_alloc.h ROUND_SIZE_WITH_POINTER stuff */ - alloc_area = - *(Dwarf_Alloc_Area *) ((char *) space - DW_RESERVE); - if (alloc_area == 0) { - /* This is the special case of a failed dwarf_init(). Also - (and more signficantly) there are a variety of other - situations where libdwarf does not *know* what dbg is - involved (because of a libdwarf-caller-error) so - libdwarf uses NULL as the dbg. Those too wind up here. */ - _dwarf_free_special_error(space); - dwarf_malloc_check_dealloc_data(space, type); - return; - } - - } - if (dbg == NULL) { - /* App error, or an app that failed to succeed in a - dwarf_init() call. */ - return; - } - if (type >= ALLOC_AREA_INDEX_TABLE_MAX) { - /* internal or user app error */ - return; - } - - index = index_into_allocated[type].ia_al_num; - /* - A string pointer may point into .debug_info or .debug_string. - Otherwise, they are directly malloc'ed. */ - dwarf_malloc_check_dealloc_data(space, type); - if (index == 0) { - if (type == DW_DLA_STRING) { - if ((Dwarf_Small *) space >= dbg->de_debug_info.dss_data && - (Dwarf_Small *) space < - dbg->de_debug_info.dss_data + dbg->de_debug_info.dss_size) - return; - - if (dbg->de_debug_line.dss_data != NULL && - (Dwarf_Small *) space >= dbg->de_debug_line.dss_data && - (Dwarf_Small *) space < - dbg->de_debug_line.dss_data + dbg->de_debug_line.dss_size) - return; - - if (dbg->de_debug_pubnames.dss_data != NULL && - (Dwarf_Small *) space >= dbg->de_debug_pubnames.dss_data && - (Dwarf_Small *) space < - dbg->de_debug_pubnames.dss_data + - dbg->de_debug_pubnames.dss_size) - return; - - if (dbg->de_debug_frame.dss_data != NULL && - (Dwarf_Small *) space >= dbg->de_debug_frame.dss_data && - (Dwarf_Small *) space < - dbg->de_debug_frame.dss_data + dbg->de_debug_frame.dss_size) - return; - - if (dbg->de_debug_str.dss_data != NULL && - (Dwarf_Small *) space >= dbg->de_debug_str.dss_data && - (Dwarf_Small *) space < - dbg->de_debug_str.dss_data + dbg->de_debug_str.dss_size) - return; - - if (dbg->de_debug_funcnames.dss_data != NULL && - (Dwarf_Small *) space >= dbg->de_debug_funcnames.dss_data && - (Dwarf_Small *) space < - dbg->de_debug_funcnames.dss_data + - dbg->de_debug_funcnames.dss_size) - return; - - if (dbg->de_debug_typenames.dss_data != NULL && - (Dwarf_Small *) space >= dbg->de_debug_typenames.dss_data && - (Dwarf_Small *) space < - dbg->de_debug_typenames.dss_data + - dbg->de_debug_typenames.dss_size) - return; - if (dbg->de_debug_pubtypes.dss_data != NULL && - (Dwarf_Small *) space >= dbg->de_debug_pubtypes.dss_data && - (Dwarf_Small *) space < - dbg->de_debug_pubtypes.dss_data + - dbg->de_debug_pubtypes.dss_size) - return; - - if (dbg->de_debug_varnames.dss_data != NULL && - (Dwarf_Small *) space >= dbg->de_debug_varnames.dss_data && - (Dwarf_Small *) space < - dbg->de_debug_varnames.dss_data + - dbg->de_debug_varnames.dss_size) - return; - - if (dbg->de_debug_weaknames.dss_data != NULL && - (Dwarf_Small *) space >= dbg->de_debug_weaknames.dss_data && - (Dwarf_Small *) space < - dbg->de_debug_weaknames.dss_data + - dbg->de_debug_weaknames.dss_size) - return; - -#ifdef DWARF_SIMPLE_MALLOC - _dwarf_simple_malloc_delete_from_list(dbg, space, type); -#endif - free(space); - return; - } - - if (type == DW_DLA_LIST || - type == DW_DLA_FRAME_BLOCK || - type == DW_DLA_LOC_BLOCK || type == DW_DLA_ADDR || - type == DW_DLA_RANGES || - type == DW_DLA_HASH_TABLE_ENTRY) { - -#ifdef DWARF_SIMPLE_MALLOC - _dwarf_simple_malloc_delete_from_list(dbg, space, type); -#endif - free(space); - return; - } - /* else is an alloc type that is not used */ - /* app or internal error */ -#ifdef DWARF_SIMPLE_MALLOC - _dwarf_simple_malloc_botch(4); -#endif - return; - - } - if (index_into_allocated[type].specialdestructor) { - index_into_allocated[type].specialdestructor(space); - } -#ifdef DWARF_SIMPLE_MALLOC - _dwarf_simple_malloc_delete_from_list(dbg, space, type); - free(space); -#else /* !DWARF_SIMPLE_MALLOC */ - alloc_hdr = &dbg->de_alloc_hdr[index]; - - /* Get pointer to Dwarf_Alloc_Area this struct came from. See - dwarf_alloc.h ROUND_SIZE_WITH_POINTER stuff */ - alloc_area = *(Dwarf_Alloc_Area *) ((char *) space - DW_RESERVE); - - /* ASSERT: alloc_area != NULL If NULL we could abort, let it - coredump below, or return, pretending all is well. We go on, - letting program crash. Is caller error. */ - - /* - Check that the alloc_hdr field of the alloc_area we have is - pointing to the right alloc_hdr. This is used to catch use of - incorrect deallocation code by the user. */ - if (alloc_area->aa_alloc_hdr != alloc_hdr) { - /* If we get here, the user has called dwarf_dealloc wrongly or - there is some other disastrous error. By leaking mem here we - try to be safe... */ -#ifdef DEBUG - fprintf(stderr, - "libdwarf Internal error: type %d hdr mismatch %lx %lx " - "area ptr %lx\n", - (int) type, - (long) alloc_area->aa_alloc_hdr, - (long) alloc_hdr, (long) alloc_area); -#endif - return; - } - - alloc_hdr->ah_struct_user_holds--; - alloc_area->aa_free_structs_in_chunk++; - - /* - Give chunk back to malloc only when every struct is freed */ - if (alloc_area->aa_free_structs_in_chunk == - alloc_hdr->ah_structs_per_chunk) { - if (alloc_area->aa_prev != NULL) { - alloc_area->aa_prev->aa_next = alloc_area->aa_next; - } else { - alloc_hdr->ah_alloc_area_head = alloc_area->aa_next; - } - - if (alloc_area->aa_next != NULL) { - alloc_area->aa_next->aa_prev = alloc_area->aa_prev; - } - - alloc_hdr->ah_chunks_allocated--; - - if (alloc_area == alloc_hdr->ah_last_alloc_area) { - alloc_hdr->ah_last_alloc_area = NULL; - } - memset(alloc_area, 0, sizeof(*alloc_area)); - free(alloc_area); - } - - else { - ((Dwarf_Free_List) space)->fl_next = alloc_area->aa_free_list; - alloc_area->aa_free_list = space; - } -#endif /* !DWARF_SIMPLE_MALLOC */ -} - - -/* - Allocates space for a Dwarf_Debug_s struct, - since one does not exist. -*/ -Dwarf_Debug -_dwarf_get_debug(void - ) -{ - Dwarf_Debug dbg; - - dbg = (Dwarf_Debug) malloc(sizeof(struct Dwarf_Debug_s)); - if (dbg == NULL) - return (NULL); - else - memset(dbg, 0, sizeof(struct Dwarf_Debug_s)); - return (dbg); -} - - -/* - Sets up the Dwarf_Debug_s struct for all the - allocation types currently defined. - Allocation types DW_DLA_STRING, DW_DLA_LIST, - DW_DLA_FRAME_BLOCK, DW_DLA_LOC_BLOCK, DW_DLA_RANGES are - malloc'ed directly. - - This routine should be called after _dwarf_setup(), - so that information about the sizes of the Dwarf - sections can be used to decide the number of - structs of each type malloc'ed. - - Also DW_DLA_ELLIST, DW_DLA_BOUNDS, DW_DLA_TYPE, - DW_DLA_SUBSCR, DW_DLA_LINEBUF allocation types - are currently not used. - The ah_bytes_one_struct and ah_structs_per_chunk fields for - these types have been set to 1 for efficiency - in dwarf_get_alloc(). - - Ah_alloc_num should be greater than 1 for all - types that are currently being used. - - Therefore, for these allocation types the - ah_bytes_one_struct, and ah_structs_per_chunk fields do not - need to be initialized. - - Being an internal routine, assume proper dbg. -*/ - -Dwarf_Debug -_dwarf_setup_debug(Dwarf_Debug dbg) -{ - int i; - - for (i = 1; i <= MAX_DW_DLA; i++) { - const struct ial_s *ialp = &index_into_allocated[i]; - unsigned int hdr_index = ialp->ia_al_num; - Dwarf_Word str_size = ialp->ia_struct_size; - Dwarf_Word str_count = ialp->ia_base_count; - Dwarf_Word rnded_size = ROUND_SIZE_WITH_POINTER(str_size); - - Dwarf_Alloc_Hdr alloc_hdr = &dbg->de_alloc_hdr[hdr_index]; - - alloc_hdr->ah_bytes_one_struct = (Dwarf_Half) rnded_size; - - /* ah_structs_per_chunk must be >0 else we are in trouble */ - alloc_hdr->ah_structs_per_chunk = str_count; - alloc_hdr->ah_bytes_malloc_per_chunk = rnded_size * str_count; - } - return (dbg); -} - -/* - This function prints out the statistics - collected on allocation of memory chunks. -*/ -void -dwarf_print_memory_stats(Dwarf_Debug dbg) -{ - Dwarf_Alloc_Hdr alloc_hdr; - Dwarf_Shalf i; - - /* - Alloc types start at 1, not 0. Hence, the first NULL string, and - also a size of MAX_DW_DLA + 1. */ - char *alloc_type_name[MAX_DW_DLA + 1] = { - "", - "DW_DLA_STRING", - "DW_DLA_LOC", - "DW_DLA_LOCDESC", - "DW_DLA_ELLIST", - "DW_DLA_BOUNDS", - "DW_DLA_BLOCK", - "DW_DLA_DEBUG", - "DW_DLA_DIE", - "DW_DLA_LINE", - "DW_DLA_ATTR", - "DW_DLA_TYPE", - "DW_DLA_SUBSCR", - "DW_DLA_GLOBAL", - "DW_DLA_ERROR", - "DW_DLA_LIST", - "DW_DLA_LINEBUF", - "DW_DLA_ARANGE", - "DW_DLA_ABBREV", - "DW_DLA_FRAME_OP", - "DW_DLA_CIE", - "DW_DLA_FDE", - "DW_DLA_LOC_BLOCK", - "DW_DLA_FRAME_BLOCK", - "DW_DLA_FUNC", - "DW_DLA_TYPENAME", - "DW_DLA_VAR", - "DW_DLA_WEAK", - "DW_DLA_ADDR", - "DW_DLA_RANGES", - "DW_DLA_ABBREV_LIST", - "DW_DLA_CHAIN", - "DW_DLA_CU_CONTEXT", - "DW_DLA_FRAME", - "DW_DLA_GLOBAL_CONTEXT", - "DW_DLA_FILE_ENTRY", - "DW_DLA_LINE_CONTEXT", - "DW_DLA_LOC_CHAIN", - "DW_DLA_HASH_TABLE", - "DW_DLA_FUNC_CONTEXT", - "DW_DLA_TYPENAME_CONTEXT", - "DW_DLA_VAR_CONTEXT", - "DW_DLA_WEAK_CONTEXT", - "DW_DLA_PUBTYPES_CONTEXT", - "DW_DLA_HASH_TABLE_ENTRY", - }; - - if (dbg == NULL) - return; - - printf("Size of Dwarf_Debug %4ld bytes\n", - (long) sizeof(*dbg)); - printf("Size of Dwarf_Alloc_Hdr_s %4ld bytes\n", - (long) sizeof(struct Dwarf_Alloc_Hdr_s)); - printf("size of Dwarf_Alloc_Area_s %4ld bytes\n", - (long) sizeof(struct Dwarf_Alloc_Area_s)); - - printf(" Alloc Type Curr Structs byt str\n"); - printf(" ---------- ---- ------- per per\n"); - for (i = 1; i <= MAX_DW_DLA; i++) { - int indx = index_into_allocated[i].ia_al_num; - - alloc_hdr = &dbg->de_alloc_hdr[indx]; - if (alloc_hdr->ah_bytes_one_struct != 1) { - printf("%2d %-25s %6d %8d %6d %6d\n", - (int) i, - alloc_type_name[i], - (int) alloc_hdr->ah_chunks_allocated, - (int) alloc_hdr->ah_struct_user_holds, - (int) alloc_hdr->ah_bytes_malloc_per_chunk, - (int) alloc_hdr->ah_structs_per_chunk); - } - } -} - - -#ifndef DWARF_SIMPLE_MALLOC -/* - This recursively frees - the chunks still allocated, and - forward chained through the aa_next - pointer. -*/ -static void -_dwarf_recursive_free(Dwarf_Alloc_Area alloc_area) -{ - if (alloc_area->aa_next != NULL) { - _dwarf_recursive_free(alloc_area->aa_next); - } - - alloc_area->aa_next = 0; - alloc_area->aa_prev = 0; - free(alloc_area); -} -#endif - -/* In the 'rela' relocation case we might have malloc'd - space to ensure it is read-write. In that case, free the space. */ -static void -rela_free(struct Dwarf_Section_s * sec) -{ - if (sec->dss_data_was_malloc) { - free(sec->dss_data); - } - sec->dss_data = 0; - sec->dss_data_was_malloc = 0; -} - -/* - Used to free all space allocated for this Dwarf_Debug. - The caller should assume that the Dwarf_Debug pointer - itself is no longer valid upon return from this function. - - In case of difficulty, this function simply returns quietly. -*/ -int -_dwarf_free_all_of_one_debug(Dwarf_Debug dbg) -{ - Dwarf_Alloc_Hdr alloc_hdr; - Dwarf_Shalf i; - Dwarf_CU_Context context = 0; - Dwarf_CU_Context nextcontext = 0; - - if (dbg == NULL) - return (DW_DLV_ERROR); - - /* To do complete validation that we have no surprising missing or - erroneous deallocs it is advisable to do the dwarf_deallocs here - that are not things the user can otherwise request. - Housecleaning. */ - - for (context = dbg->de_cu_context_list; - context; context = nextcontext) { - Dwarf_Hash_Table hash_table = context->cc_abbrev_hash_table; - _dwarf_free_abbrev_hash_table_contents(dbg,hash_table); - nextcontext = context->cc_next; - dwarf_dealloc(dbg, hash_table, DW_DLA_HASH_TABLE); - dwarf_dealloc(dbg, context, DW_DLA_CU_CONTEXT); - } - - /* Housecleaning done. Now really free all the space. */ -#ifdef DWARF_SIMPLE_MALLOC - if (dbg->de_simple_malloc_base) { - struct simple_malloc_record_s *smp = dbg->de_simple_malloc_base; - - while (smp) { - int i; - struct simple_malloc_record_s *prev_smp = 0; - - for (i = 0; i < smp->sr_used; ++i) { - struct simple_malloc_entry_s *cur; - - cur = &smp->sr_entry[i]; - if (cur->se_addr != 0) { - free(cur->se_addr); - cur->se_addr = 0; - } - } - prev_smp = smp; - smp = smp->sr_next; - free(prev_smp); - } - dbg->de_simple_malloc_base = 0; - } -#else - for (i = 1; i < ALLOC_AREA_REAL_TABLE_MAX; i++) { - int indx = i; - - alloc_hdr = &dbg->de_alloc_hdr[indx]; - if (alloc_hdr->ah_alloc_area_head != NULL) { - _dwarf_recursive_free(alloc_hdr->ah_alloc_area_head); - } - } - -#endif - rela_free(&dbg->de_debug_info); - rela_free(&dbg->de_debug_abbrev); - rela_free(&dbg->de_debug_line); - rela_free(&dbg->de_debug_loc); - rela_free(&dbg->de_debug_aranges); - rela_free(&dbg->de_debug_macinfo); - rela_free(&dbg->de_debug_pubnames); - rela_free(&dbg->de_debug_str); - rela_free(&dbg->de_debug_frame); - rela_free(&dbg->de_debug_frame_eh_gnu); - rela_free(&dbg->de_debug_pubtypes); - rela_free(&dbg->de_debug_funcnames); - rela_free(&dbg->de_debug_typenames); - rela_free(&dbg->de_debug_varnames); - rela_free(&dbg->de_debug_weaknames); - rela_free(&dbg->de_debug_ranges); - dwarf_harmless_cleanout(&dbg->de_harmless_errors); - - memset(dbg, 0, sizeof(*dbg)); /* Prevent accidental use later. */ - free(dbg); - return (DW_DLV_OK); -} - -/* A special case: we have no dbg, no alloc header etc. - So create something out of thin air that we can recognize - in dwarf_dealloc. - Something with the prefix (prefix space hidden from caller). - - Only applies to DW_DLA_ERROR, making up an error record. -*/ - -struct Dwarf_Error_s * -_dwarf_special_no_dbg_error_malloc(void) -{ - /* the union unused things are to guarantee proper alignment */ - union u { - Dwarf_Alloc_Area ptr_not_used; - struct Dwarf_Error_s base_not_used; - char data_space[sizeof(struct Dwarf_Error_s) + - (DW_RESERVE * 2)]; - }; - char *mem; - - mem = malloc(sizeof(union u)); - - if (mem == 0) { - return 0; - - } - memset(mem, 0, sizeof(union u)); - mem += DW_RESERVE; - return (struct Dwarf_Error_s *) mem; -} - -/* The free side of _dwarf_special_no_dbg_error_malloc() -*/ -static void -_dwarf_free_special_error(Dwarf_Ptr space) -{ - char *mem = (char *) space; - - mem -= DW_RESERVE; - free(mem); -} - - -#ifdef DWARF_SIMPLE_MALLOC -/* here solely for planting a breakpoint. */ -/* ARGSUSED */ -void -_dwarf_simple_malloc_botch(int err) -{ - fprintf(stderr,"simple malloc botch %d\n",err); -} -static void -_dwarf_simple_malloc_add_to_list(Dwarf_Debug dbg, - Dwarf_Ptr addr, - unsigned long size, short alloc_type) -{ - struct simple_malloc_record_s *cur; - struct simple_malloc_entry_s *newentry; - - if (!dbg->de_simple_malloc_base) { - /* First entry to this routine. */ - dbg->de_simple_malloc_base = - malloc(sizeof(struct simple_malloc_record_s)); - if (!dbg->de_simple_malloc_base) { - _dwarf_simple_malloc_botch(7); - return; /* no memory, give up */ - } - memset(dbg->de_simple_malloc_base, - 0, sizeof(struct simple_malloc_record_s)); - } - cur = dbg->de_simple_malloc_base; - - if (cur->sr_used >= DSM_BLOCK_COUNT) { - /* Better not be > than as that means chaos */ - - /* Create a new block to link at the head. */ - - struct simple_malloc_record_s *newblock = - malloc(sizeof(struct simple_malloc_record_s)); - if (!newblock) { - _dwarf_simple_malloc_botch(8); - return; /* Can do nothing, out of memory */ - } - memset(newblock, 0, sizeof(struct simple_malloc_record_s)); - /* Link the new block at the head of the chain, and make it - 'current' */ - dbg->de_simple_malloc_base = newblock; - newblock->sr_next = cur; - cur = newblock; - } - newentry = &cur->sr_entry[cur->sr_used]; - newentry->se_addr = addr; - newentry->se_size = size; - newentry->se_type = alloc_type; - ++cur->sr_used; -} - -/* - DWARF_SIMPLE_MALLOC: testing the hypothesis that the existing - malloc scheme here (see _dwarf_get_alloc()) is pointless complexity. - - DWARF_SIMPLE_MALLOC also makes it easy for a malloc-tracing - tool to verify libdwarf malloc has no botches (though of course - such does not test the complicated standard-libdwarf-alloc code). - - To properly answer the question, the simple-malloc allocate - and delete should be something other than a simple list. - Perhaps a heap, or perhaps a red-black tree. - -*/ -static void -_dwarf_simple_malloc_delete_from_list(Dwarf_Debug dbg, - Dwarf_Ptr space, short alloc_type) -{ - if (space == 0) { - _dwarf_simple_malloc_botch(6); - } - if (dbg->de_simple_malloc_base) { - struct simple_malloc_record_s *smp = dbg->de_simple_malloc_base; - - while (smp) { - int i; - - for (i = 0; i < smp->sr_used; ++i) { - struct simple_malloc_entry_s *cur; - - cur = &smp->sr_entry[i]; - if (cur->se_addr == space) { - if (cur->se_type != alloc_type) { - _dwarf_simple_malloc_botch(0); - } - cur->se_addr = 0; - return; - } - } - smp = smp->sr_next; - } - } - /* Never found the space. */ - _dwarf_simple_malloc_botch(1); - return; - -} -#endif diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_alloc.h b/usr/src/tools/ctf/dwarf/common/dwarf_alloc.h deleted file mode 100644 index 3a61c692c6..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_alloc.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - - Copyright (C) 2000,2005 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2008-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - -/* #define DWARF_SIMPLE_MALLOC 1 */ - -Dwarf_Ptr _dwarf_get_alloc(Dwarf_Debug, Dwarf_Small, Dwarf_Unsigned); -Dwarf_Debug _dwarf_get_debug(void); -Dwarf_Debug _dwarf_setup_debug(Dwarf_Debug); -int _dwarf_free_all_of_one_debug(Dwarf_Debug); - -typedef struct Dwarf_Alloc_Area_s *Dwarf_Alloc_Area; -typedef struct Dwarf_Free_List_s *Dwarf_Free_List; - -/* ALLOC_AREA_INDEX_TABLE_MAX is the size of the - struct ial_s index_into_allocated array in dwarf_alloc.c -*/ -#define ALLOC_AREA_INDEX_TABLE_MAX 45 -/* ALLOC_AREA_REAL_TABLE_MAX is the size of the array needed - to hold pointers to dwarf alloc chunk areas. - It's smaller as some of the index_into_allocated - entries (they look like {0,1,1,0,0} ) - are treated specially and don't use 'chunks'. -*/ -#define ALLOC_AREA_REAL_TABLE_MAX 32 - -/* - This struct is used to chain all the deallocated - structs on the free list of each chain. The structs - are chained internally, by using the memory they - contain. -*/ -struct Dwarf_Free_List_s { - Dwarf_Free_List fl_next; -}; - - -/* - This struct is used to manage all the chunks malloc'ed - for a particular alloc_type. Many of the fields are - initialized by dwarf_init(). -*/ -struct Dwarf_Alloc_Hdr_s { - - /* Count of actual number of structs user app holds pointers to - currently. */ - Dwarf_Sword ah_struct_user_holds; - - /* - Size of each struct that will be allocated for this alloc_type. - Initialized by dwarf_init(). */ - Dwarf_Half ah_bytes_one_struct; - - /* - Number of structs of this alloc_type that will be contained in - each chunk that is malloc'ed. Initialized by dwarf_init(). */ - Dwarf_Word ah_structs_per_chunk; - - /* - Number of bytes malloc'ed per chunk which is basically - (ah_bytes_one_struct+_DWARF_RESERVE) * ah_alloc_num. */ - Dwarf_Word ah_bytes_malloc_per_chunk; - - /* Count of chunks currently allocated for type. */ - Dwarf_Sword ah_chunks_allocated; - - /* - Points to a chain of Dwarf_Alloc_Area_s structs that represent - all the chunks currently allocated for the alloc_type. */ - Dwarf_Alloc_Area ah_alloc_area_head; - - /* Last Alloc Area that was allocated by malloc. The - free-space-search area looks here first and only if it is full - goes thru the list pointed to by ah_alloc_area_head. */ - Dwarf_Alloc_Area ah_last_alloc_area; -}; - - -/* - This struct is used to manage each chunk that is - malloc'ed for a particular alloc_type. For each - allocation type, the allocation header points to - a list of all the chunks malloc'ed for that type. -*/ -struct Dwarf_Alloc_Area_s { - - /* Points to the free list of structs in the chunk. */ - Dwarf_Ptr aa_free_list; - - /* - Count of the number of free structs in the chunk. This includes - both those on the free list, and in the blob. */ - Dwarf_Sword aa_free_structs_in_chunk; - - /* - Points to the first byte of the blob from which struct will be - allocated. A struct is put on the free_list only when it - dwarf_deallocated. Initial allocations are from the blob. */ - Dwarf_Small *aa_blob_start; - - /* Points just past the last byte of the blob. */ - Dwarf_Small *aa_blob_end; - - /* Points to alloc_hdr this alloc_area is linked to: The owner, in - other words. */ - Dwarf_Alloc_Hdr aa_alloc_hdr; - - /* - Used for chaining Dwarf_Alloc_Area_s atructs. Alloc areas are - doubly linked to enable deletion from the list in constant time. */ - Dwarf_Alloc_Area aa_next; - Dwarf_Alloc_Area aa_prev; -}; - -struct Dwarf_Error_s *_dwarf_special_no_dbg_error_malloc(void); - -#ifdef DWARF_SIMPLE_MALLOC -/* - DWARF_SIMPLE_MALLOC is for testing the hypothesis that the existing - complex malloc scheme in libdwarf is pointless complexity. - - DWARF_SIMPLE_MALLOC also makes it easy for a malloc-tracing - tool to verify libdwarf malloc has no botches (though of course - such does not test the complicated standard-libdwarf-alloc code). - -*/ - -struct simple_malloc_entry_s { - Dwarf_Small *se_addr; - unsigned long se_size; - short se_type; -}; -#define DSM_BLOCK_COUNT (1000) -#define DSM_BLOCK_SIZE (sizeof(struct simple_malloc_entry_s)*DSM_BLOCK_COUNT) - -/* we do this so dwarf_dealloc can really free everything */ -struct simple_malloc_record_s { - struct simple_malloc_record_s *sr_next; - int sr_used; - struct simple_malloc_entry_s sr_entry[DSM_BLOCK_COUNT]; -}; - - - -#endif /* DWARF_SIMPLE_MALLOC */ diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_arange.c b/usr/src/tools/ctf/dwarf/common/dwarf_arange.c deleted file mode 100644 index e7ad8acc5e..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_arange.c +++ /dev/null @@ -1,593 +0,0 @@ -/* - - Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the Crittenden Lane address. -*/ - - - - - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include "dwarf_arange.h" -#include "dwarf_global.h" /* for _dwarf_fixup_* */ - - -/* Common code for two user-visible routines to share. - Errors here result in memory leaks, but errors here - are serious (making aranges unusable) so we assume - callers will not repeat the error often or mind the leaks. -*/ -static int -dwarf_get_aranges_list(Dwarf_Debug dbg, - Dwarf_Chain * chain_out, - Dwarf_Signed * chain_count_out, - Dwarf_Error * error) -{ - /* Sweeps through the arange. */ - Dwarf_Small *arange_ptr = 0; - Dwarf_Small *arange_ptr_start = 0; - - /* Start of arange header. Used for rounding offset of arange_ptr - to twice the tuple size. Libdwarf requirement. */ - Dwarf_Small *header_ptr = 0; - - /* Version of .debug_aranges header. */ - Dwarf_Half version = 0; - - /* Offset of current set of aranges into .debug_info. */ - Dwarf_Off info_offset = 0; - - /* Size in bytes of addresses in target. */ - Dwarf_Small address_size = 0; - - /* Size in bytes of segment offsets in target. */ - Dwarf_Small segment_size = 0; - - /* Count of total number of aranges. */ - Dwarf_Unsigned arange_count = 0; - - Dwarf_Arange arange = 0; - - /* Used to chain Dwarf_Aranges structs. */ - Dwarf_Chain curr_chain = NULL; - Dwarf_Chain prev_chain = NULL; - Dwarf_Chain head_chain = NULL; - - arange_ptr = dbg->de_debug_aranges.dss_data; - arange_ptr_start = arange_ptr; - do { - /* Length of current set of aranges. */ - Dwarf_Unsigned length = 0; - Dwarf_Small remainder = 0; - Dwarf_Small *arange_ptr_past_end = 0; - Dwarf_Unsigned range_entry_size = 0; - - int local_length_size; - - /*REFERENCED*/ /* Not used in this instance of the macro */ - int local_extension_size = 0; - - header_ptr = arange_ptr; - - /* READ_AREA_LENGTH updates arange_ptr for consumed bytes */ - READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned, - arange_ptr, local_length_size, - local_extension_size); - arange_ptr_past_end = arange_ptr + length; - - - READ_UNALIGNED(dbg, version, Dwarf_Half, - arange_ptr, sizeof(Dwarf_Half)); - arange_ptr += sizeof(Dwarf_Half); - length = length - sizeof(Dwarf_Half); - if (version != CURRENT_VERSION_STAMP) { - _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR); - return (DW_DLV_ERROR); - } - - READ_UNALIGNED(dbg, info_offset, Dwarf_Off, - arange_ptr, local_length_size); - arange_ptr += local_length_size; - length = length - local_length_size; - if (info_offset >= dbg->de_debug_info.dss_size) { - FIX_UP_OFFSET_IRIX_BUG(dbg, info_offset, - "arange info offset.a"); - if (info_offset >= dbg->de_debug_info.dss_size) { - _dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD); - return (DW_DLV_ERROR); - } - } - - address_size = *(Dwarf_Small *) arange_ptr; - /* It is not an error if the sizes differ. - Unusual, but not an error. */ - arange_ptr = arange_ptr + sizeof(Dwarf_Small); - length = length - sizeof(Dwarf_Small); - - segment_size = *(Dwarf_Small *) arange_ptr; - arange_ptr = arange_ptr + sizeof(Dwarf_Small); - length = length - sizeof(Dwarf_Small); - if (segment_size != 0) { - _dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD); - return (DW_DLV_ERROR); - } - - range_entry_size = 2*address_size + segment_size; - /* Round arange_ptr offset to next multiple of address_size. */ - remainder = (Dwarf_Unsigned) (arange_ptr - header_ptr) % - (range_entry_size); - if (remainder != 0) { - arange_ptr = arange_ptr + (2 * address_size) - remainder; - length = length - ((2 * address_size) - remainder); - } - do { - Dwarf_Addr range_address = 0; - Dwarf_Unsigned segment_selector = 0; - Dwarf_Unsigned range_length = 0; - /* For segmented address spaces, the first field to - read is a segment selector (new in DWARF4) */ - if(version == 4 && segment_size != 0) { - READ_UNALIGNED(dbg, segment_selector, Dwarf_Unsigned, - arange_ptr, segment_size); - arange_ptr += address_size; - length = length - address_size; - } - - READ_UNALIGNED(dbg, range_address, Dwarf_Addr, - arange_ptr, address_size); - arange_ptr += address_size; - length = length - address_size; - - READ_UNALIGNED(dbg, range_length, Dwarf_Unsigned, - arange_ptr, address_size); - arange_ptr += address_size; - length = length - address_size; - - { /* We used to suppress all-zero entries, but - now we return all aranges entries so we show - the entire content. March 31, 2010. */ - - arange = (Dwarf_Arange) - _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1); - if (arange == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - arange->ar_segment_selector = segment_selector; - arange->ar_segment_selector_size = segment_size; - arange->ar_address = range_address; - arange->ar_length = range_length; - arange->ar_info_offset = info_offset; - arange->ar_dbg = dbg; - arange_count++; - - curr_chain = (Dwarf_Chain) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (curr_chain == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - curr_chain->ch_item = arange; - if (head_chain == NULL) - head_chain = prev_chain = curr_chain; - else { - prev_chain->ch_next = curr_chain; - prev_chain = curr_chain; - } - } - /* The current set of ranges is terminated by - range_address 0 and range_length 0, but that - does not necessarily terminate the ranges for this CU! - There can be multiple sets in that DWARF - does not explicitly forbid multiple sets. - DWARF2,3,4 section 7.20 - We stop short to avoid overrun of the end of the CU. - */ - - } while (arange_ptr_past_end >= (arange_ptr + range_entry_size)); - - /* A compiler could emit some padding bytes here. dwarf2/3 - (dwarf4 sec 7.20) does not clearly make extra padding - bytes illegal. */ - if (arange_ptr_past_end < arange_ptr) { - char buf[200]; - Dwarf_Unsigned pad_count = arange_ptr - arange_ptr_past_end; - Dwarf_Unsigned offset = arange_ptr - arange_ptr_start; - snprintf(buf,sizeof(buf),"DW_DLE_ARANGE_LENGTH_BAD." - " 0x%" DW_PR_DUx - " pad bytes at offset 0x%" DW_PR_DUx - " in .debug_aranges", - pad_count, offset); - dwarf_insert_harmless_error(dbg,buf); - } - /* For most compilers, arange_ptr == arange_ptr_past_end at - this point. But not if there were padding bytes */ - arange_ptr = arange_ptr_past_end; - } while (arange_ptr < - dbg->de_debug_aranges.dss_data + dbg->de_debug_aranges.dss_size); - - if (arange_ptr != - dbg->de_debug_aranges.dss_data + dbg->de_debug_aranges.dss_size) { - _dwarf_error(dbg, error, DW_DLE_ARANGE_DECODE_ERROR); - return (DW_DLV_ERROR); - } - *chain_out = head_chain; - *chain_count_out = arange_count; - return DW_DLV_OK; -} - -/* - This function returns the count of the number of - aranges in the .debug_aranges section. It sets - aranges to point to a block of Dwarf_Arange's - describing the arange's. It returns DW_DLV_ERROR - on error. - - Must be identical in most aspects to - dwarf_get_aranges_addr_offsets! - -*/ -int -dwarf_get_aranges(Dwarf_Debug dbg, - Dwarf_Arange ** aranges, - Dwarf_Signed * returned_count, Dwarf_Error * error) -{ - /* Count of total number of aranges. */ - Dwarf_Signed arange_count = 0; - - Dwarf_Arange *arange_block = 0; - - /* Used to chain Dwarf_Aranges structs. */ - Dwarf_Chain curr_chain = NULL; - Dwarf_Chain prev_chain = NULL; - Dwarf_Chain head_chain = NULL; - Dwarf_Unsigned i = 0; - int res = DW_DLV_ERROR; - - /* ***** BEGIN CODE ***** */ - - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - - res = _dwarf_load_section(dbg, &dbg->de_debug_aranges, error); - if (res != DW_DLV_OK) { - return res; - } - - res = dwarf_get_aranges_list(dbg,&head_chain,&arange_count,error); - if(res != DW_DLV_OK) { - return res; - } - - arange_block = (Dwarf_Arange *) - _dwarf_get_alloc(dbg, DW_DLA_LIST, arange_count); - if (arange_block == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - curr_chain = head_chain; - for (i = 0; i < arange_count; i++) { - *(arange_block + i) = curr_chain->ch_item; - prev_chain = curr_chain; - curr_chain = curr_chain->ch_next; - dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN); - } - - *aranges = arange_block; - *returned_count = (arange_count); - return DW_DLV_OK; -} - -/* - This function returns DW_DLV_OK if it succeeds - and DW_DLV_ERR or DW_DLV_OK otherwise. - count is set to the number of addresses in the - .debug_aranges section. - For each address, the corresponding element in - an array is set to the address itself(aranges) and - the section offset (offsets). - Must be identical in most aspects to - dwarf_get_aranges! -*/ -int -_dwarf_get_aranges_addr_offsets(Dwarf_Debug dbg, - Dwarf_Addr ** addrs, - Dwarf_Off ** offsets, - Dwarf_Signed * count, - Dwarf_Error * error) -{ - Dwarf_Unsigned i = 0; - - /* Used to chain Dwarf_Aranges structs. */ - Dwarf_Chain curr_chain = NULL; - Dwarf_Chain prev_chain = NULL; - Dwarf_Chain head_chain = NULL; - - Dwarf_Signed arange_count = 0; - Dwarf_Addr *arange_addrs = 0; - Dwarf_Off *arange_offsets = 0; - - int res = DW_DLV_ERROR; - - /* ***** BEGIN CODE ***** */ - - if (error != NULL) - *error = NULL; - - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - - res = _dwarf_load_section(dbg, &dbg->de_debug_aranges,error); - if (res != DW_DLV_OK) { - return res; - } - - res = dwarf_get_aranges_list(dbg,&head_chain,&arange_count,error); - if(res != DW_DLV_OK) { - return res; - } - - arange_addrs = (Dwarf_Addr *) - _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count); - if (arange_addrs == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - arange_offsets = (Dwarf_Off *) - _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count); - if (arange_offsets == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - curr_chain = head_chain; - for (i = 0; i < arange_count; i++) { - Dwarf_Arange ar = curr_chain->ch_item; - - arange_addrs[i] = ar->ar_address; - arange_offsets[i] = ar->ar_info_offset; - prev_chain = curr_chain; - curr_chain = curr_chain->ch_next; - dwarf_dealloc(dbg, ar, DW_DLA_ARANGE); - dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN); - } - *count = arange_count; - *offsets = arange_offsets; - *addrs = arange_addrs; - return (DW_DLV_OK); -} - - -/* - This function takes a pointer to a block - of Dwarf_Arange's, and a count of the - length of the block. It checks if the - given address is within the range of an - address range in the block. If yes, it - returns the appropriate Dwarf_Arange. - Otherwise, it returns DW_DLV_ERROR. -*/ -int -dwarf_get_arange(Dwarf_Arange * aranges, - Dwarf_Unsigned arange_count, - Dwarf_Addr address, - Dwarf_Arange * returned_arange, Dwarf_Error * error) -{ - Dwarf_Arange curr_arange = 0; - Dwarf_Unsigned i = 0; - - if (aranges == NULL) { - _dwarf_error(NULL, error, DW_DLE_ARANGES_NULL); - return (DW_DLV_ERROR); - } - for (i = 0; i < arange_count; i++) { - curr_arange = *(aranges + i); - if (address >= curr_arange->ar_address && - address < - curr_arange->ar_address + curr_arange->ar_length) { - *returned_arange = curr_arange; - return (DW_DLV_OK); - } - } - - return (DW_DLV_NO_ENTRY); -} - - -/* - This function takes an Dwarf_Arange, - and returns the offset of the first - die in the compilation-unit that the - arange belongs to. Returns DW_DLV_ERROR - on error. -*/ -int -dwarf_get_cu_die_offset(Dwarf_Arange arange, - Dwarf_Off * returned_offset, - Dwarf_Error * error) -{ - Dwarf_Debug dbg = 0; - Dwarf_Off offset = 0; - - if (arange == NULL) { - _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL); - return (DW_DLV_ERROR); - } - dbg = arange->ar_dbg; - offset = arange->ar_info_offset; - if (!dbg->de_debug_info.dss_data) { - int res = _dwarf_load_debug_info(dbg, error); - - if (res != DW_DLV_OK) { - return res; - } - } - *returned_offset = offset + _dwarf_length_of_cu_header(dbg, offset); - return DW_DLV_OK; -} - -/* - This function takes an Dwarf_Arange, - and returns the offset of the CU header - in the compilation-unit that the - arange belongs to. Returns DW_DLV_ERROR - on error. - Ensures .debug_info loaded so - the cu_offset is meaningful. -*/ -int -dwarf_get_arange_cu_header_offset(Dwarf_Arange arange, - Dwarf_Off * cu_header_offset_returned, - Dwarf_Error * error) -{ - Dwarf_Debug dbg = 0; - if (arange == NULL) { - _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL); - return (DW_DLV_ERROR); - } - dbg = arange->ar_dbg; - /* Like dwarf_get_arange_info this ensures debug_info loaded: - the cu_header is in debug_info and will be used else - we would not call dwarf_get_arange_cu_header_offset. */ - if (!dbg->de_debug_info.dss_data) { - int res = _dwarf_load_debug_info(dbg, error); - if (res != DW_DLV_OK) { - return res; - } - } - *cu_header_offset_returned = arange->ar_info_offset; - return DW_DLV_OK; -} - - - - -/* - This function takes a Dwarf_Arange, and returns - true if it is not NULL. It also stores the start - address of the range in *start, the length of the - range in *length, and the offset of the first die - in the compilation-unit in *cu_die_offset. It - returns false on error. - If cu_die_offset returned ensures .debug_info loaded so - the cu_die_offset is meaningful. -*/ -int -dwarf_get_arange_info(Dwarf_Arange arange, - Dwarf_Addr * start, - Dwarf_Unsigned * length, - Dwarf_Off * cu_die_offset, Dwarf_Error * error) -{ - if (arange == NULL) { - _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL); - return (DW_DLV_ERROR); - } - - if (start != NULL) - *start = arange->ar_address; - if (length != NULL) - *length = arange->ar_length; - if (cu_die_offset != NULL) { - Dwarf_Debug dbg = arange->ar_dbg; - Dwarf_Off offset = arange->ar_info_offset; - - if (!dbg->de_debug_info.dss_data) { - int res = _dwarf_load_debug_info(dbg, error); - if (res != DW_DLV_OK) { - return res; - } - } - *cu_die_offset = - offset + _dwarf_length_of_cu_header(dbg, offset); - } - return (DW_DLV_OK); -} - - -/* New for DWARF4, entries may have segment information. - *segment is only meaningful if *segment_entry_size is non-zero. */ -int -dwarf_get_arange_info_b(Dwarf_Arange arange, - Dwarf_Unsigned* segment, - Dwarf_Unsigned* segment_entry_size, - Dwarf_Addr * start, - Dwarf_Unsigned* length, - Dwarf_Off * cu_die_offset, - Dwarf_Error * error) -{ - if (arange == NULL) { - _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL); - return (DW_DLV_ERROR); - } - - if(segment != NULL) { - *segment = arange->ar_segment_selector; - } - if(segment_entry_size != NULL) { - *segment_entry_size = arange->ar_segment_selector_size; - } - if (start != NULL) - *start = arange->ar_address; - if (length != NULL) - *length = arange->ar_length; - if (cu_die_offset != NULL) { - Dwarf_Debug dbg = arange->ar_dbg; - Dwarf_Off offset = arange->ar_info_offset; - - if (!dbg->de_debug_info.dss_data) { - int res = _dwarf_load_debug_info(dbg, error); - if (res != DW_DLV_OK) { - return res; - } - } - *cu_die_offset = - offset + _dwarf_length_of_cu_header(dbg, offset); - } - return (DW_DLV_OK); -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_arange.h b/usr/src/tools/ctf/dwarf/common/dwarf_arange.h deleted file mode 100644 index d6c537c452..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_arange.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - - Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -/* This structure is used to read an arange into. */ -struct Dwarf_Arange_s { - - /* The segment selector. Only non-zero if Dwarf4, only - meaningful if ar_segment_selector_size non-zero */ - Dwarf_Unsigned ar_segment_selector; - - /* Starting address of the arange, ie low-pc. */ - Dwarf_Addr ar_address; - - /* Length of the arange. */ - Dwarf_Unsigned ar_length; - - - /* - Offset into .debug_info of the start of the compilation-unit - containing this set of aranges. */ - Dwarf_Off ar_info_offset; - - /* Corresponding Dwarf_Debug. */ - Dwarf_Debug ar_dbg; - - Dwarf_Half ar_segment_selector_size; -}; - - - -int - _dwarf_get_aranges_addr_offsets(Dwarf_Debug dbg, - Dwarf_Addr ** addrs, - Dwarf_Off ** offsets, - Dwarf_Signed * count, - Dwarf_Error * error); diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_base_types.h b/usr/src/tools/ctf/dwarf/common/dwarf_base_types.h deleted file mode 100644 index 00e2700a81..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_base_types.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - - Copyright (C) 2000,2005 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2008-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "libdwarfdefs.h" - -#define true 1 -#define false 0 - -/* to identify a cie */ -#define DW_CIE_ID ~(0x0) -#define DW_CIE_VERSION 1 /* DWARF2 */ -#define DW_CIE_VERSION3 3 /* DWARF3 */ -#define DW_CIE_VERSION4 4 /* DWARF4 */ - -#define DW_CU_VERSION2 2 -#define DW_CU_VERSION3 3 -#define DW_CU_VERSION4 4 - -/* DWARF2,3 and 4 */ -#define DW_ARANGES_VERSION2 2 - -#define DW_LINE_VERSION2 2 -#define DW_LINE_VERSION3 3 -#define DW_LINE_VERSION4 4 - - -/* - These are allocation type codes for structs that - are internal to the Libdwarf Consumer library. -*/ -#define DW_DLA_ABBREV_LIST DW_DLA_RANGES + 1 -#define DW_DLA_CHAIN DW_DLA_RANGES + 2 -#define DW_DLA_CU_CONTEXT DW_DLA_RANGES + 3 -#define DW_DLA_FRAME DW_DLA_RANGES + 4 -#define DW_DLA_GLOBAL_CONTEXT DW_DLA_RANGES + 5 -#define DW_DLA_FILE_ENTRY DW_DLA_RANGES + 6 -#define DW_DLA_LINE_CONTEXT DW_DLA_RANGES + 7 -#define DW_DLA_LOC_CHAIN DW_DLA_RANGES + 8 -#define DW_DLA_HASH_TABLE DW_DLA_RANGES + 9 -#define DW_DLA_FUNC_CONTEXT DW_DLA_RANGES + 10 -#define DW_DLA_TYPENAME_CONTEXT DW_DLA_RANGES + 11 -#define DW_DLA_VAR_CONTEXT DW_DLA_RANGES + 12 -#define DW_DLA_WEAK_CONTEXT DW_DLA_RANGES + 13 -#define DW_DLA_PUBTYPES_CONTEXT DW_DLA_RANGES + 14 /* DWARF3 */ -#define DW_DLA_HASH_TABLE_ENTRY DW_DLA_RANGES + 15 - -/* Maximum number of allocation types for allocation routines. */ -#define MAX_DW_DLA DW_DLA_HASH_TABLE_ENTRY - -/*Dwarf_Word is unsigned word usable for index, count in memory */ -/*Dwarf_Sword is signed word usable for index, count in memory */ -/* The are 32 or 64 bits depending if 64 bit longs or not, which -** fits the ILP32 and LP64 models -** These work equally well with ILP64. -*/ - -typedef unsigned long Dwarf_Word; -typedef signed long Dwarf_Sword; - -typedef signed char Dwarf_Sbyte; -typedef unsigned char Dwarf_Ubyte; -typedef signed short Dwarf_Shalf; -typedef Dwarf_Small *Dwarf_Byte_Ptr; - -/* these 2 are fixed sizes which must not vary with the -** ILP32/LP64 model. Between these two, stay at 32 bit. -*/ -typedef __uint32_t Dwarf_ufixed; -typedef __int32_t Dwarf_sfixed; - -/* - In various places the code mistakenly associates - forms 8 bytes long with Dwarf_Signed or Dwarf_Unsigned - This is not a very portable assumption. - The following should be used instead for 64 bit integers. -*/ -typedef __uint64_t Dwarf_ufixed64; -typedef __int64_t Dwarf_sfixed64; - - -typedef struct Dwarf_Abbrev_List_s *Dwarf_Abbrev_List; -typedef struct Dwarf_File_Entry_s *Dwarf_File_Entry; -typedef struct Dwarf_CU_Context_s *Dwarf_CU_Context; -typedef struct Dwarf_Hash_Table_s *Dwarf_Hash_Table; -typedef struct Dwarf_Hash_Table_Entry_s *Dwarf_Hash_Table_Entry; - - -typedef struct Dwarf_Alloc_Hdr_s *Dwarf_Alloc_Hdr; diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_die_deliv.c b/usr/src/tools/ctf/dwarf/common/dwarf_die_deliv.c deleted file mode 100644 index 4ba9f2aded..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_die_deliv.c +++ /dev/null @@ -1,855 +0,0 @@ -/* - - Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the Crittenden Lane address. -*/ - - - - -#include "config.h" -#include "dwarf_incl.h" -#ifdef HAVE_ELF_H -#include -#endif -#include -#include "dwarf_die_deliv.h" - - -/* - For a given Dwarf_Debug dbg, this function checks - if a CU that includes the given offset has been read - or not. If yes, it returns the Dwarf_CU_Context - for the CU. Otherwise it returns NULL. Being an - internal routine, it is assumed that a valid dbg - is passed. - - **This is a sequential search. May be too slow. - - If debug_info and debug_abbrev not loaded, this will - wind up returning NULL. So no need to load before calling - this. -*/ -static Dwarf_CU_Context -_dwarf_find_CU_Context(Dwarf_Debug dbg, Dwarf_Off offset) -{ - Dwarf_CU_Context cu_context = 0; - - if (offset >= dbg->de_info_last_offset) - return (NULL); - - if (dbg->de_cu_context != NULL && - dbg->de_cu_context->cc_next != NULL && - dbg->de_cu_context->cc_next->cc_debug_info_offset == offset) { - - return (dbg->de_cu_context->cc_next); - } - - if (dbg->de_cu_context != NULL && - dbg->de_cu_context->cc_debug_info_offset <= offset) { - - for (cu_context = dbg->de_cu_context; - cu_context != NULL; cu_context = cu_context->cc_next) { - - if (offset >= cu_context->cc_debug_info_offset && - offset < cu_context->cc_debug_info_offset + - cu_context->cc_length + cu_context->cc_length_size - + cu_context->cc_extension_size) { - - return (cu_context); - } - } - } - - for (cu_context = dbg->de_cu_context_list; - cu_context != NULL; cu_context = cu_context->cc_next) { - - if (offset >= cu_context->cc_debug_info_offset && - offset < cu_context->cc_debug_info_offset + - cu_context->cc_length + cu_context->cc_length_size - + cu_context->cc_extension_size) { - - return (cu_context); - } - } - - return (NULL); -} - - -/* - This routine checks the dwarf_offdie() list of - CU contexts for the right CU context. -*/ -static Dwarf_CU_Context -_dwarf_find_offdie_CU_Context(Dwarf_Debug dbg, Dwarf_Off offset) -{ - Dwarf_CU_Context cu_context = 0; - - for (cu_context = dbg->de_offdie_cu_context; - cu_context != NULL; cu_context = cu_context->cc_next) - - if (offset >= cu_context->cc_debug_info_offset && - offset < cu_context->cc_debug_info_offset + - cu_context->cc_length + cu_context->cc_length_size - + cu_context->cc_extension_size) - - return (cu_context); - - return (NULL); -} - - -/* - This function is used to create a CU Context for - a compilation-unit that begins at offset in - .debug_info. The CU Context is attached to the - list of CU Contexts for this dbg. It is assumed - that the CU at offset has not been read before, - and so do not call this routine before making - sure of this with _dwarf_find_CU_Context(). - Returns NULL on error. As always, being an - internal routine, assumes a good dbg. - - This function must always set a dwarf error code - before returning NULL. Always. -*/ -static Dwarf_CU_Context -_dwarf_make_CU_Context(Dwarf_Debug dbg, - Dwarf_Off offset, Dwarf_Error * error) -{ - Dwarf_CU_Context cu_context = 0; - Dwarf_Unsigned length = 0; - Dwarf_Signed abbrev_offset = 0; - Dwarf_Byte_Ptr cu_ptr = 0; - int local_extension_size = 0; - int local_length_size = 0; - - cu_context = - (Dwarf_CU_Context) _dwarf_get_alloc(dbg, DW_DLA_CU_CONTEXT, 1); - if (cu_context == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (NULL); - } - cu_context->cc_dbg = dbg; - - cu_ptr = (Dwarf_Byte_Ptr) (dbg->de_debug_info.dss_data + offset); - - /* READ_AREA_LENGTH updates cu_ptr for consumed bytes */ - READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned, - cu_ptr, local_length_size, local_extension_size); - cu_context->cc_length_size = local_length_size; - cu_context->cc_extension_size = local_extension_size; - - - cu_context->cc_length = (Dwarf_Word) length; - - READ_UNALIGNED(dbg, cu_context->cc_version_stamp, Dwarf_Half, - cu_ptr, sizeof(Dwarf_Half)); - cu_ptr += sizeof(Dwarf_Half); - - READ_UNALIGNED(dbg, abbrev_offset, Dwarf_Signed, - cu_ptr, local_length_size); - cu_ptr += local_length_size; - cu_context->cc_abbrev_offset = (Dwarf_Sword) abbrev_offset; - - cu_context->cc_address_size = *(Dwarf_Small *) cu_ptr; - - if ((length < CU_VERSION_STAMP_SIZE + local_length_size + - CU_ADDRESS_SIZE_SIZE) || - (offset + length + local_length_size + - local_extension_size > dbg->de_debug_info.dss_size)) { - - dwarf_dealloc(dbg, cu_context, DW_DLA_CU_CONTEXT); - _dwarf_error(dbg, error, DW_DLE_CU_LENGTH_ERROR); - return (NULL); - } - - if (cu_context->cc_version_stamp != CURRENT_VERSION_STAMP - && cu_context->cc_version_stamp != CURRENT_VERSION_STAMP3 - && cu_context->cc_version_stamp != CURRENT_VERSION_STAMP4) { - dwarf_dealloc(dbg, cu_context, DW_DLA_CU_CONTEXT); - _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR); - return (NULL); - } - - if (abbrev_offset >= dbg->de_debug_abbrev.dss_size) { - dwarf_dealloc(dbg, cu_context, DW_DLA_CU_CONTEXT); - _dwarf_error(dbg, error, DW_DLE_ABBREV_OFFSET_ERROR); - return (NULL); - } - - cu_context->cc_abbrev_hash_table = - (Dwarf_Hash_Table) _dwarf_get_alloc(dbg, DW_DLA_HASH_TABLE, 1); - if (cu_context->cc_abbrev_hash_table == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (NULL); - } - - cu_context->cc_debug_info_offset = (Dwarf_Word) offset; - dbg->de_info_last_offset = - (Dwarf_Word) (offset + length + - local_extension_size + local_length_size); - - if (dbg->de_cu_context_list == NULL) { - dbg->de_cu_context_list = cu_context; - dbg->de_cu_context_list_end = cu_context; - } else { - dbg->de_cu_context_list_end->cc_next = cu_context; - dbg->de_cu_context_list_end = cu_context; - } - - return (cu_context); -} - - -/* - Returns offset of next compilation-unit thru next_cu_offset - pointer. - It basically sequentially moves from one - cu to the next. The current cu is recorded - internally by libdwarf. - - The _b form is new for DWARF4 adding new returned fields. -*/ -int -dwarf_next_cu_header(Dwarf_Debug dbg, - Dwarf_Unsigned * cu_header_length, - Dwarf_Half * version_stamp, - Dwarf_Unsigned * abbrev_offset, - Dwarf_Half * address_size, - Dwarf_Unsigned * next_cu_offset, - Dwarf_Error * error) -{ - return dwarf_next_cu_header_b(dbg, - cu_header_length, - version_stamp, - abbrev_offset, - address_size, - 0,0, - next_cu_offset, - error); -} -int -dwarf_next_cu_header_b(Dwarf_Debug dbg, - Dwarf_Unsigned * cu_header_length, - Dwarf_Half * version_stamp, - Dwarf_Unsigned * abbrev_offset, - Dwarf_Half * address_size, - Dwarf_Half * offset_size, - Dwarf_Half * extension_size, - Dwarf_Unsigned * next_cu_offset, - Dwarf_Error * error) -{ - /* Offset for current and new CU. */ - Dwarf_Unsigned new_offset = 0; - - /* CU Context for current CU. */ - Dwarf_CU_Context cu_context = 0; - - /* ***** BEGIN CODE ***** */ - - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - /* - Get offset into .debug_info of next CU. If dbg has no context, - this has to be the first one. */ - if (dbg->de_cu_context == NULL) { - new_offset = 0; - if (!dbg->de_debug_info.dss_data) { - int res = _dwarf_load_debug_info(dbg, error); - - if (res != DW_DLV_OK) { - return res; - } - } - - } else { - new_offset = dbg->de_cu_context->cc_debug_info_offset + - dbg->de_cu_context->cc_length + - dbg->de_cu_context->cc_length_size + - dbg->de_cu_context->cc_extension_size; - } - - /* - Check that there is room in .debug_info beyond the new offset - for at least a new cu header. If not, return 0 to indicate end - of debug_info section, and reset de_cu_debug_info_offset to - enable looping back through the cu's. */ - if ((new_offset + _dwarf_length_of_cu_header_simple(dbg)) >= - dbg->de_debug_info.dss_size) { - dbg->de_cu_context = NULL; - return (DW_DLV_NO_ENTRY); - } - - /* Check if this CU has been read before. */ - cu_context = _dwarf_find_CU_Context(dbg, new_offset); - - /* If not, make CU Context for it. */ - if (cu_context == NULL) { - cu_context = _dwarf_make_CU_Context(dbg, new_offset, error); - if (cu_context == NULL) { - /* Error if CU Context could not be made. Since - _dwarf_make_CU_Context has already registered an error - we do not do that here: we let the lower error pass - thru. */ - return (DW_DLV_ERROR); - } - } - - dbg->de_cu_context = cu_context; - - if (cu_header_length != NULL) - *cu_header_length = cu_context->cc_length; - - if (version_stamp != NULL) - *version_stamp = cu_context->cc_version_stamp; - - if (abbrev_offset != NULL) - *abbrev_offset = cu_context->cc_abbrev_offset; - - if (address_size != NULL) - *address_size = cu_context->cc_address_size; - if (offset_size != NULL) - *offset_size = cu_context->cc_length_size; - if (extension_size != NULL) - *extension_size = cu_context->cc_extension_size; - - new_offset = new_offset + cu_context->cc_length + - cu_context->cc_length_size + cu_context->cc_extension_size; - *next_cu_offset = new_offset; - return (DW_DLV_OK); -} - - -/* - This function does two slightly different things - depending on the input flag want_AT_sibling. If - this flag is true, it checks if the input die has - a DW_AT_sibling attribute. If it does it returns - a pointer to the start of the sibling die in the - .debug_info section. Otherwise it behaves the - same as the want_AT_sibling false case. - - If the want_AT_sibling flag is false, it returns - a pointer to the immediately adjacent die in the - .debug_info section. - - Die_info_end points to the end of the .debug_info - portion for the cu the die belongs to. It is used - to check that the search for the next die does not - cross the end of the current cu. Cu_info_start points - to the start of the .debug_info portion for the - current cu, and is used to add to the offset for - DW_AT_sibling attributes. Finally, has_die_child - is a pointer to a Dwarf_Bool that is set true if - the present die has children, false otherwise. - However, in case want_AT_child is true and the die - has a DW_AT_sibling attribute *has_die_child is set - false to indicate that the children are being skipped. - - die_info_end points to the last byte+1 of the cu. - -*/ -static Dwarf_Byte_Ptr -_dwarf_next_die_info_ptr(Dwarf_Byte_Ptr die_info_ptr, - Dwarf_CU_Context cu_context, - Dwarf_Byte_Ptr die_info_end, - Dwarf_Byte_Ptr cu_info_start, - Dwarf_Bool want_AT_sibling, - Dwarf_Bool * has_die_child) -{ - Dwarf_Byte_Ptr info_ptr = 0; - Dwarf_Byte_Ptr abbrev_ptr = 0; - Dwarf_Word abbrev_code = 0; - Dwarf_Abbrev_List abbrev_list; - Dwarf_Half attr = 0; - Dwarf_Half attr_form = 0; - Dwarf_Unsigned offset = 0; - Dwarf_Word leb128_length = 0; - Dwarf_Unsigned utmp = 0; - Dwarf_Debug dbg = 0; - - info_ptr = die_info_ptr; - DECODE_LEB128_UWORD(info_ptr, utmp); - abbrev_code = (Dwarf_Word) utmp; - if (abbrev_code == 0) { - return NULL; - } - - - abbrev_list = _dwarf_get_abbrev_for_code(cu_context, abbrev_code); - if (abbrev_list == NULL) { - return (NULL); - } - dbg = cu_context->cc_dbg; - - *has_die_child = abbrev_list->ab_has_child; - - abbrev_ptr = abbrev_list->ab_abbrev_ptr; - do { - Dwarf_Unsigned utmp2; - - DECODE_LEB128_UWORD(abbrev_ptr, utmp2); - attr = (Dwarf_Half) utmp2; - DECODE_LEB128_UWORD(abbrev_ptr, utmp2); - attr_form = (Dwarf_Half) utmp2; - if (attr_form == DW_FORM_indirect) { - Dwarf_Unsigned utmp6; - - /* DECODE_LEB128_UWORD updates info_ptr */ - DECODE_LEB128_UWORD(info_ptr, utmp6); - attr_form = (Dwarf_Half) utmp6; - - } - - if (want_AT_sibling && attr == DW_AT_sibling) { - switch (attr_form) { - case DW_FORM_ref1: - offset = *(Dwarf_Small *) info_ptr; - break; - case DW_FORM_ref2: - /* READ_UNALIGNED does not update info_ptr */ - READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, - info_ptr, sizeof(Dwarf_Half)); - break; - case DW_FORM_ref4: - READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, - info_ptr, sizeof(Dwarf_ufixed)); - break; - case DW_FORM_ref8: - READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, - info_ptr, sizeof(Dwarf_Unsigned)); - break; - case DW_FORM_ref_udata: - offset = - _dwarf_decode_u_leb128(info_ptr, &leb128_length); - break; - case DW_FORM_ref_addr: - /* Very unusual. The FORM is intended to refer to - a different CU, but a different CU cannot - be a sibling, can it? - We could ignore this and treat as if no DW_AT_sibling - present. Or derive the offset from it and if - it is in the same CU use it directly. - The offset here is *supposed* to be a global offset, - so adding cu_info_start is wrong to any offset - we find here unless cu_info_start - is zero! Lets pretend there is no DW_AT_sibling - attribute. */ - goto no_sibling_attr; - default: - return (NULL); - } - - /* Reset *has_die_child to indicate children skipped. */ - *has_die_child = false; - - /* A value beyond die_info_end indicates an error. Exactly - at die_info_end means 1-past-cu-end and simply means we - are at the end, do not return NULL. Higher level code - will detect that we are at the end. */ - if (cu_info_start + offset > die_info_end) { - /* Error case, bad DWARF. */ - return (NULL); - } - /* At or before end-of-cu */ - return (cu_info_start + offset); - } - - no_sibling_attr: - if (attr_form != 0) { - info_ptr += _dwarf_get_size_of_val(cu_context->cc_dbg, - attr_form, - cu_context->cc_address_size, - info_ptr, - cu_context->cc_length_size); - /* It is ok for info_ptr == die_info_end, as we will test - later before using a too-large info_ptr */ - if (info_ptr > die_info_end) { - /* More than one-past-end indicates a bug somewhere, - likely bad dwarf generation. */ - return (NULL); - } - } - } while (attr != 0 || attr_form != 0); - - return (info_ptr); -} - - -/* - Given a Dwarf_Debug dbg, and a Dwarf_Die die, it returns - a Dwarf_Die for the sibling of die. In case die is NULL, - it returns (thru ptr) a Dwarf_Die for the first die in the current - cu in dbg. Returns DW_DLV_ERROR on error. - - It is assumed that every sibling chain including those with - only one element is terminated with a NULL die, except a - chain with only a NULL die. - - The algorithm moves from one die to the adjacent one. It - returns when the depth of children it sees equals the number - of sibling chain terminations. A single count, child_depth - is used to track the depth of children and sibling terminations - encountered. Child_depth is incremented when a die has the - Has-Child flag set unless the child happens to be a NULL die. - Child_depth is decremented when a die has Has-Child false, - and the adjacent die is NULL. Algorithm returns when - child_depth is 0. - - **NOTE: Do not modify input die, since it is used at the end. -*/ -int -dwarf_siblingof(Dwarf_Debug dbg, - Dwarf_Die die, - Dwarf_Die * caller_ret_die, Dwarf_Error * error) -{ - Dwarf_Die ret_die = 0; - Dwarf_Byte_Ptr die_info_ptr = 0; - Dwarf_Byte_Ptr cu_info_start = 0; - - /* die_info_end points 1-past end of die (once set) */ - Dwarf_Byte_Ptr die_info_end = 0; - Dwarf_Word abbrev_code = 0; - Dwarf_Unsigned utmp = 0; - - - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - - if (die == NULL) { - /* Find root die of cu */ - /* die_info_end is untouched here, need not be set in this - branch. */ - Dwarf_Off off2; - - /* If we've not loaded debug_info, de_cu_context will be NULL, - so no need to laod */ - - if (dbg->de_cu_context == NULL) { - _dwarf_error(dbg, error, DW_DLE_DBG_NO_CU_CONTEXT); - return (DW_DLV_ERROR); - } - - off2 = dbg->de_cu_context->cc_debug_info_offset; - die_info_ptr = dbg->de_debug_info.dss_data + - off2 + _dwarf_length_of_cu_header(dbg, off2); - } else { - /* Find sibling die. */ - Dwarf_Bool has_child = false; - Dwarf_Sword child_depth = 0; - - /* We cannot have a legal die unless debug_info was loaded, so - no need to load debug_info here. */ - CHECK_DIE(die, DW_DLV_ERROR); - - die_info_ptr = die->di_debug_info_ptr; - if (*die_info_ptr == 0) { - return (DW_DLV_NO_ENTRY); - } - cu_info_start = dbg->de_debug_info.dss_data + - die->di_cu_context->cc_debug_info_offset; - die_info_end = cu_info_start + die->di_cu_context->cc_length + - die->di_cu_context->cc_length_size + - die->di_cu_context->cc_extension_size; - - if ((*die_info_ptr) == 0) { - return (DW_DLV_NO_ENTRY); - } - child_depth = 0; - do { - die_info_ptr = _dwarf_next_die_info_ptr(die_info_ptr, - die->di_cu_context, - die_info_end, - cu_info_start, true, - &has_child); - if (die_info_ptr == NULL) { - _dwarf_error(dbg, error, DW_DLE_NEXT_DIE_PTR_NULL); - return (DW_DLV_ERROR); - } - - /* die_info_end is one past end. Do not read it! - A test for ``!= die_info_end'' would work as well, - but perhaps < reads more like the meaning. */ - if(die_info_ptr < die_info_end) { - if ((*die_info_ptr) == 0 && has_child) { - die_info_ptr++; - has_child = false; - } - } - - /* die_info_ptr can be one-past-end. */ - if ((die_info_ptr == die_info_end) || - ((*die_info_ptr) == 0)) { - for (; child_depth > 0 && *die_info_ptr == 0; - child_depth--, die_info_ptr++); - } else { - child_depth = has_child ? child_depth + 1 : child_depth; - } - - } while (child_depth != 0); - } - - /* die_info_ptr > die_info_end is really a bug (possibly in dwarf - generation)(but we are past end, no more DIEs here), whereas - die_info_ptr == die_info_end means 'one past end, no more DIEs - here'. */ - if (die != NULL && die_info_ptr >= die_info_end) { - return (DW_DLV_NO_ENTRY); - } - - if ((*die_info_ptr) == 0) { - return (DW_DLV_NO_ENTRY); - } - - ret_die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1); - if (ret_die == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - ret_die->di_debug_info_ptr = die_info_ptr; - ret_die->di_cu_context = - die == NULL ? dbg->de_cu_context : die->di_cu_context; - - DECODE_LEB128_UWORD(die_info_ptr, utmp); - abbrev_code = (Dwarf_Word) utmp; - if (abbrev_code == 0) { - /* Zero means a null DIE */ - dwarf_dealloc(dbg, ret_die, DW_DLA_DIE); - return (DW_DLV_NO_ENTRY); - } - ret_die->di_abbrev_code = abbrev_code; - ret_die->di_abbrev_list = - _dwarf_get_abbrev_for_code(ret_die->di_cu_context, abbrev_code); - if (ret_die->di_abbrev_list == NULL || (die == NULL && - ret_die->di_abbrev_list-> - ab_tag != - DW_TAG_compile_unit)) { - dwarf_dealloc(dbg, ret_die, DW_DLA_DIE); - _dwarf_error(dbg, error, DW_DLE_FIRST_DIE_NOT_CU); - return (DW_DLV_ERROR); - } - - *caller_ret_die = ret_die; - return (DW_DLV_OK); -} - - -int -dwarf_child(Dwarf_Die die, - Dwarf_Die * caller_ret_die, Dwarf_Error * error) -{ - Dwarf_Byte_Ptr die_info_ptr = 0; - - /* die_info_end points one-past-end of die area. */ - Dwarf_Byte_Ptr die_info_end = 0; - Dwarf_Die ret_die = 0; - Dwarf_Bool has_die_child = 0; - Dwarf_Debug dbg; - Dwarf_Word abbrev_code = 0; - Dwarf_Unsigned utmp = 0; - - - CHECK_DIE(die, DW_DLV_ERROR); - dbg = die->di_cu_context->cc_dbg; - die_info_ptr = die->di_debug_info_ptr; - - /* NULL die has no child. */ - if ((*die_info_ptr) == 0) - return (DW_DLV_NO_ENTRY); - - die_info_end = dbg->de_debug_info.dss_data + - die->di_cu_context->cc_debug_info_offset + - die->di_cu_context->cc_length + - die->di_cu_context->cc_length_size + - die->di_cu_context->cc_extension_size; - - die_info_ptr = - _dwarf_next_die_info_ptr(die_info_ptr, die->di_cu_context, - die_info_end, NULL, false, - &has_die_child); - if (die_info_ptr == NULL) { - _dwarf_error(dbg, error, DW_DLE_NEXT_DIE_PTR_NULL); - return (DW_DLV_ERROR); - } - - if (!has_die_child) - return (DW_DLV_NO_ENTRY); - - ret_die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1); - if (ret_die == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - ret_die->di_debug_info_ptr = die_info_ptr; - ret_die->di_cu_context = die->di_cu_context; - - DECODE_LEB128_UWORD(die_info_ptr, utmp); - abbrev_code = (Dwarf_Word) utmp; - if (abbrev_code == 0) { - /* We have arrived at a null DIE, at the end of a CU or the end - of a list of siblings. */ - *caller_ret_die = 0; - dwarf_dealloc(dbg, ret_die, DW_DLA_DIE); - return DW_DLV_NO_ENTRY; - } - ret_die->di_abbrev_code = abbrev_code; - ret_die->di_abbrev_list = - _dwarf_get_abbrev_for_code(die->di_cu_context, abbrev_code); - if (ret_die->di_abbrev_list == NULL) { - dwarf_dealloc(dbg, ret_die, DW_DLA_DIE); - _dwarf_error(dbg, error, DW_DLE_DIE_BAD); - return (DW_DLV_ERROR); - } - - *caller_ret_die = ret_die; - return (DW_DLV_OK); -} - -/* - Given a (global, not cu_relative) die offset, this returns - a pointer to a DIE thru *new_die. - It is up to the caller to do a - dwarf_dealloc(dbg,*new_die,DW_DLE_DIE); -*/ -int -dwarf_offdie(Dwarf_Debug dbg, - Dwarf_Off offset, Dwarf_Die * new_die, Dwarf_Error * error) -{ - Dwarf_CU_Context cu_context = 0; - Dwarf_Off new_cu_offset = 0; - Dwarf_Die die = 0; - Dwarf_Byte_Ptr info_ptr = 0; - Dwarf_Unsigned abbrev_code = 0; - Dwarf_Unsigned utmp = 0; - - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - - cu_context = _dwarf_find_CU_Context(dbg, offset); - if (cu_context == NULL) - cu_context = _dwarf_find_offdie_CU_Context(dbg, offset); - - if (cu_context == NULL) { - int res = _dwarf_load_debug_info(dbg, error); - - if (res != DW_DLV_OK) { - return res; - } - - if (dbg->de_offdie_cu_context_end != NULL) { - Dwarf_CU_Context lcu_context = - dbg->de_offdie_cu_context_end; - new_cu_offset = - lcu_context->cc_debug_info_offset + - lcu_context->cc_length + - lcu_context->cc_length_size + - lcu_context->cc_extension_size; - } - - - do { - if ((new_cu_offset + - _dwarf_length_of_cu_header_simple(dbg)) >= - dbg->de_debug_info.dss_size) { - _dwarf_error(dbg, error, DW_DLE_OFFSET_BAD); - return (DW_DLV_ERROR); - } - - cu_context = - _dwarf_make_CU_Context(dbg, new_cu_offset, error); - if (cu_context == NULL) { - /* Error if CU Context could not be made. Since - _dwarf_make_CU_Context has already registered an - error we do not do that here: we let the lower error - pass thru. */ - - return (DW_DLV_ERROR); - } - - if (dbg->de_offdie_cu_context == NULL) { - dbg->de_offdie_cu_context = cu_context; - dbg->de_offdie_cu_context_end = cu_context; - } else { - dbg->de_offdie_cu_context_end->cc_next = cu_context; - dbg->de_offdie_cu_context_end = cu_context; - } - - new_cu_offset = new_cu_offset + cu_context->cc_length + - cu_context->cc_length_size; - - } while (offset >= new_cu_offset); - } - - die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1); - if (die == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - die->di_cu_context = cu_context; - - info_ptr = dbg->de_debug_info.dss_data + offset; - die->di_debug_info_ptr = info_ptr; - DECODE_LEB128_UWORD(info_ptr, utmp); - abbrev_code = utmp; - if (abbrev_code == 0) { - /* we are at a null DIE (or there is a bug). */ - *new_die = 0; - dwarf_dealloc(dbg, die, DW_DLA_DIE); - return DW_DLV_NO_ENTRY; - } - die->di_abbrev_code = abbrev_code; - die->di_abbrev_list = - _dwarf_get_abbrev_for_code(cu_context, abbrev_code); - if (die->di_abbrev_list == NULL) { - dwarf_dealloc(dbg, die, DW_DLA_DIE); - _dwarf_error(dbg, error, DW_DLE_DIE_ABBREV_LIST_NULL); - return (DW_DLV_ERROR); - } - - *new_die = die; - return (DW_DLV_OK); -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_die_deliv.h b/usr/src/tools/ctf/dwarf/common/dwarf_die_deliv.h deleted file mode 100644 index f1ecb153ba..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_die_deliv.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - - Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2008-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - - -/* - This struct holds information about a abbreviation. - It is put in the hash table for abbreviations for - a compile-unit. -*/ -struct Dwarf_Abbrev_List_s { - - Dwarf_Unsigned ab_code; - Dwarf_Half ab_tag; - Dwarf_Half ab_has_child; - - /* - Points to start of attribute and form pairs in the .debug_abbrev - section for the abbrev. */ - Dwarf_Byte_Ptr ab_abbrev_ptr; - - struct Dwarf_Abbrev_List_s *ab_next; -}; diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_elf_access.c b/usr/src/tools/ctf/dwarf/common/dwarf_elf_access.c deleted file mode 100644 index 6caa64a758..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_elf_access.c +++ /dev/null @@ -1,976 +0,0 @@ -/* - Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. - Portions Copyright 2008-2010 Arxan Technologies, Inc. All Rights Reserved. - Portions Copyright 2009-2010 David Anderson. All rights reserved. - Portions Copyright 2009-2010 Novell Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - -#include "config.h" -#include "dwarf_incl.h" -#include "dwarf_elf_access.h" - -#ifdef HAVE_ELF_H -#include -#endif -#ifdef HAVE_LIBELF_H -#include -#else -#ifdef HAVE_LIBELF_LIBELF_H -#include -#endif -#endif - -#include -#include -#include -#include -#include - -#define FALSE 0 -#define TRUE 1 - -#ifndef EM_MIPS -/* This is the standard elf value EM_MIPS. */ -#define EM_MIPS 8 -#endif - - -#ifdef HAVE_ELF64_GETEHDR -extern Elf64_Ehdr *elf64_getehdr(Elf *); -#endif -#ifdef HAVE_ELF64_GETSHDR -extern Elf64_Shdr *elf64_getshdr(Elf_Scn *); -#endif -#ifdef WORDS_BIGENDIAN -#define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \ - { \ - dbg->de_copy_word(dest, \ - ((char *)source) +srclength-len_out, \ - len_out) ; \ - } - - -#else /* LITTLE ENDIAN */ - -#define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \ - { \ - dbg->de_copy_word( (dest) , \ - ((char *)source) , \ - len_out) ; \ - } -#endif - - - -typedef struct { - dwarf_elf_handle elf; - int is_64bit; - Dwarf_Small length_size; - Dwarf_Small pointer_size; - Dwarf_Unsigned section_count; - Dwarf_Endianness endianness; - Dwarf_Small machine; - int libdwarf_owns_elf; - Elf32_Ehdr *ehdr32; - -#ifdef HAVE_ELF64_GETEHDR - Elf64_Ehdr *ehdr64; -#endif - /* Elf symtab and its strtab. Initialized at first - call to do relocations, the actual data is in the Dwarf_Debug - struct, not allocated locally here. */ - struct Dwarf_Section_s *symtab; - struct Dwarf_Section_s *strtab; - -} dwarf_elf_object_access_internals_t; - -struct Dwarf_Elf_Rela { - Dwarf_ufixed64 r_offset; - /*Dwarf_ufixed64 r_info; */ - Dwarf_ufixed64 r_type; - Dwarf_ufixed64 r_symidx; - Dwarf_ufixed64 r_addend; -}; - - -static int dwarf_elf_object_access_load_section(void* obj_in, - Dwarf_Half section_index, - Dwarf_Small** section_data, - int* error); - -/* - dwarf_elf_object_access_internals_init() - */ -static int -dwarf_elf_object_access_internals_init(void* obj_in, - dwarf_elf_handle elf, - int* error) -{ - dwarf_elf_object_access_internals_t*obj = - (dwarf_elf_object_access_internals_t*)obj_in; - char *ehdr_ident = 0; - Dwarf_Half machine = 0; - obj->elf = elf; - - if ((ehdr_ident = elf_getident(elf, NULL)) == NULL) { - *error = DW_DLE_ELF_GETIDENT_ERROR; - return DW_DLV_ERROR; - } - - obj->is_64bit = (ehdr_ident[EI_CLASS] == ELFCLASS64); - - - if(ehdr_ident[EI_DATA] == ELFDATA2LSB){ - obj->endianness = DW_OBJECT_LSB; - } - else if(ehdr_ident[EI_DATA] == ELFDATA2MSB){ - obj->endianness = DW_OBJECT_MSB; - } - - if (obj->is_64bit) { -#ifdef HAVE_ELF64_GETEHDR - obj->ehdr64 = elf64_getehdr(elf); - if (obj->ehdr64 == NULL) { - *error = DW_DLE_ELF_GETEHDR_ERROR; - return DW_DLV_ERROR; - } - obj->section_count = obj->ehdr64->e_shnum; - machine = obj->ehdr64->e_machine; - obj->machine = machine; -#else - *error = DW_DLE_NO_ELF64_SUPPORT; - return DW_DLV_ERROR; -#endif - } - else { - obj->ehdr32 = elf32_getehdr(elf); - if (obj->ehdr32 == NULL) { - *error = DW_DLE_ELF_GETEHDR_ERROR; - return DW_DLV_ERROR; - } - obj->section_count = obj->ehdr32->e_shnum; - machine = obj->ehdr32->e_machine; - obj->machine = machine; - } - - /* The following length_size is Not Too Significant. Only used - one calculation, and an approximate one at that. */ - obj->length_size = obj->is_64bit ? 8 : 4; - obj->pointer_size = obj->is_64bit ? 8 : 4; - - if (obj->is_64bit && machine != EM_MIPS) { - /* MIPS/IRIX makes pointer size and length size 8 for -64. - Other platforms make length 4 always. */ - /* 4 here supports 32bit-offset dwarf2, as emitted by cygnus - tools, and the dwarfv2.1 64bit extension setting. - This is not the same as the size-of-an-offset, which - is 4 in 32bit dwarf and 8 in 64bit dwarf. */ - obj->length_size = 4; - } - return DW_DLV_OK; -} - -/* - dwarf_elf_object_access_get_byte_order - */ -static -Dwarf_Endianness -dwarf_elf_object_access_get_byte_order(void* obj_in) -{ - dwarf_elf_object_access_internals_t*obj = - (dwarf_elf_object_access_internals_t*)obj_in; - return obj->endianness; -} - -/* - dwarf_elf_object_access_get_section_count() - */ -static -Dwarf_Unsigned -dwarf_elf_object_access_get_section_count(void * obj_in) -{ - dwarf_elf_object_access_internals_t*obj = - (dwarf_elf_object_access_internals_t*)obj_in; - return obj->section_count; -} - - -/* - dwarf_elf_object_access_get_section() - */ -static -int -dwarf_elf_object_access_get_section_info( - void* obj_in, - Dwarf_Half section_index, - Dwarf_Obj_Access_Section* ret_scn, - int* error) -{ - dwarf_elf_object_access_internals_t*obj = - (dwarf_elf_object_access_internals_t*)obj_in; - - Elf32_Shdr *shdr32 = 0; - -#ifdef HAVE_ELF64_GETSHDR - Elf64_Shdr *shdr64 = 0; -#endif - Elf_Scn *scn = 0; - - - scn = elf_getscn(obj->elf, section_index); - if (scn == NULL) { - *error = DW_DLE_MDE; - return DW_DLV_ERROR; - } - if (obj->is_64bit) { -#ifdef HAVE_ELF64_GETSHDR - shdr64 = elf64_getshdr(scn); - if (shdr64 == NULL) { - *error = DW_DLE_ELF_GETSHDR_ERROR; - return DW_DLV_ERROR; - } - - ret_scn->size = shdr64->sh_size; - ret_scn->addr = shdr64->sh_addr; - ret_scn->link = shdr64->sh_link; - - ret_scn->name = elf_strptr(obj->elf, obj->ehdr64->e_shstrndx, - shdr64->sh_name); - if(ret_scn->name == NULL) { - *error = DW_DLE_ELF_STRPTR_ERROR; - return DW_DLV_ERROR; - } - return DW_DLV_OK; -#else - *error = DW_DLE_MISSING_ELF64_SUPPORT; - return DW_DLV_ERROR; -#endif /* HAVE_ELF64_GETSHDR */ - } - if ((shdr32 = elf32_getshdr(scn)) == NULL) { - *error = DW_DLE_ELF_GETSHDR_ERROR; - return DW_DLV_ERROR; - } - - ret_scn->size = shdr32->sh_size; - ret_scn->addr = shdr32->sh_addr; - ret_scn->link = shdr32->sh_link; - - ret_scn->name = elf_strptr(obj->elf, obj->ehdr32->e_shstrndx, - shdr32->sh_name); - if (ret_scn->name == NULL) { - *error = DW_DLE_ELF_STRPTR_ERROR; - return DW_DLV_ERROR; - } - return DW_DLV_OK; -} - -/* - dwarf_elf_object_access_get_length_size - */ -static -Dwarf_Small -dwarf_elf_object_access_get_length_size(void* obj_in) -{ - dwarf_elf_object_access_internals_t*obj = - (dwarf_elf_object_access_internals_t*)obj_in; - return obj->length_size; -} - -/* - dwarf_elf_object_access_get_pointer_size - */ -static -Dwarf_Small -dwarf_elf_object_access_get_pointer_size(void* obj_in) -{ - dwarf_elf_object_access_internals_t*obj = - (dwarf_elf_object_access_internals_t*)obj_in; - return obj->pointer_size; -} - -#define MATCH_REL_SEC(i_,s_,r_) \ -if(i_ == s_.dss_index) { \ - *r_ = &s_; \ - return DW_DLV_OK; \ -} - -static int -find_section_to_relocate(Dwarf_Debug dbg,Dwarf_Half section_index, - struct Dwarf_Section_s **relocatablesec, int *error) -{ - MATCH_REL_SEC(section_index,dbg->de_debug_info,relocatablesec); - MATCH_REL_SEC(section_index,dbg->de_debug_abbrev,relocatablesec); - MATCH_REL_SEC(section_index,dbg->de_debug_line,relocatablesec); - MATCH_REL_SEC(section_index,dbg->de_debug_loc,relocatablesec); - MATCH_REL_SEC(section_index,dbg->de_debug_aranges,relocatablesec); - MATCH_REL_SEC(section_index,dbg->de_debug_macinfo,relocatablesec); - MATCH_REL_SEC(section_index,dbg->de_debug_pubnames,relocatablesec); - MATCH_REL_SEC(section_index,dbg->de_debug_ranges,relocatablesec); - MATCH_REL_SEC(section_index,dbg->de_debug_frame,relocatablesec); - MATCH_REL_SEC(section_index,dbg->de_debug_frame_eh_gnu,relocatablesec); - MATCH_REL_SEC(section_index,dbg->de_debug_pubtypes,relocatablesec); - MATCH_REL_SEC(section_index,dbg->de_debug_funcnames,relocatablesec); - MATCH_REL_SEC(section_index,dbg->de_debug_typenames,relocatablesec); - MATCH_REL_SEC(section_index,dbg->de_debug_varnames,relocatablesec); - MATCH_REL_SEC(section_index,dbg->de_debug_weaknames,relocatablesec); - /* dbg-> de_debug_str,syms); */ - /* de_elf_symtab,syms); */ - /* de_elf_strtab,syms); */ - *error = DW_DLE_RELOC_SECTION_MISMATCH; - return DW_DLV_ERROR; - -} -#undef MATCH_REL_SEC - -static void -get_rela_elf32(Dwarf_Small *data, unsigned int i, - int endianness, - int machine, struct Dwarf_Elf_Rela *relap) -{ - Elf32_Rela *relp = (Elf32_Rela*)(data + (i * sizeof(Elf32_Rela))); - relap->r_offset = relp->r_offset; - /* - relap->r_info = relp->r_info; - */ - relap->r_type = ELF32_R_TYPE(relp->r_info); - relap->r_symidx = ELF32_R_SYM(relp->r_info); - relap->r_addend = relp->r_addend; -} - -static void -get_rela_elf64(Dwarf_Small *data, unsigned int i, - int endianness, - int machine,struct Dwarf_Elf_Rela *relap) -{ -#ifdef HAVE_ELF64_RELA - Elf64_Rela * relp = (Elf64_Rela*)(data + (i * sizeof(Elf64_Rela))); - relap->r_offset = relp->r_offset; - /* - relap->r_info = relp->r_info; - */ - if(machine == EM_MIPS && endianness == DW_OBJECT_LSB ) { - /* This is really wierd. Treat this very specially. - The Elf64 LE MIPS object used for - testing (that has rela) wants the - values as sym ssym type3 type2 type, treating - each value as independent value. But libelf xlate - treats it as something else so we fudge here. - It is unclear - how to precisely characterize where these relocations - were used. - SGI MIPS on IRIX never used .rela relocations. - The BE 64bit elf MIPS test object with rela uses traditional - elf relocation layouts, not this special case. */ -#define ELF64MIPS_REL_SYM(i) ((i) & 0xffffffff) -#define ELF64MIPS_REL_TYPE(i) ((i >> 56) &0xff) - /* We ignore the special TYPE2 and TYPE3, they should be - value R_MIPS_NONE in rela. */ - relap->r_type = ELF64MIPS_REL_TYPE(relp->r_info); - relap->r_symidx = ELF64MIPS_REL_SYM(relp->r_info); -#undef MIPS64SYM -#undef MIPS64TYPE - } else - { - relap->r_type = ELF64_R_TYPE(relp->r_info); - relap->r_symidx = ELF64_R_SYM(relp->r_info); - } - relap->r_addend = relp->r_addend; -#endif -} - -static void -get_relocations_array(Dwarf_Bool is_64bit, - int endianness, - int machine, - Dwarf_Small *data, - unsigned int num_relocations, - struct Dwarf_Elf_Rela *relap) -{ - unsigned int i = 0; - void (*get_relocations)(Dwarf_Small *data, unsigned int i, - int endianness, - int machine, - struct Dwarf_Elf_Rela *relap); - - /* Handle 32/64 bit issue - */ - if (is_64bit) { - get_relocations = get_rela_elf64; - } else { - get_relocations = get_rela_elf32; - } - - for (i=0; i < num_relocations; i++) { - get_relocations(data, i,endianness,machine, &(relap[i])); - } - -} - -static int -get_relocation_entries(Dwarf_Bool is_64bit, - int endianness, - int machine, - Dwarf_Small *relocation_section, - Dwarf_Unsigned relocation_section_size, - struct Dwarf_Elf_Rela **relas, - unsigned int *nrelas, - int *error) -{ - unsigned int relocation_size = 0; - - if (is_64bit) { -#ifdef HAVE_ELF64_RELA - relocation_size = sizeof(Elf64_Rela); -#else - *error = DW_DLE_MISSING_ELF64_SUPPORT; - return DW_DLV_ERROR; -#endif - } else { - relocation_size = sizeof(Elf32_Rela); - } - - if (relocation_section == NULL) { - *error = DW_DLE_RELOC_SECTION_PTR_NULL; - return(DW_DLV_ERROR); - } - - if ((relocation_section_size != 0)) { - size_t bytescount = 0; - if(relocation_section_size%relocation_size) { - *error = DW_DLE_RELOC_SECTION_LENGTH_ODD; - return DW_DLV_ERROR; - } - *nrelas = relocation_section_size/relocation_size; - bytescount = (*nrelas) * sizeof(struct Dwarf_Elf_Rela); - *relas = malloc(bytescount); - if (!*relas) { - *error = DW_DLE_MAF; - return(DW_DLV_ERROR); - } - memset(*relas,0,bytescount); - get_relocations_array(is_64bit,endianness,machine, relocation_section, - *nrelas, *relas); - } - return(DW_DLV_OK); -} - -static Dwarf_Bool -is_32bit_abs_reloc(unsigned int type, Dwarf_Half machine) -{ - Dwarf_Bool r = 0; - switch (machine) { -#if defined(EM_MIPS) && defined (R_MIPS_32) - case EM_MIPS: - r = (type == R_MIPS_32); - break; -#endif -#if defined(EM_SPARC32PLUS) && defined (R_SPARC_UA32) - case EM_SPARC32PLUS: - r = (type == R_SPARC_UA32); - break; -#endif -#if defined(EM_SPARCV9) && defined (R_SPARC_UA32) - case EM_SPARCV9: - r = (type == R_SPARC_UA32); - break; -#endif -#if defined(EM_SPARC) && defined (R_SPARC_UA32) - case EM_SPARC: - r = (type == R_SPARC_UA32); - break; -#endif -#if defined(EM_386) && defined (R_386_32) - case EM_386: - r = (type == R_386_32); - break; -#endif -#if defined(EM_IA_64) && defined (R_IA64_SECREL32LSB) - case EM_IA_64: - r = (type == R_IA64_SECREL32LSB); - break; -#endif -#if defined(EM_PPC64) && defined (R_PPC64_ADDR32) - case EM_PPC64: - r = (type == R_PPC64_ADDR32); - break; -#endif -#if defined(EM_PPC) && defined (R_PPC_ADDR32) - case EM_PPC: - r = (type == R_PPC_ADDR32); - break; -#endif -#if defined(EM_S390) && defined (R_390_32) - case EM_S390: - r = (type == R_390_32); - break; -#endif -#if defined(EM_X86_64) && defined (R_X86_64_32) - case EM_X86_64: - r = (type == R_X86_64_32); - break; -#endif - } - return r; -} - -static Dwarf_Bool -is_64bit_abs_reloc(unsigned int type, Dwarf_Half machine) -{ - Dwarf_Bool r = 0; - switch (machine) { -#if defined(EM_MIPS) && defined (R_MIPS_64) - case EM_MIPS: - r = (type == R_MIPS_64); - break; -#endif -#if defined(EM_SPARC32PLUS) && defined (R_SPARC_UA64) - case EM_SPARC32PLUS: - r = (type == R_SPARC_UA64); - break; -#endif -#if defined(EM_SPARCV9) && defined (R_SPARC_UA64) - case EM_SPARCV9: - r = (type == R_SPARC_UA64); - break; -#endif -#if defined(EM_SPARC) && defined (R_SPARC_UA64) - case EM_SPARC: - r = (type == R_SPARC_UA64); - break; -#endif -#if defined(EM_IA_64) && defined (R_IA64_SECREL32LSB) - case EM_IA_64: - r = (type == R_IA64_DIR64LSB); - break; -#endif -#if defined(EM_PPC64) && defined (R_PPC64_ADDR64) - case EM_PPC64: - r = (type == R_PPC64_ADDR64); - break; -#endif -#if defined(EM_S390) && defined (R_390_64) - case EM_S390: - r = (type == R_390_64); - break; -#endif -#if defined(EM_X86_64) && defined (R_X86_64_64) - case EM_X86_64: - r = (type == R_X86_64_64); - break; -#endif - } - return r; -} - - -static void -update_entry(Dwarf_Debug dbg, - Dwarf_Bool is_64bit, Dwarf_Endianness endianess, - Dwarf_Half machine, struct Dwarf_Elf_Rela *rela, - Dwarf_Small *target_section, Dwarf_Small *section_data) -{ - unsigned int type = 0; - unsigned int sym_idx = 0; -#ifdef HAVE_ELF64_SYM - Elf64_Sym sym_buf; - Elf64_Sym *sym = 0; -#else - Elf32_Sym sym_buf; - Elf32_Sym *sym = 0; -#endif - Elf32_Sym *sym32 = 0; - Dwarf_ufixed64 offset = 0; - Dwarf_sfixed64 addend = 0; - Dwarf_Unsigned reloc_size = 0; - - - /* Dwarf_Elf_Rela dereferencing */ - offset = rela->r_offset; - addend = rela->r_addend; - type = rela->r_type; - sym_idx = rela->r_symidx; - - if (is_64bit) { -#ifdef HAVE_ELF64_SYM - sym = &((Elf64_Sym*)section_data)[sym_idx]; -#endif - } else { - sym32 = &((Elf32_Sym*)section_data)[sym_idx]; - - /* Convert Elf32_Sym struct to Elf64_Sym struct. We point at - * an Elf64_Sym local variable (sym_buf) to allow us to use the - * same pointer (sym) for both 32-bit and 64-bit instances. - */ - sym = &sym_buf; - sym->st_name = sym32->st_name; - sym->st_info = sym32->st_info; - sym->st_other = sym32->st_other; - sym->st_shndx = sym32->st_shndx; - sym->st_value = sym32->st_value; - sym->st_size = sym32->st_size; - } - - /* Determine relocation size */ - if (is_32bit_abs_reloc(type, machine)) { - reloc_size = 4; - } else if (is_64bit_abs_reloc(type, machine)) { - reloc_size = 8; - } else { - return; - } - - - { - /* Assuming we do not need to do a READ_UNALIGNED here - at target_section + offset and add its value to - outval. Some ABIs say no read (for example MIPS), - but if some do then which ones? */ - Dwarf_Unsigned outval = sym->st_value + addend; - WRITE_UNALIGNED(dbg,target_section + offset, - &outval,sizeof(outval),reloc_size); - } -} - - - -static int -apply_rela_entries(Dwarf_Debug dbg, - Dwarf_Bool is_64bit, - Dwarf_Endianness endianess, - Dwarf_Half machine, - Dwarf_Small *target_section, - Dwarf_Small *symtab_section, - struct Dwarf_Elf_Rela *relas, unsigned int nrelas, - int *error) -{ - if ((target_section != NULL) && (relas != NULL)) { - unsigned int i; - for (i = 0; i < nrelas; i++) { - update_entry(dbg, is_64bit, - endianess, - machine, - &(relas)[i], - target_section, - symtab_section); - } - } - return DW_DLV_OK; -} - - -static int -loop_through_relocations( - Dwarf_Debug dbg, - dwarf_elf_object_access_internals_t* obj, - struct Dwarf_Section_s *relocatablesec, - int *error) -{ - Dwarf_Small *target_section = 0; - Dwarf_Small *symtab_section = obj->symtab->dss_data; - Dwarf_Small *relocation_section = relocatablesec->dss_reloc_data; - Dwarf_Unsigned relocation_section_size = - relocatablesec->dss_reloc_size; - int ret = DW_DLV_ERROR; - struct Dwarf_Elf_Rela *relas = 0; - unsigned int nrelas = 0; - Dwarf_Small *mspace = 0; - - ret = get_relocation_entries(obj->is_64bit, - obj->endianness, - obj->machine, - relocation_section, - relocation_section_size, - &relas, &nrelas, error); - if(ret != DW_DLV_OK) { - free(relas); - return ret; - } - - /* Some systems read Elf in read-only memory via mmap or the like. - So the only safe thing is to copy the current data into - malloc space and refer to the malloc space instead of the - space returned by the elf library */ - mspace = malloc(relocatablesec->dss_size); - if(!mspace) { - *error = DW_DLE_RELOC_SECTION_MALLOC_FAIL; - return DW_DLV_ERROR; - } - memcpy(mspace,relocatablesec->dss_data,relocatablesec->dss_size); - relocatablesec->dss_data = mspace; - target_section = relocatablesec->dss_data; - relocatablesec->dss_data_was_malloc = 1; - - ret = apply_rela_entries( - dbg, - obj->is_64bit, - obj->endianness, obj->machine, - target_section, - symtab_section, - relas, nrelas, error); - - free(relas); - - return ret; -} - -/* - Find the section data in dbg and find all the relevant - sections. Then do relocations. -*/ -static int -dwarf_elf_object_relocate_a_section(void* obj_in, - Dwarf_Half section_index, - Dwarf_Debug dbg, - int* error) -{ - int res = DW_DLV_ERROR; - dwarf_elf_object_access_internals_t*obj = 0; - struct Dwarf_Section_s * relocatablesec = 0; - if (section_index == 0) { - return DW_DLV_NO_ENTRY; - } - obj = (dwarf_elf_object_access_internals_t*)obj_in; - - /* The section to relocate must already be loaded into memory. */ - res = find_section_to_relocate(dbg, section_index,&relocatablesec,error); - if(res != DW_DLV_OK) { - return res; - } - - /* Sun and possibly others do not always set sh_link in .debug_* sections. - So we cannot do full consistency checks. */ - if(relocatablesec->dss_reloc_index == 0 ) { - /* Something is wrong. */ - *error = DW_DLE_RELOC_SECTION_MISSING_INDEX; - return DW_DLV_ERROR; - } - /* Now load the relocations themselves. */ - res = dwarf_elf_object_access_load_section(obj_in, - relocatablesec->dss_reloc_index, - &relocatablesec->dss_reloc_data, error); - if(res != DW_DLV_OK) { - return res; - } - - /* Now get the symtab. */ - if (!obj->symtab) { - obj->symtab = &dbg->de_elf_symtab; - obj->strtab = &dbg->de_elf_strtab; - } - if( obj->symtab->dss_index != relocatablesec->dss_reloc_link) { - /* Something is wrong. */ - *error = DW_DLE_RELOC_MISMATCH_RELOC_INDEX; - return DW_DLV_ERROR; - } - if( obj->strtab->dss_index != obj->symtab->dss_link) { - /* Something is wrong. */ - *error = DW_DLE_RELOC_MISMATCH_STRTAB_INDEX; - return DW_DLV_ERROR; - } - if(!obj->symtab->dss_data) { - /* Now load the symtab */ - res = dwarf_elf_object_access_load_section(obj_in, - obj->symtab->dss_index, - &obj->symtab->dss_data, error); - if(res != DW_DLV_OK) { - return res; - } - } - if(! obj->strtab->dss_data) { - /* Now load the strtab */ - res = dwarf_elf_object_access_load_section(obj_in, - obj->strtab->dss_index, - &obj->strtab->dss_data,error); - if(res != DW_DLV_OK){ - return res; - } - } - - /* We have all the data we need in memory. */ - res = loop_through_relocations(dbg,obj,relocatablesec,error); - - return res; -} - -/* - dwarf_elf_object_access_load_section - */ -static int -dwarf_elf_object_access_load_section(void* obj_in, - Dwarf_Half section_index, - Dwarf_Small** section_data, - int* error) -{ - dwarf_elf_object_access_internals_t*obj = - (dwarf_elf_object_access_internals_t*)obj_in; - if (section_index == 0) { - return DW_DLV_NO_ENTRY; - } - - { - Elf_Scn *scn = 0; - Elf_Data *data = 0; - - scn = elf_getscn(obj->elf, section_index); - if (scn == NULL) { - *error = DW_DLE_MDE; - return DW_DLV_ERROR; - } - - /* - When using libelf as a producer, section data may be stored - in multiple buffers. In libdwarf however, we only use libelf - as a consumer (there is a dwarf producer API, but it doesn't - use libelf). Because of this, this single call to elf_getdata - will retrieve the entire section in a single contiguous - buffer. */ - data = elf_getdata(scn, NULL); - if (data == NULL) { - *error = DW_DLE_MDE; - return DW_DLV_ERROR; - } - *section_data = data->d_buf; - } - return DW_DLV_OK; -} - - -/* dwarf_elf_access method table. */ -static const struct Dwarf_Obj_Access_Methods_s dwarf_elf_object_access_methods = -{ - dwarf_elf_object_access_get_section_info, - dwarf_elf_object_access_get_byte_order, - dwarf_elf_object_access_get_length_size, - dwarf_elf_object_access_get_pointer_size, - dwarf_elf_object_access_get_section_count, - dwarf_elf_object_access_load_section, - dwarf_elf_object_relocate_a_section -}; - - -/* - Interface for the ELF object file implementation. - */ -int -dwarf_elf_object_access_init(dwarf_elf_handle elf, - int libdwarf_owns_elf, - Dwarf_Obj_Access_Interface** ret_obj, - int *err) -{ - int res = 0; - dwarf_elf_object_access_internals_t *internals = 0; - Dwarf_Obj_Access_Interface *intfc = 0; - - internals = malloc(sizeof(dwarf_elf_object_access_internals_t)); - if(!internals) { - /* Impossible case, we hope. Give up. */ - return DW_DLV_ERROR; - } - memset(internals,0,sizeof(*internals)); - res = dwarf_elf_object_access_internals_init(internals, elf, err); - if(res != DW_DLV_OK){ - free(internals); - return DW_DLV_ERROR; - } - internals->libdwarf_owns_elf = libdwarf_owns_elf; - - intfc = malloc(sizeof(Dwarf_Obj_Access_Interface)); - if(!intfc) { - /* Impossible case, we hope. Give up. */ - free(internals); - return DW_DLV_ERROR; - } - /* Initialize the interface struct */ - intfc->object = internals; - intfc->methods = &dwarf_elf_object_access_methods; - - *ret_obj = intfc; - return DW_DLV_OK; -} - - - -/* - Clean up the Dwarf_Obj_Access_Interface returned by elf_access_init. - */ -void -dwarf_elf_object_access_finish(Dwarf_Obj_Access_Interface* obj) -{ - if(!obj) { - return; - } - if(obj->object) { - dwarf_elf_object_access_internals_t *internals = - (dwarf_elf_object_access_internals_t *)obj->object; - if(internals->libdwarf_owns_elf){ - elf_end(internals->elf); - } - } - free(obj->object); - free(obj); -} - -/* - This function returns the Elf * pointer - associated with a Dwarf_Debug. - - This function only makes sense if ELF is implied. - */ -int -dwarf_get_elf(Dwarf_Debug dbg, dwarf_elf_handle * elf, - Dwarf_Error * error) -{ - struct Dwarf_Obj_Access_Interface_s * obj = 0; - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - - obj = dbg->de_obj_file; - if(obj) { - dwarf_elf_object_access_internals_t *internals = - (dwarf_elf_object_access_internals_t*)obj->object; - if(internals->elf == NULL) { - _dwarf_error(dbg, error, DW_DLE_FNO); - return (DW_DLV_ERROR); - } - *elf = internals->elf; - return DW_DLV_OK; - - } - _dwarf_error(dbg, error, DW_DLE_FNO); - return DW_DLV_ERROR; -} - - diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_elf_access.h b/usr/src/tools/ctf/dwarf/common/dwarf_elf_access.h deleted file mode 100644 index fd52c17938..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_elf_access.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef _DWARF_ELF_PORT_H -#define _DWARF_ELF_PORT_H -/* - - Copyright (C) 2008-2010 David Anderson. All rights reserved. - Portions Copyright 2008-2010 Arxan Technologies, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -/* ELF (usually libelf) object access for the generic object file interface */ - -int -dwarf_elf_object_access_init(dwarf_elf_handle elf , - int libdwarf_owns_elf, - Dwarf_Obj_Access_Interface** ret_obj, - int *err ); - -void -dwarf_elf_object_access_finish(Dwarf_Obj_Access_Interface* obj ); - -/* End ELF object access for the generic object file interface */ - - -#endif diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_error.c b/usr/src/tools/ctf/dwarf/common/dwarf_error.c deleted file mode 100644 index 7327529820..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_error.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - - Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2008-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "dwarf_incl.h" -#ifdef HAVE_ELF_H -#include -#endif - -#include -#include -#include -#include - -/* Array to hold string representation of errors. Any time a - define is added to the list in libdwarf.h, a string should be - added to this Array -*/ - -const char *_dwarf_errmsgs[] = { - - "No error (0)\n", - "DW_DLE_VMM 1 dwarf format/library version mismatch", - "DW_DLE_MAP 2 memory map failure", - "DW_DLE_LEE 3 libelf error", - "DW_DLE_NDS 4 no debug section", - "DW_DLE_NLS 5 no line section ", - "DW_DLE_ID 6 invalid descriptor for query ", - "DW_DLE_IOF 7 I/O failure ", - "DW_DLE_MAF 8 memory allocation failure ", - "DW_DLE_IA 9 invalid argument ", - "DW_DLE_MDE 10 mangled debugging entry ", - "DW_DLE_MLE 11 mangled line number entry ", - "DW_DLE_FNO 12 file not open ", - "DW_DLE_FNR 13 file not a regular file ", - "DW_DLE_FWA 14 file open with wrong access ", - "DW_DLE_NOB 15 not an object file ", - "DW_DLE_MOF 16 mangled object file header ", - "DW_DLE_EOLL 17 end of location list entries ", - "DW_DLE_NOLL 18 no location list section ", - "DW_DLE_BADOFF 19 Invalid offset ", - "DW_DLE_EOS 20 end of section ", - "DW_DLE_ATRUNC 21 abbreviations section appears truncated", - "DW_DLE_BADBITC 22 Address size passed to dwarf bad", - - "DW_DLE_DBG_ALLOC 23 Unable to malloc a Dwarf_Debug structure", - "DW_DLE_FSTAT_ERROR 24 The file fd passed to dwarf_init " - "cannot be fstat()ed", - "DW_DLE_FSTAT_MODE_ERROR 25 The file mode bits do not " - "indicate that the file being opened via " - "dwarf_init() is a normal file", - "DW_DLE_INIT_ACCESS_WRONG 26 A call to dwarf_init had an " - "access of other than DW_DLC_READ", - "DW_DLE_ELF_BEGIN_ERROR 27 a call to " - "elf_begin(... ELF_C_READ_MMAP... ) failed", - "DW_DLE_ELF_GETEHDR_ERROR 28 a call to " - "elf32_getehdr() or elf64_getehdr() failed", - "DW_DLE_ELF_GETSHDR_ERROR 29 a call to " - "elf32_getshdr() or elf64_getshdr() failed", - "DW_DLE_ELF_STRPTR_ERROR 30 a call to " - "elf_strptr() failed trying to get a section name", - "DW_DLE_DEBUG_INFO_DUPLICATE 31 Only one .debug_info " - "section is allowed", - "DW_DLE_DEBUG_INFO_NULL 32 .debug_info section present but " - "elf_getdata() failed or section is zero-length", - "DW_DLE_DEBUG_ABBREV_DUPLICATE 33 Only one .debug_abbrev " - "section is allowed", - "DW_DLE_DEBUG_ABBREV_NULL 34 .debug_abbrev section present but " - "elf_getdata() failed or section is zero-length", - "DW_DLE_DEBUG_ARANGES_DUPLICATE 35 Only one .debug_aranges " - "section is allowed", - "DW_DLE_DEBUG_ARANGES_NULL 36 .debug_aranges section present but " - "elf_getdata() failed or section is zero-length", - "DW_DLE_DEBUG_LINE_DUPLICATE 37 Only one .debug_line " - "section is allowed", - "DW_DLE_DEBUG_LINE_NULL (38) .debug_line section present but " - "elf_getdata() failed or section is zero-length", - "DW_DLE_DEBUG_LOC_DUPLICATE (39) Only one .debug_loc " - "section is allowed", - "DW_DLE_DEBUG_LOC_NULL (40) .debug_loc section present but " - "elf_getdata() failed or section is zero-length", - "DW_DLE_DEBUG_MACINFO_DUPLICATE (41) Only one .debug_macinfo " - "section is allowed", - "DW_DLE_DEBUG_MACINFO_NULL (42) .debug_macinfo section present but " - "elf_getdata() failed or section is zero-length", - "DW_DLE_DEBUG_PUBNAMES_DUPLICATE (43) Only one .debug_pubnames " - "section is allowed", - "DW_DLE_DEBUG_PUBNAMES_NULL (44) .debug_pubnames section present but " - "elf_getdata() failed or section is zero-length", - "DW_DLE_DEBUG_STR_DUPLICATE (45) Only one .debug_str " - "section is allowed", - "DW_DLE_DEBUG_STR_NULL (46) .debug_str section present but " - "elf_getdata() failed or section is zero-length", - "DW_DLE_CU_LENGTH_ERROR (47)", - "DW_DLE_VERSION_STAMP_ERROR (48)", - "DW_DLE_ABBREV_OFFSET_ERROR (49)", - "DW_DLE_ADDRESS_SIZE_ERROR (50)", - "DW_DLE_DEBUG_INFO_PTR_NULL (51)", - "DW_DLE_DIE_NULL (52)", - "DW_DLE_STRING_OFFSET_BAD (53)", - "DW_DLE_DEBUG_LINE_LENGTH_BAD (54)", - "DW_DLE_LINE_PROLOG_LENGTH_BAD (55)", - "DW_DLE_LINE_NUM_OPERANDS_BAD", - "DW_DLE_LINE_SET_ADDR_ERROR", - "DW_DLE_LINE_EXT_OPCODE_BAD", - "DW_DLE_DWARF_LINE_NULL", - "DW_DLE_INCL_DIR_NUM_BAD", - "DW_DLE_LINE_FILE_NUM_BAD", - "DW_DLE_ALLOC_FAIL", - "DW_DLE_NO_CALLBACK_FUNC", - "DW_DLE_SECT_ALLOC", - "DW_DLE_FILE_ENTRY_ALLOC", - "DW_DLE_LINE_ALLOC", - "DW_DLE_FPGM_ALLOC", - "DW_DLE_INCDIR_ALLOC", - "DW_DLE_STRING_ALLOC", - "DW_DLE_CHUNK_ALLOC", - "DW_DLE_BYTEOFF_ERR", - "DW_DLE_CIE_ALLOC", - "DW_DLE_FDE_ALLOC", - "DW_DLE_REGNO_OVFL", - "DW_DLE_CIE_OFFS_ALLOC", - "DW_DLE_WRONG_ADDRESS", - "DW_DLE_EXTRA_NEIGHBORS", - "DW_DLE_WRONG_TAG", - "DW_DLE_DIE_ALLOC", - "DW_DLE_PARENT_EXISTS", - "DW_DLE_DBG_NULL", - "DW_DLE_DEBUGLINE_ERROR", - "DW_DLE_DEBUGFRAME_ERROR", - "DW_DLE_DEBUGINFO_ERROR", - "DW_DLE_ATTR_ALLOC", - "DW_DLE_ABBREV_ALLOC", - "DW_DLE_OFFSET_UFLW", - "DW_DLE_ELF_SECT_ERR", - "DW_DLE_DEBUG_FRAME_LENGTH_BAD", - "DW_DLE_FRAME_VERSION_BAD", - "DW_DLE_CIE_RET_ADDR_REG_ERROR", - "DW_DLE_FDE_NULL", - "DW_DLE_FDE_DBG_NULL", - "DW_DLE_CIE_NULL", - "DW_DLE_CIE_DBG_NULL", - "DW_DLE_FRAME_TABLE_COL_BAD", - "DW_DLE_PC_NOT_IN_FDE_RANGE", - "DW_DLE_CIE_INSTR_EXEC_ERROR", - "DW_DLE_FRAME_INSTR_EXEC_ERROR", - "DW_DLE_FDE_PTR_NULL", - "DW_DLE_RET_OP_LIST_NULL", - "DW_DLE_LINE_CONTEXT_NULL", - "DW_DLE_DBG_NO_CU_CONTEXT", - "DW_DLE_DIE_NO_CU_CONTEXT", - "DW_DLE_FIRST_DIE_NOT_CU", - "DW_DLE_NEXT_DIE_PTR_NULL", - "DW_DLE_DEBUG_FRAME_DUPLICATE Only one .debug_frame " - "section is allowed", - "DW_DLE_DEBUG_FRAME_NULL .debug_frame section present but " - "elf_getdata() failed or section is zero-length", - "DW_DLE_ABBREV_DECODE_ERROR", - "DW_DLE_DWARF_ABBREV_NULL", - "DW_DLE_ATTR_NULL", - "DW_DLE_DIE_BAD", - "DW_DLE_DIE_ABBREV_BAD", - "DW_DLE_ATTR_FORM_BAD", - "DW_DLE_ATTR_NO_CU_CONTEXT", - "DW_DLE_ATTR_FORM_SIZE_BAD", - "DW_DLE_ATTR_DBG_NULL", - "DW_DLE_BAD_REF_FORM", - "DW_DLE_ATTR_FORM_OFFSET_BAD", - "DW_DLE_LINE_OFFSET_BAD", - "DW_DLE_DEBUG_STR_OFFSET_BAD", - "DW_DLE_STRING_PTR_NULL", - "DW_DLE_PUBNAMES_VERSION_ERROR", - "DW_DLE_PUBNAMES_LENGTH_BAD", - "DW_DLE_GLOBAL_NULL", - "DW_DLE_GLOBAL_CONTEXT_NULL", - "DW_DLE_DIR_INDEX_BAD", - "DW_DLE_LOC_EXPR_BAD", - "DW_DLE_DIE_LOC_EXPR_BAD", - "DW_DLE_ADDR_ALLOC", - "DW_DLE_OFFSET_BAD", - "DW_DLE_MAKE_CU_CONTEXT_FAIL", - "DW_DLE_REL_ALLOC", - "DW_DLE_ARANGE_OFFSET_BAD", - "DW_DLE_SEGMENT_SIZE_BAD", - "DW_DLE_ARANGE_LENGTH_BAD", - "DW_DLE_ARANGE_DECODE_ERROR", - "DW_DLE_ARANGES_NULL", - "DW_DLE_ARANGE_NULL", - "DW_DLE_NO_FILE_NAME", - "DW_DLE_NO_COMP_DIR", - "DW_DLE_CU_ADDRESS_SIZE_BAD", - "DW_DLE_INPUT_ATTR_BAD", - "DW_DLE_EXPR_NULL", - "DW_DLE_BAD_EXPR_OPCODE", - "DW_DLE_EXPR_LENGTH_BAD", - "DW_DLE_MULTIPLE_RELOC_IN_EXPR", - "DW_DLE_ELF_GETIDENT_ERROR", - "DW_DLE_NO_AT_MIPS_FDE", - "DW_DLE_NO_CIE_FOR_FDE", - "DW_DLE_DIE_ABBREV_LIST_NULL", - "DW_DLE_DEBUG_FUNCNAMES_DUPLICATE", - "DW_DLE_DEBUG_FUNCNAMES_NULL .debug_funcnames section present but " - "elf_getdata() failed or section is zero-length", - "DW_DLE_DEBUG_FUNCNAMES_VERSION_ERROR", - "DW_DLE_DEBUG_FUNCNAMES_LENGTH_BAD", - "DW_DLE_FUNC_NULL", - "DW_DLE_FUNC_CONTEXT_NULL", - "DW_DLE_DEBUG_TYPENAMES_DUPLICATE", - "DW_DLE_DEBUG_TYPENAMES_NULL .debug_typenames section present but " - "elf_getdata() failed or section is zero-length", - "DW_DLE_DEBUG_TYPENAMES_VERSION_ERROR", - "DW_DLE_DEBUG_TYPENAMES_LENGTH_BAD", - "DW_DLE_TYPE_NULL", - "DW_DLE_TYPE_CONTEXT_NULL", - "DW_DLE_DEBUG_VARNAMES_DUPLICATE", - "DW_DLE_DEBUG_VARNAMES_NULL .debug_varnames section present but " - "elf_getdata() failed or section is zero-length", - "DW_DLE_DEBUG_VARNAMES_VERSION_ERROR", - "DW_DLE_DEBUG_VARNAMES_LENGTH_BAD", - "DW_DLE_VAR_NULL", - "DW_DLE_VAR_CONTEXT_NULL", - "DW_DLE_DEBUG_WEAKNAMES_DUPLICATE", - "DW_DLE_DEBUG_WEAKNAMES_NULL .debug_weaknames section present but " - "elf_getdata() failed or section is zero-length", - - "DW_DLE_DEBUG_WEAKNAMES_VERSION_ERROR", - "DW_DLE_DEBUG_WEAKNAMES_LENGTH_BAD", - "DW_DLE_WEAK_NULL", - "DW_DLE_WEAK_CONTEXT_NULL (175)", - "DW_DLE_LOCDESC_COUNT_WRONG (176)", - "DW_DLE_MACINFO_STRING_NULL (177)", - "DW_DLE_MACINFO_STRING_EMPTY (178)", - "DW_DLE_MACINFO_INTERNAL_ERROR_SPACE (179)", - "DW_DLE_MACINFO_MALLOC_FAIL (180)", - "DW_DLE_DEBUGMACINFO_ERROR (181)", - "DW_DLE_DEBUG_MACRO_LENGTH_BAD (182)", - "DW_DLE_DEBUG_MACRO_MAX_BAD (183)", - "DW_DLE_DEBUG_MACRO_INTERNAL_ERR (184)", - "DW_DLE_DEBUG_MACRO_MALLOC_SPACE (185)", - "DW_DLE_DEBUG_MACRO_INCONSISTENT (186)", - "DW_DLE_DF_NO_CIE_AUGMENTATION(187)", - "DW_DLE_DF_REG_NUM_TOO_HIGH(188)", - "DW_DLE_DF_MAKE_INSTR_NO_INIT(189)", - "DW_DLE_DF_NEW_LOC_LESS_OLD_LOC(190)", - "DW_DLE_DF_POP_EMPTY_STACK(191)", - "DW_DLE_DF_ALLOC_FAIL(192)", - "DW_DLE_DF_FRAME_DECODING_ERROR(193)", - "DW_DLE_DEBUG_LOC_SECTION_SHORT(194)", - "DW_DLE_FRAME_AUGMENTATION_UNKNOWN(195)", - "DW_DLE_PUBTYPE_CONTEXT(196)", - "DW_DLE_DEBUG_PUBTYPES_LENGTH_BAD(197)", - "DW_DLE_DEBUG_PUBTYPES_VERSION_ERROR(198)", - "DW_DLE_DEBUG_PUBTYPES_DUPLICATE(199)", - "DW_DLE_FRAME_CIE_DECODE_ERROR(200)", - "DW_DLE_FRAME_REGISTER_UNREPRESENTABLE(201)", - "DW_DLE_FRAME_REGISTER_COUNT_MISMATCH(202)", - "DW_DLE_LINK_LOOP(203)", - "DW_DLE_STRP_OFFSET_BAD(204)", - "DW_DLE_DEBUG_RANGES_DUPLICATE(205)", - "DW_DLE_DEBUG_RANGES_OFFSET_BAD(206)", - "DW_DLE_DEBUG_RANGES_MISSING_END(207)", - "DW_DLE_DEBUG_RANGES_OUT_OF_MEM(208)", - "DW_DLE_DEBUG_SYMTAB_ERR(209)", - "DW_DLE_DEBUG_STRTAB_ERR(210)", - "DW_DLE_RELOC_MISMATCH_INDEX(211)", - "DW_DLE_RELOC_MISMATCH_RELOC_INDEX(212)", - "DW_DLE_RELOC_MISMATCH_STRTAB_INDEX(213)", - "DW_DLE_RELOC_SECTION_MISMATCH(214)", - "DW_DLE_RELOC_SECTION_MISSING_INDEX(215)", - "DW_DLE_RELOC_SECTION_LENGTH_ODD(216)", - "DW_DLE_RELOC_SECTION_PTR_NULL(217)", - "DW_DLE_RELOC_SECTION_MALLOC_FAIL(218)", - "DW_DLE_NO_ELF64_SUPPORT(219)", - "DW_DLE_MISSING_ELF64_SUPPORT(220)", - "DW_DLE_ORPHAN_FDE(221)", - "DW_DLE_DUPLICATE_INST_BLOCK(222)", - "DW_DLE_BAD_REF_SIG8_FORM(223)", - "DW_DLE_ATTR_EXPRLOC_FORM_BAD(224)", - "DW_DLE_FORM_SEC_OFFSET_LENGTH_BAD(225)", - "DW_DLE_NOT_REF_FORM(226)", - "DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE(227)" -}; - - - - -/* - This function performs error handling as described in the - libdwarf consumer document section 3. Dbg is the Dwarf_debug - structure being processed. Error is a pointer to the pointer - to the error descriptor that will be returned. Errval is an - error code listed in dwarf_error.h. -*/ -void -_dwarf_error(Dwarf_Debug dbg, Dwarf_Error * error, Dwarf_Sword errval) -{ - Dwarf_Error errptr; - - /* - Allow NULL dbg on entry, since sometimes that can happen and we - want to report the upper-level error, not this one. */ - if (error != NULL) { - - /* - If dbg is NULL, use the alternate error struct. However, - this will overwrite the earlier error. */ - if (dbg != NULL) { - errptr = - (Dwarf_Error) _dwarf_get_alloc(dbg, DW_DLA_ERROR, 1); - if (errptr == NULL) { - fprintf(stderr, - "Could not allocate Dwarf_Error structure, " - "abort() in libdwarf.\n"); - abort(); - } - } else { - /* We have no dbg to work with. dwarf_init failed. We hack - up a special area. */ - errptr = _dwarf_special_no_dbg_error_malloc(); - if (errptr == NULL) { - fprintf(stderr, - "Could not allocate Dwarf_Error structure, " - "abort() in libdwarf..\n"); - abort(); - } - } - - errptr->er_errval = errval; - *error = errptr; - return; - } - - if (dbg != NULL && dbg->de_errhand != NULL) { - errptr = (Dwarf_Error) _dwarf_get_alloc(dbg, DW_DLA_ERROR, 1); - if (errptr == NULL) { - fprintf(stderr, "Could not allocate Dwarf_Error structure," - " abort() in libdwarf.\n"); - abort(); - } - errptr->er_errval = errval; - dbg->de_errhand(errptr, dbg->de_errarg); - return; - } - fprintf(stderr, - "abort() in libdwarf. No error argument, no handler.\n"); - abort(); -} - - -Dwarf_Unsigned -dwarf_errno(Dwarf_Error error) -{ - if (error == NULL) { - return (0); - } - - return (error->er_errval); -} - - -/* -*/ -char * -dwarf_errmsg(Dwarf_Error error) -{ - if (error == NULL) { - return "Dwarf_Error is NULL"; - } - - if (error->er_errval > (sizeof(_dwarf_errmsgs) / sizeof(char *))) { - return "Dwarf_Error value out of range"; - } - - return ((char *) _dwarf_errmsgs[error->er_errval]); -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_error.h b/usr/src/tools/ctf/dwarf/common/dwarf_error.h deleted file mode 100644 index 27acf70db0..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_error.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - - Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -void _dwarf_error(Dwarf_Debug dbg, Dwarf_Error * error, - Dwarf_Sword errval); - -struct Dwarf_Error_s { - Dwarf_Sword er_errval; -}; diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_form.c b/usr/src/tools/ctf/dwarf/common/dwarf_form.c deleted file mode 100644 index fcdd64230c..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_form.c +++ /dev/null @@ -1,963 +0,0 @@ -/* - - Copyright (C) 2000,2002,2004,2005 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. - Portions Copyright 2008-2010 David Anderson. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "dwarf_incl.h" -#include "dwarf_die_deliv.h" - -int -dwarf_hasform(Dwarf_Attribute attr, - Dwarf_Half form, - Dwarf_Bool * return_bool, Dwarf_Error * error) -{ - Dwarf_CU_Context cu_context = 0; - - if (attr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); - return (DW_DLV_ERROR); - } - - cu_context = attr->ar_cu_context; - if (cu_context == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); - return (DW_DLV_ERROR); - } - - if (cu_context->cc_dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); - return (DW_DLV_ERROR); - } - - *return_bool = (attr->ar_attribute_form == form); - return DW_DLV_OK; -} - -/* Not often called, we do not worry about efficiency here. - The dwarf_whatform() call does the sanity checks for us. -*/ -int -dwarf_whatform_direct(Dwarf_Attribute attr, - Dwarf_Half * return_form, Dwarf_Error * error) -{ - int res = dwarf_whatform(attr, return_form, error); - - if (res != DW_DLV_OK) { - return res; - } - - *return_form = attr->ar_attribute_form_direct; - return (DW_DLV_OK); -} -void * -dwarf_uncompress_integer_block( - Dwarf_Debug dbg, - Dwarf_Bool unit_is_signed, - Dwarf_Small unit_length_in_bits, - void* input_block, - Dwarf_Unsigned input_length_in_bytes, - Dwarf_Unsigned* output_length_in_units_ptr, - Dwarf_Error* error -) -{ - Dwarf_Unsigned output_length_in_units = 0; - void * output_block = 0; - int i = 0; - char * ptr = 0; - int remain = 0; - Dwarf_sfixed * array = 0; - - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_DBG_NULL); - return((void *)DW_DLV_BADADDR); - } - - if (unit_is_signed == false || - unit_length_in_bits != 32 || - input_block == NULL || - input_length_in_bytes == 0 || - output_length_in_units_ptr == NULL) { - - _dwarf_error(NULL, error, DW_DLE_BADBITC); - return ((void *) DW_DLV_BADADDR); - } - - /* At this point we assume the format is: signed 32 bit */ - - /* first uncompress everything to find the total size. */ - - output_length_in_units = 0; - remain = input_length_in_bytes; - ptr = input_block; - while (remain > 0) { - Dwarf_Signed num; - Dwarf_Word len; - num = _dwarf_decode_s_leb128((unsigned char *)ptr, &len); - ptr += len; - remain -= len; - output_length_in_units++; - } - - if (remain != 0) { - _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL); - return((void *)DW_DLV_BADADDR); - } - - /* then alloc */ - - output_block = (void *) - _dwarf_get_alloc(dbg, - DW_DLA_STRING, - output_length_in_units * (unit_length_in_bits / 8)); - if (output_block == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return((void*)DW_DLV_BADADDR); - } - - /* then uncompress again and copy into new buffer */ - - array = (Dwarf_sfixed *) output_block; - remain = input_length_in_bytes; - ptr = input_block; - for (i=0; i0; i++) { - Dwarf_Signed num; - Dwarf_Word len; - num = _dwarf_decode_s_leb128((unsigned char *)ptr, &len); - ptr += len; - remain -= len; - array[i] = num; - } - - if (remain != 0) { - dwarf_dealloc(dbg, (unsigned char *)output_block, DW_DLA_STRING); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return((Dwarf_P_Attribute)DW_DLV_BADADDR); - } - - *output_length_in_units_ptr = output_length_in_units; - return output_block; -} - -void -dwarf_dealloc_uncompressed_block(Dwarf_Debug dbg, void * space) -{ - dwarf_dealloc(dbg, space, DW_DLA_STRING); -} - - -int -dwarf_whatform(Dwarf_Attribute attr, - Dwarf_Half * return_form, Dwarf_Error * error) -{ - Dwarf_CU_Context cu_context = 0; - - if (attr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); - return (DW_DLV_ERROR); - } - - cu_context = attr->ar_cu_context; - if (cu_context == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); - return (DW_DLV_ERROR); - } - - if (cu_context->cc_dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); - return (DW_DLV_ERROR); - } - - *return_form = attr->ar_attribute_form; - return (DW_DLV_OK); -} - - -/* - This function is analogous to dwarf_whatform. - It returns the attribute in attr instead of - the form. -*/ -int -dwarf_whatattr(Dwarf_Attribute attr, - Dwarf_Half * return_attr, Dwarf_Error * error) -{ - Dwarf_CU_Context cu_context = 0; - - if (attr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); - return (DW_DLV_ERROR); - } - - cu_context = attr->ar_cu_context; - if (cu_context == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); - return (DW_DLV_ERROR); - } - - if (cu_context->cc_dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); - return (DW_DLV_ERROR); - } - - *return_attr = (attr->ar_attribute); - return DW_DLV_OK; -} - - -/* - A global offset cannot be returned by this interface: - see dwarf_global_formref(). - - DW_FORM_ref_addr is considered an incorrect form - for this call because DW_FORM_ref_addr is a global-offset into - the debug_info section. - - For the same reason DW_FORM_data4/data8 are not returned - from this function. - - For the same reason DW_FORM_sec_offset is not returned - from this function, DW_FORM_sec_offset is a global offset - (to various sections, not a CU relative offset. - - DW_FORM_ref_addr has a value which was documented in - DWARF2 as address-size but which was always an offset - so should have always been offset size (wording - corrected in DWARF3). - - -*/ -int -dwarf_formref(Dwarf_Attribute attr, - Dwarf_Off * ret_offset, Dwarf_Error * error) -{ - Dwarf_Debug dbg = 0; - Dwarf_Unsigned offset = 0; - Dwarf_CU_Context cu_context = 0; - - - if (attr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); - return (DW_DLV_ERROR); - } - - cu_context = attr->ar_cu_context; - if (cu_context == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); - return (DW_DLV_ERROR); - } - - if (cu_context->cc_dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); - return (DW_DLV_ERROR); - } - dbg = cu_context->cc_dbg; - - switch (attr->ar_attribute_form) { - - case DW_FORM_ref1: - offset = *(Dwarf_Small *) attr->ar_debug_info_ptr; - break; - - case DW_FORM_ref2: - READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, - attr->ar_debug_info_ptr, sizeof(Dwarf_Half)); - break; - - case DW_FORM_ref4: - READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, - attr->ar_debug_info_ptr, sizeof(Dwarf_ufixed)); - break; - - case DW_FORM_ref8: - READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, - attr->ar_debug_info_ptr, sizeof(Dwarf_Unsigned)); - break; - - case DW_FORM_ref_udata: - offset = _dwarf_decode_u_leb128(attr->ar_debug_info_ptr, NULL); - break; - - default: - _dwarf_error(dbg, error, DW_DLE_BAD_REF_FORM); - return (DW_DLV_ERROR); - } - - /* Check that offset is within current cu portion of .debug_info. */ - if (offset >= cu_context->cc_length + - cu_context->cc_length_size + cu_context->cc_extension_size) { - _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_OFFSET_BAD); - return (DW_DLV_ERROR); - } - - *ret_offset = (offset); - return DW_DLV_OK; -} - -/* dwarf_formsig8 returns in the caller-provided 8 byte area - the 8 bytes of a DW_FORM_ref_sig8 (copying the bytes - directly to the caller). Not a string, an 8 byte - MD5 hash. This function is new in DWARF4 libdwarf. -*/ -int dwarf_formsig8(Dwarf_Attribute attr, - Dwarf_Sig8 * returned_sig_bytes, - Dwarf_Error* error) -{ - Dwarf_Debug dbg = 0; - Dwarf_Unsigned field_end_offset = 0; - Dwarf_CU_Context cu_context = 0; - - - if (attr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); - return (DW_DLV_ERROR); - } - - cu_context = attr->ar_cu_context; - if (cu_context == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); - return (DW_DLV_ERROR); - } - - if (cu_context->cc_dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); - return (DW_DLV_ERROR); - } - dbg = cu_context->cc_dbg; - - if(attr->ar_attribute_form != DW_FORM_ref_sig8 ) { - _dwarf_error(dbg, error, DW_DLE_BAD_REF_SIG8_FORM); - return (DW_DLV_ERROR); - } - - field_end_offset = attr->ar_debug_info_ptr + sizeof(Dwarf_Sig8) - - (dbg->de_debug_info.dss_data + cu_context->cc_debug_info_offset); - /* Check that offset is within current cu portion of .debug_info. */ - if (field_end_offset > cu_context->cc_length + - cu_context->cc_length_size + cu_context->cc_extension_size) { - _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_OFFSET_BAD); - return (DW_DLV_ERROR); - } - - memcpy(returned_sig_bytes, attr->ar_debug_info_ptr, - sizeof(Dwarf_Sig8)); - return DW_DLV_OK; -} - - -/* - Since this returns section-relative debug_info offsets, - this can represent all REFERENCE forms correctly - and allows all applicable forms. - - DW_FORM_ref_addr has a value which was documented in - DWARF2 as address-size but which was always an offset - so should have always been offset size (wording - corrected in DWARF3). - - See the DWARF4 document for the 3 cases fitting - reference forms. The caller must determine which section the - reference 'points' to. The function added in November 2009, - dwarf_get_form_class(), helps in this regard. - -*/ -int -dwarf_global_formref(Dwarf_Attribute attr, - Dwarf_Off * ret_offset, Dwarf_Error * error) -{ - Dwarf_Debug dbg = 0; - Dwarf_Unsigned offset = 0; - Dwarf_Addr ref_addr = 0; - Dwarf_CU_Context cu_context = 0; - Dwarf_Half context_version = 0; - - if (attr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); - return (DW_DLV_ERROR); - } - - cu_context = attr->ar_cu_context; - if (cu_context == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); - return (DW_DLV_ERROR); - } - context_version = cu_context->cc_version_stamp; - - if (cu_context->cc_dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); - return (DW_DLV_ERROR); - } - dbg = cu_context->cc_dbg; - - switch (attr->ar_attribute_form) { - - case DW_FORM_ref1: - offset = *(Dwarf_Small *) attr->ar_debug_info_ptr; - goto fixoffset; - - case DW_FORM_ref2: - READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, - attr->ar_debug_info_ptr, sizeof(Dwarf_Half)); - goto fixoffset; - - case DW_FORM_ref4: - READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, - attr->ar_debug_info_ptr, sizeof(Dwarf_ufixed)); - goto fixoffset; - - case DW_FORM_ref8: - READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, - attr->ar_debug_info_ptr, sizeof(Dwarf_Unsigned)); - goto fixoffset; - - case DW_FORM_ref_udata: - offset = _dwarf_decode_u_leb128(attr->ar_debug_info_ptr, NULL); - - fixoffset: /* we have a local offset, make it - global */ - - /* check legality of offset */ - if (offset >= cu_context->cc_length + - cu_context->cc_length_size + - cu_context->cc_extension_size) { - _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_OFFSET_BAD); - return (DW_DLV_ERROR); - } - - /* globalize the offset */ - offset += cu_context->cc_debug_info_offset; - break; - /* The DWARF2 document did not make clear that - DW_FORM_data4( and 8) were references with - global offsets to some section. - That was first clearly documented in DWARF3. - In DWARF4 these two forms are no longer references. */ - case DW_FORM_data4: - if(context_version == DW_CU_VERSION4) { - _dwarf_error(dbg, error, DW_DLE_NOT_REF_FORM); - return (DW_DLV_ERROR); - } - READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, - attr->ar_debug_info_ptr, sizeof(Dwarf_ufixed)); - /* The offset is global. */ - break; - case DW_FORM_data8: - if(context_version == DW_CU_VERSION4) { - _dwarf_error(dbg, error, DW_DLE_NOT_REF_FORM); - return (DW_DLV_ERROR); - } - READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, - attr->ar_debug_info_ptr, sizeof(Dwarf_Unsigned)); - /* The offset is global. */ - break; - case DW_FORM_ref_addr: - case DW_FORM_sec_offset: - { - /* DW_FORM_sec_offset first exists in DWARF4.*/ - /* It is up to the caller to know what the offset - of DW_FORM_sec_offset refers to, - the offset is not going to refer to .debug_info! */ - unsigned length_size = cu_context->cc_length_size; - if(length_size == 4) { - READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, - attr->ar_debug_info_ptr, sizeof(Dwarf_ufixed)); - } else if (length_size == 8) { - READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, - attr->ar_debug_info_ptr, sizeof(Dwarf_Unsigned)); - } else { - _dwarf_error(dbg, error, DW_DLE_FORM_SEC_OFFSET_LENGTH_BAD); - return (DW_DLV_ERROR); - } - } - break; - - default: - _dwarf_error(dbg, error, DW_DLE_BAD_REF_FORM); - return (DW_DLV_ERROR); - } - - /* We do not know what section the offset refers to, so - we have no way to check it for correctness. */ - *ret_offset = offset; - return DW_DLV_OK; -} - - -int -dwarf_formaddr(Dwarf_Attribute attr, - Dwarf_Addr * return_addr, Dwarf_Error * error) -{ - Dwarf_Debug dbg = 0; - Dwarf_Addr ret_addr = 0; - Dwarf_CU_Context cu_context = 0; - - if (attr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); - return (DW_DLV_ERROR); - } - - cu_context = attr->ar_cu_context; - if (cu_context == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); - return (DW_DLV_ERROR); - } - - if (cu_context->cc_dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); - return (DW_DLV_ERROR); - } - dbg = cu_context->cc_dbg; - - if (attr->ar_attribute_form == DW_FORM_addr - /* || attr->ar_attribute_form == DW_FORM_ref_addr Allowance of - DW_FORM_ref_addr was a mistake. The value returned in that - case is NOT an address it is a global debug_info offset (ie, - not CU-relative offset within the CU in debug_info). The - Dwarf document refers to it as an address (misleadingly) in - sec 6.5.4 where it describes the reference form. It is - address-sized so that the linker can easily update it, but - it is a reference inside the debug_info section. No longer - allowed. */ - ) { - - READ_UNALIGNED(dbg, ret_addr, Dwarf_Addr, - attr->ar_debug_info_ptr, - cu_context->cc_address_size); - *return_addr = ret_addr; - return (DW_DLV_OK); - } - - _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD); - return (DW_DLV_ERROR); -} - - -int -dwarf_formflag(Dwarf_Attribute attr, - Dwarf_Bool * ret_bool, Dwarf_Error * error) -{ - Dwarf_CU_Context cu_context = 0; - - if (attr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); - return (DW_DLV_ERROR); - } - - cu_context = attr->ar_cu_context; - if (cu_context == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); - return (DW_DLV_ERROR); - } - - if (cu_context->cc_dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); - return (DW_DLV_ERROR); - } - if (attr->ar_attribute_form == DW_FORM_flag_present) { - /* Implicit means we don't read any data at all. Just - the existence of the Form does it. DWARF4. */ - *ret_bool = 1; - return (DW_DLV_OK); - } - - if (attr->ar_attribute_form == DW_FORM_flag) { - *ret_bool = (*(Dwarf_Small *) attr->ar_debug_info_ptr != 0); - return (DW_DLV_OK); - } - _dwarf_error(cu_context->cc_dbg, error, DW_DLE_ATTR_FORM_BAD); - return (DW_DLV_ERROR); -} - - -int -dwarf_formudata(Dwarf_Attribute attr, - Dwarf_Unsigned * return_uval, Dwarf_Error * error) -{ - Dwarf_Unsigned ret_value = 0; - Dwarf_Debug dbg = 0; - Dwarf_CU_Context cu_context = 0; - - if (attr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); - return (DW_DLV_ERROR); - } - - - cu_context = attr->ar_cu_context; - if (cu_context == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); - return (DW_DLV_ERROR); - } - - dbg = cu_context->cc_dbg; - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); - return (DW_DLV_ERROR); - } - - switch (attr->ar_attribute_form) { - - case DW_FORM_data1: - READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, - attr->ar_debug_info_ptr, sizeof(Dwarf_Small)); - *return_uval = ret_value; - return DW_DLV_OK; - - /* READ_UNALIGNED does the right thing as it reads - the right number bits and generates host order. - So we can just assign to *return_uval. */ - case DW_FORM_data2:{ - READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, - attr->ar_debug_info_ptr, sizeof(Dwarf_Half)); - *return_uval = ret_value; - return DW_DLV_OK; - } - - case DW_FORM_data4:{ - READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, - attr->ar_debug_info_ptr, - sizeof(Dwarf_ufixed)); - *return_uval = ret_value; - return DW_DLV_OK; - } - - case DW_FORM_data8:{ - READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, - attr->ar_debug_info_ptr, - sizeof(Dwarf_Unsigned)); - *return_uval = ret_value; - return DW_DLV_OK; - } - break; - case DW_FORM_udata: - ret_value = - (_dwarf_decode_u_leb128(attr->ar_debug_info_ptr, NULL)); - *return_uval = ret_value; - return DW_DLV_OK; - - - /* see bug 583450. We do not allow reading sdata from a udata - value. Caller can retry, calling sdata */ - - - default: - break; - } - _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD); - return (DW_DLV_ERROR); -} - - -int -dwarf_formsdata(Dwarf_Attribute attr, - Dwarf_Signed * return_sval, Dwarf_Error * error) -{ - Dwarf_Signed ret_value = 0; - Dwarf_Debug dbg = 0; - Dwarf_CU_Context cu_context = 0; - - if (attr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); - return (DW_DLV_ERROR); - } - - cu_context = attr->ar_cu_context; - if (cu_context == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); - return (DW_DLV_ERROR); - } - - dbg = cu_context->cc_dbg; - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); - return (DW_DLV_ERROR); - } - - switch (attr->ar_attribute_form) { - - case DW_FORM_data1: - *return_sval = (*(Dwarf_Sbyte *) attr->ar_debug_info_ptr); - return DW_DLV_OK; - - /* READ_UNALIGNED does not sign extend. - So we have to use a cast to get the - value sign extended in the right way for each case. */ - case DW_FORM_data2:{ - READ_UNALIGNED(dbg, ret_value, Dwarf_Signed, - attr->ar_debug_info_ptr, - sizeof(Dwarf_Shalf)); - *return_sval = (Dwarf_Shalf) ret_value; - return DW_DLV_OK; - - } - - case DW_FORM_data4:{ - READ_UNALIGNED(dbg, ret_value, Dwarf_Signed, - attr->ar_debug_info_ptr, - sizeof(Dwarf_sfixed)); - *return_sval = (Dwarf_sfixed) ret_value; - return DW_DLV_OK; - } - - case DW_FORM_data8:{ - READ_UNALIGNED(dbg, ret_value, Dwarf_Signed, - attr->ar_debug_info_ptr, - sizeof(Dwarf_Signed)); - *return_sval = (Dwarf_Signed) ret_value; - return DW_DLV_OK; - } - - case DW_FORM_sdata: - ret_value = - (_dwarf_decode_s_leb128(attr->ar_debug_info_ptr, NULL)); - *return_sval = ret_value; - return DW_DLV_OK; - - - /* see bug 583450. We do not allow reading sdata from a udata - value. Caller can retry, calling sdata */ - - - default: - break; - } - _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD); - return (DW_DLV_ERROR); -} - - -int -dwarf_formblock(Dwarf_Attribute attr, - Dwarf_Block ** return_block, Dwarf_Error * error) -{ - Dwarf_CU_Context cu_context = 0; - Dwarf_Debug dbg = 0; - Dwarf_Unsigned length = 0; - Dwarf_Small *data = 0; - Dwarf_Word leb128_length = 0; - Dwarf_Block *ret_block = 0; - - if (attr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); - return (DW_DLV_ERROR); - } - - cu_context = attr->ar_cu_context; - if (cu_context == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); - return (DW_DLV_ERROR); - } - - if (cu_context->cc_dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); - return (DW_DLV_ERROR); - } - dbg = cu_context->cc_dbg; - - switch (attr->ar_attribute_form) { - - case DW_FORM_block1: - length = *(Dwarf_Small *) attr->ar_debug_info_ptr; - data = attr->ar_debug_info_ptr + sizeof(Dwarf_Small); - break; - - case DW_FORM_block2: - READ_UNALIGNED(dbg, length, Dwarf_Unsigned, - attr->ar_debug_info_ptr, sizeof(Dwarf_Half)); - data = attr->ar_debug_info_ptr + sizeof(Dwarf_Half); - break; - - case DW_FORM_block4: - READ_UNALIGNED(dbg, length, Dwarf_Unsigned, - attr->ar_debug_info_ptr, sizeof(Dwarf_ufixed)); - data = attr->ar_debug_info_ptr + sizeof(Dwarf_ufixed); - break; - - case DW_FORM_block: - length = _dwarf_decode_u_leb128(attr->ar_debug_info_ptr, - &leb128_length); - data = attr->ar_debug_info_ptr + leb128_length; - break; - - default: - _dwarf_error(cu_context->cc_dbg, error, DW_DLE_ATTR_FORM_BAD); - return (DW_DLV_ERROR); - } - - /* Check that block lies within current cu in .debug_info. */ - if (attr->ar_debug_info_ptr + length >= - dbg->de_debug_info.dss_data + cu_context->cc_debug_info_offset + - cu_context->cc_length + cu_context->cc_length_size + - cu_context->cc_extension_size) { - _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_SIZE_BAD); - return (DW_DLV_ERROR); - } - - ret_block = (Dwarf_Block *) _dwarf_get_alloc(dbg, DW_DLA_BLOCK, 1); - if (ret_block == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - ret_block->bl_len = length; - ret_block->bl_data = (Dwarf_Ptr) data; - ret_block->bl_from_loclist = 0; - ret_block->bl_section_offset = data - dbg->de_debug_info.dss_data; - - - *return_block = ret_block; - return (DW_DLV_OK); -} - - -/* Contrary to long standing documentation, - The string pointer returned thru return_str must - never have dwarf_dealloc() applied to it. - Documentation fixed July 2005. -*/ -int -dwarf_formstring(Dwarf_Attribute attr, - char **return_str, Dwarf_Error * error) -{ - Dwarf_CU_Context cu_context = 0; - Dwarf_Debug dbg = 0; - Dwarf_Unsigned offset = 0; - int res = DW_DLV_ERROR; - - if (attr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); - return (DW_DLV_ERROR); - } - - cu_context = attr->ar_cu_context; - if (cu_context == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); - return (DW_DLV_ERROR); - } - - if (cu_context->cc_dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); - return (DW_DLV_ERROR); - } - dbg = cu_context->cc_dbg; - - if (attr->ar_attribute_form == DW_FORM_string) { - - void *begin = attr->ar_debug_info_ptr; - - if (0 == dbg->de_assume_string_in_bounds) { - /* Check that string lies within current cu in .debug_info. - */ - void *end = dbg->de_debug_info.dss_data + - cu_context->cc_debug_info_offset + - cu_context->cc_length + cu_context->cc_length_size + - cu_context->cc_extension_size; - if (0 == _dwarf_string_valid(begin, end)) { - _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_SIZE_BAD); - return (DW_DLV_ERROR); - } - } - *return_str = (char *) (begin); - return DW_DLV_OK; - } - - if (attr->ar_attribute_form == DW_FORM_strp) { - READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, - attr->ar_debug_info_ptr, - cu_context->cc_length_size); - - res = _dwarf_load_section(dbg, &dbg->de_debug_str,error); - if (res != DW_DLV_OK) { - return res; - } - if (0 == dbg->de_assume_string_in_bounds) { - /* Check that string lies within current cu in .debug_info. - */ - void *end = dbg->de_debug_str.dss_data + - dbg->de_debug_str.dss_size; - void*begin = dbg->de_debug_str.dss_data + offset; - if (0 == _dwarf_string_valid(begin, end)) { - _dwarf_error(dbg, error, DW_DLE_STRP_OFFSET_BAD); - return (DW_DLV_ERROR); - } - } - *return_str = (char *) (dbg->de_debug_str.dss_data + offset); - return DW_DLV_OK; - } - - _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD); - return (DW_DLV_ERROR); -} - -int -dwarf_formexprloc(Dwarf_Attribute attr, - Dwarf_Unsigned * return_exprlen, - Dwarf_Ptr * block_ptr, - Dwarf_Error * error) -{ - Dwarf_Debug dbg = 0; - Dwarf_CU_Context cu_context = 0; - - if (attr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); - return (DW_DLV_ERROR); - } - - cu_context = attr->ar_cu_context; - if (cu_context == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); - return (DW_DLV_ERROR); - } - - dbg = cu_context->cc_dbg; - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); - return (DW_DLV_ERROR); - } - - if (attr->ar_attribute_form == DW_FORM_exprloc ) { - Dwarf_Unsigned exprlen = - (_dwarf_decode_u_leb128(attr->ar_debug_info_ptr, NULL)); - Dwarf_Small * addr = attr->ar_debug_info_ptr; - *return_exprlen = exprlen; - *block_ptr = addr + exprlen; - return DW_DLV_OK; - - } - _dwarf_error(dbg, error, DW_DLE_ATTR_EXPRLOC_FORM_BAD); - return (DW_DLV_ERROR); -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_frame.c b/usr/src/tools/ctf/dwarf/common/dwarf_frame.c deleted file mode 100644 index 3a825ee925..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_frame.c +++ /dev/null @@ -1,2442 +0,0 @@ -/* - - Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the Crittenden Lane address. -*/ - - - - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include -#include -#include "dwarf_frame.h" -#include "dwarf_arange.h" /* Using Arange as a way to build a - list */ - -#define FDE_NULL_CHECKS_AND_SET_DBG(fde,dbg ) \ - do { \ - if ((fde) == NULL) { \ - _dwarf_error(NULL, error, DW_DLE_FDE_NULL); \ - return (DW_DLV_ERROR); \ - } \ - (dbg)= (fde)->fd_dbg; \ - if ((dbg) == NULL) { \ - _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);\ - return (DW_DLV_ERROR); \ - } } while (0) - - -#define MIN(a,b) (((a) < (b))? a:b) - -static void _dwarf_init_regrule_table(struct Dwarf_Reg_Rule_s *t1reg, - int last_reg_num, - int initial_value); -static int dwarf_initialize_fde_table(Dwarf_Debug dbg, - struct Dwarf_Frame_s *fde_table, - unsigned table_real_data_size, - Dwarf_Error * error); -static void dwarf_free_fde_table(struct Dwarf_Frame_s *fde_table); - -#if 0 -/* Only used for debugging libdwarf. */ -static void dump_frame_rule(char *msg, - struct Dwarf_Reg_Rule_s *reg_rule); -#endif - - - -/* - This function is the heart of the debug_frame stuff. Don't even - think of reading this without reading both the Libdwarf and - consumer API carefully first. This function basically executes - frame instructions contained in a Cie or an Fde, but does in a - number of different ways depending on the information sought. - Start_instr_ptr points to the first byte of the frame instruction - stream, and final_instr_ptr to the to the first byte after the - last. - - The offsets returned in the frame instructions are factored. That - is they need to be multiplied by either the code_alignment_factor - or the data_alignment_factor, as appropriate to obtain the actual - offset. This makes it possible to expand an instruction stream - without the corresponding Cie. However, when an Fde frame instr - sequence is being expanded there must be a valid Cie with a pointer - to an initial table row. - - - If successful, returns DW_DLV_OK - And sets returned_count thru the pointer - if make_instr is true. - If make_instr is false returned_count - should NOT be used by the caller (returned_count - is set to 0 thru the pointer by this routine...) - If unsuccessful, returns DW_DLV_ERROR - and sets returned_error to the error code - - It does not do a whole lot of input validation being a private - function. Please make sure inputs are valid. - - (1) If make_instr is true, it makes a list of pointers to - Dwarf_Frame_Op structures containing the frame instructions - executed. A pointer to this list is returned in ret_frame_instr. - Make_instr is true only when a list of frame instructions is to be - returned. In this case since we are not interested in the contents - of the table, the input Cie can be NULL. This is the only case - where the inpute Cie can be NULL. - - (2) If search_pc is true, frame instructions are executed till - either a location is reached that is greater than the search_pc_val - provided, or all instructions are executed. At this point the - last row of the table generated is returned in a structure. - A pointer to this structure is supplied in table. - - (3) This function is also used to create the initial table row - defined by a Cie. In this case, the Dwarf_Cie pointer cie, is - NULL. For an FDE, however, cie points to the associated Cie. - - make_instr - make list of frame instr? 0/1 - ret_frame_instr - Ptr to list of ptrs to frame instrs - search_pc - Search for a pc value? 0/1 - search_pc_val - Search for this pc value - initial_loc - Initial code location value. - start_instr_ptr - Ptr to start of frame instrs. - final_instr_ptr - Ptr just past frame instrs. - table - Ptr to struct with last row. - cie - Ptr to Cie used by the Fde. - Different cies may have distinct address-sizes, so the cie - is used, not de_pointer_size. - -*/ - -int -_dwarf_exec_frame_instr(Dwarf_Bool make_instr, - Dwarf_Frame_Op ** ret_frame_instr, - Dwarf_Bool search_pc, - Dwarf_Addr search_pc_val, - Dwarf_Addr initial_loc, - Dwarf_Small * start_instr_ptr, - Dwarf_Small * final_instr_ptr, - Dwarf_Frame table, - Dwarf_Cie cie, - Dwarf_Debug dbg, - Dwarf_Half reg_num_of_cfa, - Dwarf_Sword * returned_count, - int *returned_error) -{ -#define ERROR_IF_REG_NUM_TOO_HIGH(macreg,machigh_reg) \ - do { \ - if ((macreg) >= (machigh_reg) || (macreg) < 0) { \ - SIMPLE_ERROR_RETURN(DW_DLE_DF_REG_NUM_TOO_HIGH); \ - } \ - } /*CONSTCOND */ while(0) -#define SIMPLE_ERROR_RETURN(code) \ - free(localregtab); \ - *returned_error = code; \ - return DW_DLV_ERROR - - /* Sweeps the frame instructions. */ - Dwarf_Small *instr_ptr; - - /* Register numbers not limited to just 255, thus not using - Dwarf_Small. */ - typedef int reg_num_type; - - Dwarf_Unsigned factored_N_value; - Dwarf_Signed signed_factored_N_value; - Dwarf_Addr current_loc = initial_loc; /* code location/ - pc-value - corresponding to the - frame instructions. - Starts at zero when - the caller has no - value to pass in. */ - - /* Must be min de_pointer_size bytes and must be at least sizeof - Dwarf_ufixed */ - Dwarf_Unsigned adv_loc = 0; - - int reg_count = dbg->de_frame_reg_rules_entry_count; - struct Dwarf_Reg_Rule_s *localregtab = calloc(reg_count, - sizeof(struct - Dwarf_Reg_Rule_s)); - - struct Dwarf_Reg_Rule_s cfa_reg; - - - /* This is used to end executing frame instructions. */ - /* Becomes true when search_pc is true and current_loc */ - /* is greater than search_pc_val. */ - Dwarf_Bool search_over = false; - - /* Used by the DW_FRAME_advance_loc instr */ - /* to hold the increment in pc value. */ - Dwarf_Addr adv_pc; - - /* Contains the length in bytes of */ - /* an leb128 encoded number. */ - Dwarf_Word leb128_length; - - Dwarf_Half address_size = (cie)? cie->ci_address_size: - dbg->de_pointer_size; - - /* Counts the number of frame instructions executed. */ - Dwarf_Word instr_count = 0; - - /* - These contain the current fields of the current frame - instruction. */ - Dwarf_Small fp_base_op = 0; - Dwarf_Small fp_extended_op; - reg_num_type fp_register; - - /* The value in fp_offset may be signed, though we call it - unsigned. This works ok for 2-s complement arithmetic. */ - Dwarf_Unsigned fp_offset; - Dwarf_Off fp_instr_offset; - - /* - Stack_table points to the row (Dwarf_Frame ie) being pushed or - popped by a remember or restore instruction. Top_stack points to - the top of the stack of rows. */ - Dwarf_Frame stack_table = NULL; - Dwarf_Frame top_stack = NULL; - - /* - These are used only when make_instr is true. Curr_instr is a - pointer to the current frame instruction executed. - Curr_instr_ptr, head_instr_list, and curr_instr_list are used to - form a chain of Dwarf_Frame_Op structs. Dealloc_instr_ptr is - used to deallocate the structs used to form the chain. - Head_instr_block points to a contiguous list of pointers to the - Dwarf_Frame_Op structs executed. */ - Dwarf_Frame_Op *curr_instr; - Dwarf_Chain curr_instr_item, dealloc_instr_item; - Dwarf_Chain head_instr_chain = NULL; - Dwarf_Chain tail_instr_chain = NULL; - Dwarf_Frame_Op *head_instr_block; - - /* - These are the alignment_factors taken from the Cie provided. - When no input Cie is provided they are set to 1, because only - factored offsets are required. */ - Dwarf_Sword code_alignment_factor = 1; - Dwarf_Sword data_alignment_factor = 1; - - /* - This flag indicates when an actual alignment factor is needed. - So if a frame instruction that computes an offset using an - alignment factor is encountered when this flag is set, an error - is returned because the Cie did not have a valid augmentation. */ - Dwarf_Bool need_augmentation = false; - - Dwarf_Word i; - - /* Initialize first row from associated Cie. Using temp regs - explicity */ - - if (localregtab == 0) { - SIMPLE_ERROR_RETURN(DW_DLE_ALLOC_FAIL); - } - { - struct Dwarf_Reg_Rule_s *t1reg = localregtab; - struct Dwarf_Reg_Rule_s *t1end = t1reg + reg_count; - - if (cie != NULL && cie->ci_initial_table != NULL) { - struct Dwarf_Reg_Rule_s *t2reg = - cie->ci_initial_table->fr_reg; - - if (reg_count != cie->ci_initial_table->fr_reg_count) { - /* Should never happen, it makes no sense to have the - table sizes change. There is no real allowance for - the set of registers to change dynamically in a - single Dwarf_Debug (except the size can be set near - initial Dwarf_Debug creation time). */ - SIMPLE_ERROR_RETURN - (DW_DLE_FRAME_REGISTER_COUNT_MISMATCH); - } - - for (; t1reg < t1end; t1reg++, t2reg++) { - *t1reg = *t2reg; - } - cfa_reg = cie->ci_initial_table->fr_cfa_rule; - } else { - _dwarf_init_regrule_table(t1reg, - reg_count, - dbg->de_frame_rule_initial_value); - _dwarf_init_regrule_table(&cfa_reg, 1, - dbg->de_frame_rule_initial_value); - } - } - - /* - The idea here is that the code_alignment_factor and - data_alignment_factor which are needed for certain instructions - are valid only when the Cie has a proper augmentation string. So - if the augmentation is not right, only Frame instruction can be - read. */ - if (cie != NULL && cie->ci_augmentation != NULL) { - code_alignment_factor = cie->ci_code_alignment_factor; - data_alignment_factor = cie->ci_data_alignment_factor; - } else { - need_augmentation = !make_instr; - } - - instr_ptr = start_instr_ptr; - while ((instr_ptr < final_instr_ptr) && (!search_over)) { - Dwarf_Small instr = 0; - Dwarf_Small opcode = 0; - reg_num_type reg_no = 0; - - fp_instr_offset = instr_ptr - start_instr_ptr; - instr = *(Dwarf_Small *) instr_ptr; - instr_ptr += sizeof(Dwarf_Small); - - fp_base_op = (instr & 0xc0) >> 6; - if ((instr & 0xc0) == 0x00) { - opcode = instr; /* is really extended op */ - fp_extended_op = (instr & (~(0xc0))) & 0xff; - } else { - opcode = instr & 0xc0; /* is base op */ - fp_extended_op = 0; - } - - fp_register = 0; - fp_offset = 0; - switch (opcode) { - case DW_CFA_advance_loc: - { - /* base op */ - fp_offset = adv_pc = instr & DW_FRAME_INSTR_OFFSET_MASK; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - adv_pc = adv_pc * code_alignment_factor; - - search_over = search_pc && - (current_loc + adv_pc > search_pc_val); - /* If gone past pc needed, retain old pc. */ - if (!search_over) { - current_loc = current_loc + adv_pc; - } - break; - } - - case DW_CFA_offset: - { /* base op */ - reg_no = - (reg_num_type) (instr & DW_FRAME_INSTR_OFFSET_MASK); - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - - factored_N_value = - _dwarf_decode_u_leb128(instr_ptr, &leb128_length); - instr_ptr = instr_ptr + leb128_length; - - fp_register = reg_no; - fp_offset = factored_N_value; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - - localregtab[reg_no].ru_is_off = 1; - localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; - localregtab[reg_no].ru_register = reg_num_of_cfa; - localregtab[reg_no].ru_offset_or_block_len = - factored_N_value * data_alignment_factor; - - break; - } - - case DW_CFA_restore: - { /* base op */ - reg_no = (instr & DW_FRAME_INSTR_OFFSET_MASK); - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - - fp_register = reg_no; - - if (cie != NULL && cie->ci_initial_table != NULL) - localregtab[reg_no] = - cie->ci_initial_table->fr_reg[reg_no]; - else if (!make_instr) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_MAKE_INSTR_NO_INIT); - } - - break; - } - case DW_CFA_set_loc: - { - Dwarf_Addr new_loc = 0; - - READ_UNALIGNED(dbg, new_loc, Dwarf_Addr, - instr_ptr, address_size); - instr_ptr += address_size; - if (new_loc != 0 && current_loc != 0) { - /* Pre-relocation or before current_loc is set the - test comparing new_loc and current_loc makes no - sense. Testing for non-zero (above) is a way - (fallible) to check that current_loc, new_loc - are already relocated. */ - if (new_loc <= current_loc) { - /* Within a frame, address must increase. - Seemingly it has not. Seems to be an error. */ - - SIMPLE_ERROR_RETURN - (DW_DLE_DF_NEW_LOC_LESS_OLD_LOC); - } - } - - search_over = search_pc && (new_loc > search_pc_val); - - /* If gone past pc needed, retain old pc. */ - if (!search_over) { - current_loc = new_loc; - } - fp_offset = new_loc; - break; - } - - case DW_CFA_advance_loc1: - { - fp_offset = adv_loc = *(Dwarf_Small *) instr_ptr; - instr_ptr += sizeof(Dwarf_Small); - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - adv_loc *= code_alignment_factor; - - search_over = search_pc && - (current_loc + adv_loc > search_pc_val); - - /* If gone past pc needed, retain old pc. */ - if (!search_over) { - current_loc = current_loc + adv_loc; - } - break; - } - - case DW_CFA_advance_loc2: - { - READ_UNALIGNED(dbg, adv_loc, Dwarf_Unsigned, - instr_ptr, sizeof(Dwarf_Half)); - instr_ptr += sizeof(Dwarf_Half); - fp_offset = adv_loc; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - adv_loc *= code_alignment_factor; - - search_over = search_pc && - (current_loc + adv_loc > search_pc_val); - - /* If gone past pc needed, retain old pc. */ - if (!search_over) { - current_loc = current_loc + adv_loc; - } - break; - } - - case DW_CFA_advance_loc4: - { - READ_UNALIGNED(dbg, adv_loc, Dwarf_Unsigned, - instr_ptr, sizeof(Dwarf_ufixed)); - instr_ptr += sizeof(Dwarf_ufixed); - fp_offset = adv_loc; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - adv_loc *= code_alignment_factor; - - search_over = search_pc && - (current_loc + adv_loc > search_pc_val); - - /* If gone past pc needed, retain old pc. */ - if (!search_over) { - current_loc = current_loc + adv_loc; - } - break; - } - - case DW_CFA_offset_extended: - { - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);; - factored_N_value = - _dwarf_decode_u_leb128(instr_ptr, &leb128_length); - instr_ptr += leb128_length; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - localregtab[reg_no].ru_is_off = 1; - localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; - localregtab[reg_no].ru_register = reg_num_of_cfa; - localregtab[reg_no].ru_offset_or_block_len = factored_N_value * - data_alignment_factor; - - fp_register = reg_no; - fp_offset = factored_N_value; - break; - } - - case DW_CFA_restore_extended: - { - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - - if (cie != NULL && cie->ci_initial_table != NULL) { - localregtab[reg_no] = cie->ci_initial_table->fr_reg[reg_no]; - } else { - if (!make_instr) { - SIMPLE_ERROR_RETURN - (DW_DLE_DF_MAKE_INSTR_NO_INIT); - } - } - - fp_register = reg_no; - break; - } - - case DW_CFA_undefined: - { - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - - localregtab[reg_no].ru_is_off = 0; - localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; - localregtab[reg_no].ru_register = - dbg->de_frame_undefined_value_number; - localregtab[reg_no].ru_offset_or_block_len = 0; - - fp_register = reg_no; - break; - } - - case DW_CFA_same_value: - { - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - - localregtab[reg_no].ru_is_off = 0; - localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; - localregtab[reg_no].ru_register = - dbg->de_frame_same_value_number; - localregtab[reg_no].ru_offset_or_block_len = 0; - fp_register = reg_no; - break; - } - - case DW_CFA_register: - { - Dwarf_Unsigned lreg; - reg_num_type reg_noA = 0; - reg_num_type reg_noB = 0; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_noA = (reg_num_type) lreg; - - ERROR_IF_REG_NUM_TOO_HIGH(reg_noA, reg_count); - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_noB = (reg_num_type) lreg; - - if (reg_noB > reg_count) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_REG_NUM_TOO_HIGH); - } - - - localregtab[reg_noA].ru_is_off = 0; - localregtab[reg_noA].ru_value_type = DW_EXPR_OFFSET; - localregtab[reg_noA].ru_register = reg_noB; - localregtab[reg_noA].ru_offset_or_block_len = 0; - - fp_register = reg_noA; - fp_offset = reg_noB; - break; - } - - case DW_CFA_remember_state: - { - stack_table = (Dwarf_Frame) - _dwarf_get_alloc(dbg, DW_DLA_FRAME, 1); - if (stack_table == NULL) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL); - } - - for (i = 0; i < reg_count; i++) - stack_table->fr_reg[i] = localregtab[i]; - stack_table->fr_cfa_rule = cfa_reg; - - if (top_stack != NULL) - stack_table->fr_next = top_stack; - top_stack = stack_table; - - break; - } - - case DW_CFA_restore_state: - { - if (top_stack == NULL) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_POP_EMPTY_STACK); - } - stack_table = top_stack; - top_stack = stack_table->fr_next; - - for (i = 0; i < reg_count; i++) - localregtab[i] = stack_table->fr_reg[i]; - cfa_reg = stack_table->fr_cfa_rule; - - dwarf_dealloc(dbg, stack_table, DW_DLA_FRAME); - break; - } - - case DW_CFA_def_cfa: - { - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - - factored_N_value = - _dwarf_decode_u_leb128(instr_ptr, &leb128_length); - instr_ptr += leb128_length; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - cfa_reg.ru_is_off = 1; - cfa_reg.ru_value_type = DW_EXPR_OFFSET; - cfa_reg.ru_register = reg_no; - cfa_reg.ru_offset_or_block_len = factored_N_value; - - fp_register = reg_no; - fp_offset = factored_N_value; - break; - } - - case DW_CFA_def_cfa_register: - { - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - - cfa_reg.ru_register = reg_no; - /* Do NOT set ru_offset_or_block_len or ru_is_off here. - See dwarf2/3 spec. */ - fp_register = reg_no; - break; - } - - case DW_CFA_def_cfa_offset: - { - factored_N_value = - _dwarf_decode_u_leb128(instr_ptr, &leb128_length); - instr_ptr += leb128_length; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - /* Do set ru_is_off here, as here factored_N_value - counts. */ - cfa_reg.ru_is_off = 1; - cfa_reg.ru_value_type = DW_EXPR_OFFSET; - cfa_reg.ru_offset_or_block_len = factored_N_value; - - fp_offset = factored_N_value; - break; - } - case DW_CFA_nop: - { - break; - } - /* DWARF3 ops begin here. */ - case DW_CFA_def_cfa_expression: - { - /* A single DW_FORM_block representing a dwarf - expression. The form block establishes the way to - compute the CFA. */ - Dwarf_Unsigned block_len = 0; - - DECODE_LEB128_UWORD(instr_ptr, block_len); - cfa_reg.ru_is_off = 0; /* arbitrary */ - cfa_reg.ru_value_type = DW_EXPR_EXPRESSION; - cfa_reg.ru_offset_or_block_len = block_len; - cfa_reg.ru_block = instr_ptr; - fp_offset = (Dwarf_Unsigned)(uintptr_t)instr_ptr; - instr_ptr += block_len; - } - break; - case DW_CFA_expression: - { - /* An unsigned leb128 value is the first operand (a - register number). The second operand is single - DW_FORM_block representing a dwarf expression. The - evaluator pushes the CFA on the evaluation stack - then evaluates the expression to compute the value - of the register contents. */ - Dwarf_Unsigned lreg = 0; - Dwarf_Unsigned block_len = 0; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - DECODE_LEB128_UWORD(instr_ptr, block_len); - localregtab[lreg].ru_is_off = 0; /* arbitrary */ - localregtab[lreg].ru_value_type = DW_EXPR_EXPRESSION; - localregtab[lreg].ru_offset_or_block_len = block_len; - localregtab[lreg].ru_block = instr_ptr; - fp_offset = (Dwarf_Unsigned)(uintptr_t)instr_ptr; - fp_register = reg_no; - instr_ptr += block_len; - } - break; - case DW_CFA_offset_extended_sf: - { - /* The first operand is an unsigned leb128 register - number. The second is a signed factored offset. - Identical to DW_CFA_offset_extended except the - secondoperand is signed */ - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - signed_factored_N_value = - _dwarf_decode_s_leb128(instr_ptr, &leb128_length); - instr_ptr += leb128_length; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - localregtab[reg_no].ru_is_off = 1; - localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; - localregtab[reg_no].ru_register = reg_num_of_cfa; - localregtab[reg_no].ru_offset_or_block_len = - signed_factored_N_value * data_alignment_factor; - - fp_register = reg_no; - fp_offset = signed_factored_N_value; - } - break; - case DW_CFA_def_cfa_sf: - { - /* The first operand is an unsigned leb128 register - number. The second is a signed leb128 factored - offset. Identical to DW_CFA_def_cfa except that the - second operand is signed and factored. */ - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - - signed_factored_N_value = - _dwarf_decode_s_leb128(instr_ptr, &leb128_length); - instr_ptr += leb128_length; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - cfa_reg.ru_is_off = 1; - cfa_reg.ru_value_type = DW_EXPR_OFFSET; - cfa_reg.ru_register = reg_no; - cfa_reg.ru_offset_or_block_len = - signed_factored_N_value * data_alignment_factor; - - fp_register = reg_no; - fp_offset = signed_factored_N_value; - } - break; - case DW_CFA_def_cfa_offset_sf: - { - /* The operand is a signed leb128 operand representing - a factored offset. Identical to - DW_CFA_def_cfa_offset excep the operand is signed - and factored. */ - - signed_factored_N_value = - _dwarf_decode_s_leb128(instr_ptr, &leb128_length); - instr_ptr += leb128_length; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - /* Do set ru_is_off here, as here factored_N_value - counts. */ - cfa_reg.ru_is_off = 1; - cfa_reg.ru_value_type = DW_EXPR_OFFSET; - cfa_reg.ru_offset_or_block_len = - signed_factored_N_value * data_alignment_factor; - - fp_offset = signed_factored_N_value; - } - break; - case DW_CFA_val_offset: - { - /* The first operand is an unsigned leb128 register - number. The second is a factored unsigned offset. - Makes the register be a val_offset(N) rule with N = - factored_offset*data_alignment_factor. */ - - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - - factored_N_value = - _dwarf_decode_u_leb128(instr_ptr, &leb128_length); - instr_ptr += leb128_length; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - /* Do set ru_is_off here, as here factored_N_value - counts. */ - localregtab[reg_no].ru_is_off = 1; - localregtab[reg_no].ru_register = reg_num_of_cfa; - localregtab[reg_no].ru_value_type = DW_EXPR_VAL_OFFSET; - localregtab[reg_no].ru_offset_or_block_len = - factored_N_value * data_alignment_factor; - - fp_offset = factored_N_value; - break; - } - case DW_CFA_val_offset_sf: - { - /* The first operand is an unsigned leb128 register - number. The second is a factored signed offset. - Makes the register be a val_offset(N) rule with N = - factored_offset*data_alignment_factor. */ - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - signed_factored_N_value = - _dwarf_decode_s_leb128(instr_ptr, &leb128_length); - instr_ptr += leb128_length; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - /* Do set ru_is_off here, as here factored_N_value - counts. */ - localregtab[reg_no].ru_is_off = 1; - localregtab[reg_no].ru_value_type = DW_EXPR_VAL_OFFSET; - localregtab[reg_no].ru_offset_or_block_len = - signed_factored_N_value * data_alignment_factor; - - fp_offset = signed_factored_N_value; - - } - break; - case DW_CFA_val_expression: - { - /* The first operand is an unsigned leb128 register - number. The second is a DW_FORM_block representing a - DWARF expression. The rule for the register number - becomes a val_expression(E) rule. */ - Dwarf_Unsigned lreg = 0; - Dwarf_Unsigned block_len = 0; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - DECODE_LEB128_UWORD(instr_ptr, block_len); - localregtab[lreg].ru_is_off = 0; /* arbitrary */ - localregtab[lreg].ru_value_type = DW_EXPR_VAL_EXPRESSION; - localregtab[lreg].ru_offset_or_block_len = block_len; - localregtab[lreg].ru_block = instr_ptr; - fp_offset = (Dwarf_Unsigned)(uintptr_t)instr_ptr; - - instr_ptr += block_len; - fp_register = reg_no; - - } - break; - - /* END DWARF3 new ops. */ - - -#ifdef DW_CFA_GNU_window_save - case DW_CFA_GNU_window_save: - { - /* no information: this just tells unwinder to restore - the window registers from the previous frame's - window save area */ - break; - } -#endif -#ifdef DW_CFA_GNU_args_size - /* single uleb128 is the current arg area size in bytes. No - register exists yet to save this in */ - case DW_CFA_GNU_args_size: - { - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - - break; - } -#endif - default: - /* ERROR, we have an opcode we know nothing about. Memory - leak here, but an error like this is not supposed to - happen so we ignore the leak. These used to be ignored, - now we notice and report. */ - SIMPLE_ERROR_RETURN(DW_DLE_DF_FRAME_DECODING_ERROR); - - } - - if (make_instr) { - instr_count++; - - curr_instr = (Dwarf_Frame_Op *) - _dwarf_get_alloc(dbg, DW_DLA_FRAME_OP, 1); - if (curr_instr == NULL) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL); - } - - curr_instr->fp_base_op = fp_base_op; - curr_instr->fp_extended_op = fp_extended_op; - curr_instr->fp_register = fp_register; - curr_instr->fp_offset = fp_offset; - curr_instr->fp_instr_offset = fp_instr_offset; - - curr_instr_item = (Dwarf_Chain) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (curr_instr_item == NULL) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL); - } - - curr_instr_item->ch_item = curr_instr; - if (head_instr_chain == NULL) - head_instr_chain = tail_instr_chain = curr_instr_item; - else { - tail_instr_chain->ch_next = curr_instr_item; - tail_instr_chain = curr_instr_item; - } - } - } - - /* - If frame instruction decoding was right we would stop exactly at - final_instr_ptr. */ - if (instr_ptr > final_instr_ptr) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_FRAME_DECODING_ERROR); - } - - /* Fill in the actual output table, the space the caller passed in. */ - if (table != NULL) { - - struct Dwarf_Reg_Rule_s *t2reg = table->fr_reg; - struct Dwarf_Reg_Rule_s *t3reg = localregtab; - struct Dwarf_Reg_Rule_s *t3end = t3reg + reg_count; - - table->fr_loc = current_loc; - for (; t3reg < t3end; t3reg++, t2reg++) { - *t2reg = *t3reg; - } - - /* CONSTCOND */ - /* Do not update the main table with the cfa_reg. - Just leave cfa_reg as cfa_reg. */ - table->fr_cfa_rule = cfa_reg; - } - - /* Dealloc anything remaining on stack. */ - for (; top_stack != NULL;) { - stack_table = top_stack; - top_stack = top_stack->fr_next; - dwarf_dealloc(dbg, stack_table, DW_DLA_FRAME); - } - - if (make_instr) { - /* Allocate list of pointers to Dwarf_Frame_Op's. */ - head_instr_block = (Dwarf_Frame_Op *) - _dwarf_get_alloc(dbg, DW_DLA_FRAME_BLOCK, instr_count); - if (head_instr_block == NULL) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL); - } - - /* - Store pointers to Dwarf_Frame_Op's in this list and - deallocate the structs that chain the Dwarf_Frame_Op's. */ - curr_instr_item = head_instr_chain; - for (i = 0; i < instr_count; i++) { - *(head_instr_block + i) = - *(Dwarf_Frame_Op *) curr_instr_item->ch_item; - dealloc_instr_item = curr_instr_item; - curr_instr_item = curr_instr_item->ch_next; - dwarf_dealloc(dbg, dealloc_instr_item->ch_item, - DW_DLA_FRAME_OP); - dwarf_dealloc(dbg, dealloc_instr_item, DW_DLA_CHAIN); - } - *ret_frame_instr = head_instr_block; - - *returned_count = (Dwarf_Sword) instr_count; - } else { - *returned_count = 0; - } - free(localregtab); - return DW_DLV_OK; -#undef ERROR_IF_REG_NUM_TOO_HIGH -#undef SIMPLE_ERROR_RETURN -} - -/* Depending on version, either read the return address register - as a ubyte or as an leb number. - The form of this value changed for DWARF3. -*/ -Dwarf_Unsigned -_dwarf_get_return_address_reg(Dwarf_Small * frame_ptr, - int version, unsigned long *size) -{ - Dwarf_Unsigned uvalue = 0; - Dwarf_Word leb128_length = 0; - - if (version == 1) { - *size = 1; - uvalue = *(unsigned char *) frame_ptr; - return uvalue; - } - uvalue = _dwarf_decode_u_leb128(frame_ptr, &leb128_length); - *size = leb128_length; - return uvalue; -} - - -/* Trivial consumer function. -*/ -int -dwarf_get_cie_of_fde(Dwarf_Fde fde, - Dwarf_Cie * cie_returned, Dwarf_Error * error) -{ - if (fde == NULL) { - _dwarf_error(NULL, error, DW_DLE_FDE_NULL); - return (DW_DLV_ERROR); - } - - *cie_returned = fde->fd_cie; - return DW_DLV_OK; - -} - -int dwarf_get_cie_index( - Dwarf_Cie cie, - Dwarf_Signed* index, - Dwarf_Error* error ) -{ - if( cie == NULL ) - { - _dwarf_error(NULL, error, DW_DLE_CIE_NULL); - return (DW_DLV_ERROR); - } - - *index = cie->ci_index; - return (DW_DLV_OK); -} - - -/* - For g++ .eh_frame fde and cie. - the cie id is different as the - definition of the cie_id in an fde - is the distance back from the address of the - value to the cie. - Or 0 if this is a true cie. - Non standard dwarf, designed this way to be - convenient at run time for an allocated - (mapped into memory as part of the running image) section. -*/ -int -dwarf_get_fde_list_eh(Dwarf_Debug dbg, - Dwarf_Cie ** cie_data, - Dwarf_Signed * cie_element_count, - Dwarf_Fde ** fde_data, - Dwarf_Signed * fde_element_count, - Dwarf_Error * error) -{ - int res = _dwarf_load_section(dbg, &dbg->de_debug_frame_eh_gnu,error); - if (res != DW_DLV_OK) { - return res; - } - - res = _dwarf_get_fde_list_internal(dbg, - cie_data, - cie_element_count, - fde_data, - fde_element_count, - dbg->de_debug_frame_eh_gnu.dss_data, - dbg->de_debug_frame_eh_gnu.dss_index, - dbg->de_debug_frame_eh_gnu.dss_size, - /* cie_id_value */ 0, - /* use_gnu_cie_calc= */ 1, - error); - return res; -} - - - -/* - For standard dwarf .debug_frame - cie_id is -1 in a cie, and - is the section offset in the .debug_frame section - of the cie otherwise. Standard dwarf -*/ -int -dwarf_get_fde_list(Dwarf_Debug dbg, - Dwarf_Cie ** cie_data, - Dwarf_Signed * cie_element_count, - Dwarf_Fde ** fde_data, - Dwarf_Signed * fde_element_count, - Dwarf_Error * error) -{ - int res = _dwarf_load_section(dbg, &dbg->de_debug_frame,error); - if (res != DW_DLV_OK) { - return res; - } - - res = _dwarf_get_fde_list_internal(dbg, cie_data, - cie_element_count, - fde_data, - fde_element_count, - dbg->de_debug_frame.dss_data, - dbg->de_debug_frame.dss_index, - dbg->de_debug_frame.dss_size, - DW_CIE_ID, - /* use_gnu_cie_calc= */ 0, - error); - - return res; -} - - -/* - Only works on dwarf sections, not eh_frame - Given a Dwarf_Die, see if it has a - DW_AT_MIPS_fde attribute and if so use that - to get an fde offset. - Then create a Dwarf_Fde to return thru the ret_fde pointer. - Also creates a cie (pointed at from the Dwarf_Fde). -*/ -int -dwarf_get_fde_for_die(Dwarf_Debug dbg, - Dwarf_Die die, - Dwarf_Fde * ret_fde, Dwarf_Error * error) -{ - Dwarf_Attribute attr; - Dwarf_Unsigned fde_offset = 0; - Dwarf_Signed signdval = 0; - Dwarf_Fde new_fde = 0; - unsigned char *fde_ptr = 0; - unsigned char *cie_ptr = 0; - Dwarf_Unsigned cie_id = 0; - - /* Fields for the current Cie being read. */ - int res = 0; - int resattr = 0; - int sdatares = 0; - - struct cie_fde_prefix_s prefix; - struct cie_fde_prefix_s prefix_c; - - if (die == NULL) { - _dwarf_error(NULL, error, DW_DLE_DIE_NULL); - return (DW_DLV_ERROR); - } - - resattr = dwarf_attr(die, DW_AT_MIPS_fde, &attr, error); - if (resattr != DW_DLV_OK) { - return resattr; - } - - /* why is this formsdata? FIX */ - sdatares = dwarf_formsdata(attr, &signdval, error); - if (sdatares != DW_DLV_OK) { - return sdatares; - } - - res = _dwarf_load_section(dbg, &dbg->de_debug_frame,error); - if (res != DW_DLV_OK) { - return res; - } - - fde_offset = signdval; - fde_ptr = (dbg->de_debug_frame.dss_data + fde_offset); - - - /* First read in the 'common prefix' to figure out what * we are to - do with this entry. */ - memset(&prefix_c, 0, sizeof(prefix_c)); - memset(&prefix, 0, sizeof(prefix)); - res = dwarf_read_cie_fde_prefix(dbg, fde_ptr, - dbg->de_debug_frame.dss_data, - dbg->de_debug_frame.dss_index, - dbg->de_debug_frame.dss_size, - &prefix, - error); - if (res == DW_DLV_ERROR) { - return res; - } - if (res == DW_DLV_NO_ENTRY) - return res; - fde_ptr = prefix.cf_addr_after_prefix; - cie_id = prefix.cf_cie_id; - /* Pass NULL, not section pointer, for 3rd argument. - de_debug_frame.dss_data has no eh_frame relevance. */ - res = dwarf_create_fde_from_after_start(dbg, &prefix, - (Dwarf_Small *) NULL, - fde_ptr, - /* use_gnu_cie_calc= */ 0, - /* Dwarf_Cie = */ 0, - &new_fde, error); - if (res == DW_DLV_ERROR) { - return res; - } else if (res == DW_DLV_NO_ENTRY) { - return res; - } - /* DW_DLV_OK */ - - /* now read the cie corresponding to the fde */ - cie_ptr = new_fde->fd_section_ptr + cie_id; - res = dwarf_read_cie_fde_prefix(dbg, cie_ptr, - dbg->de_debug_frame.dss_data, - dbg->de_debug_frame.dss_index, - dbg->de_debug_frame.dss_size, - &prefix_c, error); - if (res == DW_DLV_ERROR) { - return res; - } - if (res == DW_DLV_NO_ENTRY) - return res; - - cie_ptr = prefix_c.cf_addr_after_prefix; - cie_id = prefix_c.cf_cie_id; - - if (cie_id == DW_CIE_ID) { - int res2 = 0; - Dwarf_Cie new_cie = 0; - - /* Pass NULL, not section pointer, for 3rd argument. - de_debug_frame.dss_data has no eh_frame relevance. */ - res2 = dwarf_create_cie_from_after_start(dbg, - &prefix_c, - (Dwarf_Small *) NULL, - cie_ptr, - /* cie_count= */ 0, - /* use_gnu_cie_calc= */ - 0, &new_cie, error); - if (res2 == DW_DLV_ERROR) { - dwarf_dealloc(dbg, new_fde, DW_DLA_FDE); - return res; - } else if (res2 == DW_DLV_NO_ENTRY) { - dwarf_dealloc(dbg, new_fde, DW_DLA_FDE); - return res; - } - new_fde->fd_cie = new_cie; - } else { - _dwarf_error(dbg, error, DW_DLE_NO_CIE_FOR_FDE); - return (DW_DLV_ERROR); - } - - *ret_fde = new_fde; - return DW_DLV_OK; -} - -/* A dwarf consumer operation, see the consumer library documentation. -*/ -int -dwarf_get_fde_range(Dwarf_Fde fde, - Dwarf_Addr * low_pc, - Dwarf_Unsigned * func_length, - Dwarf_Ptr * fde_bytes, - Dwarf_Unsigned * fde_byte_length, - Dwarf_Off * cie_offset, - Dwarf_Signed * cie_index, - Dwarf_Off * fde_offset, Dwarf_Error * error) -{ - Dwarf_Debug dbg; - - if (fde == NULL) { - _dwarf_error(NULL, error, DW_DLE_FDE_NULL); - return (DW_DLV_ERROR); - } - - dbg = fde->fd_dbg; - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL); - return (DW_DLV_ERROR); - } - - - /* We have always already done the section load here, so no need to - load the section. We did the section load in order to create the - Dwarf_Fde pointer passed in here. */ - - - if (low_pc != NULL) - *low_pc = fde->fd_initial_location; - if (func_length != NULL) - *func_length = fde->fd_address_range; - if (fde_bytes != NULL) - *fde_bytes = fde->fd_fde_start; - if (fde_byte_length != NULL) - *fde_byte_length = fde->fd_length; - if (cie_offset != NULL) - *cie_offset = fde->fd_cie_offset; - if (cie_index != NULL) - *cie_index = fde->fd_cie_index; - if (fde_offset != NULL) - *fde_offset = fde->fd_fde_start - fde->fd_section_ptr; - - return DW_DLV_OK; -} - -/* IRIX specific function. The exception tables - have C++ destructor information and are - at present undocumented. */ -int -dwarf_get_fde_exception_info(Dwarf_Fde fde, - Dwarf_Signed * - offset_into_exception_tables, - Dwarf_Error * error) -{ - Dwarf_Debug dbg; - - dbg = fde->fd_dbg; - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL); - return (DW_DLV_ERROR); - } - *offset_into_exception_tables = - fde->fd_offset_into_exception_tables; - return DW_DLV_OK; -} - - -/* A consumer code function. - Given a CIE pointer, return the normal CIE data thru - pointers. - Special augmentation data is not returned here. -*/ -int -dwarf_get_cie_info(Dwarf_Cie cie, - Dwarf_Unsigned * bytes_in_cie, - Dwarf_Small * ptr_to_version, - char **augmenter, - Dwarf_Unsigned * code_alignment_factor, - Dwarf_Signed * data_alignment_factor, - Dwarf_Half * return_address_register, - Dwarf_Ptr * initial_instructions, - Dwarf_Unsigned * initial_instructions_length, - Dwarf_Error * error) -{ - Dwarf_Debug dbg; - - if (cie == NULL) { - _dwarf_error(NULL, error, DW_DLE_CIE_NULL); - return (DW_DLV_ERROR); - } - - dbg = cie->ci_dbg; - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_CIE_DBG_NULL); - return (DW_DLV_ERROR); - } - - if (ptr_to_version != NULL) - *ptr_to_version = cie->ci_cie_version_number; - if (augmenter != NULL) - *augmenter = cie->ci_augmentation; - if (code_alignment_factor != NULL) - *code_alignment_factor = cie->ci_code_alignment_factor; - if (data_alignment_factor != NULL) - *data_alignment_factor = cie->ci_data_alignment_factor; - if (return_address_register != NULL) - *return_address_register = cie->ci_return_address_register; - if (initial_instructions != NULL) - *initial_instructions = cie->ci_cie_instr_start; - if (initial_instructions_length != NULL) { - *initial_instructions_length = cie->ci_length + - cie->ci_length_size + - cie->ci_extension_size - - (cie->ci_cie_instr_start - cie->ci_cie_start); - - } - *bytes_in_cie = (cie->ci_length); - return (DW_DLV_OK); -} - -/* Return the register rules for all registers at a given pc. -*/ -static int -_dwarf_get_fde_info_for_a_pc_row(Dwarf_Fde fde, - Dwarf_Addr pc_requested, - Dwarf_Frame table, - Dwarf_Half cfa_reg_col_num, - Dwarf_Error * error) -{ - Dwarf_Debug dbg = 0; - Dwarf_Cie cie = 0; - int dw_err = 0; - Dwarf_Sword icount = 0; - int res = 0; - - if (fde == NULL) { - _dwarf_error(NULL, error, DW_DLE_FDE_NULL); - return (DW_DLV_ERROR); - } - - dbg = fde->fd_dbg; - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL); - return (DW_DLV_ERROR); - } - - if (pc_requested < fde->fd_initial_location || - pc_requested >= - fde->fd_initial_location + fde->fd_address_range) { - _dwarf_error(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE); - return (DW_DLV_ERROR); - } - - cie = fde->fd_cie; - if (cie->ci_initial_table == NULL) { - cie->ci_initial_table = _dwarf_get_alloc(dbg, DW_DLA_FRAME, 1); - - if (cie->ci_initial_table == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - _dwarf_init_regrule_table(cie->ci_initial_table->fr_reg, - dbg->de_frame_reg_rules_entry_count, - dbg->de_frame_rule_initial_value); - _dwarf_init_regrule_table(&cie->ci_initial_table->fr_cfa_rule, - 1, dbg->de_frame_rule_initial_value); - res = _dwarf_exec_frame_instr( /* make_instr= */ false, - /* ret_frame_instr= */ NULL, - /* search_pc */ false, - /* search_pc_val */ 0, - /* location */ 0, - cie->ci_cie_instr_start, - cie->ci_cie_instr_start + (cie->ci_length + - cie->ci_length_size + - cie->ci_extension_size - - (cie->ci_cie_instr_start - - cie->ci_cie_start)), - cie->ci_initial_table, cie, dbg, - cfa_reg_col_num, &icount, - &dw_err); - if (res == DW_DLV_ERROR) { - _dwarf_error(dbg, error, dw_err); - return (res); - } else if (res == DW_DLV_NO_ENTRY) { - return res; - } - } - - { - Dwarf_Small *instr_end = fde->fd_fde_instr_start + - fde->fd_length + - fde->fd_length_size + - fde->fd_extension_size - (fde->fd_fde_instr_start - - fde->fd_fde_start); - - res = _dwarf_exec_frame_instr( /* make_instr= */ false, - /* ret_frame_instr= */ NULL, - /* search_pc */ true, - /* search_pc_val */ pc_requested, - fde->fd_initial_location, - fde->fd_fde_instr_start, - instr_end, - table, - cie, dbg, - cfa_reg_col_num, &icount, - &dw_err); - } - if (res == DW_DLV_ERROR) { - _dwarf_error(dbg, error, dw_err); - return (res); - } else if (res == DW_DLV_NO_ENTRY) { - return res; - } - - return DW_DLV_OK; -} - -/* A consumer call for efficiently getting the register info - for all registers in one call. - - The output table rules array is size DW_REG_TABLE_SIZE. - The frame info rules array in fde_table is of size - DW_REG_TABLE_SIZE too. - - This interface really only works well with MIPS/IRIX - where DW_FRAME_CFA_COL is zero (in that case it's safe). - - It is also restricted to the case where - DW_REG_TABLE_SIZE == DW_FRAME_LAST_REG_NUM == - dbg->de_frame_reg_rules_entry_count (true for MIPS/IRIX). - If this condition is not met calling this routine can result in - incorrect output or in memory corruption. - - It is much better to use dwarf_get_fde_info_for_all_regs3() - instead of this interface. -*/ -int -dwarf_get_fde_info_for_all_regs(Dwarf_Fde fde, - Dwarf_Addr pc_requested, - Dwarf_Regtable * reg_table, - Dwarf_Addr * row_pc, - Dwarf_Error * error) -{ - - /* Table size: DW_REG_TABLE_SIZE */ - struct Dwarf_Frame_s fde_table; - Dwarf_Sword i = 0; - struct Dwarf_Reg_Rule_s *rule = NULL; - struct Dwarf_Regtable_Entry_s *out_rule = NULL; - int res = 0; - Dwarf_Debug dbg = 0; - - /* For this interface the size is fixed at compile time. */ - int output_table_real_data_size = DW_REG_TABLE_SIZE; - - FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); - - res = dwarf_initialize_fde_table(dbg, &fde_table, - output_table_real_data_size, - error); - if (res != DW_DLV_OK) - return res; - - /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks - */ - res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, - &fde_table, dbg->de_frame_cfa_col_number, error); - if (res != DW_DLV_OK) { - dwarf_free_fde_table(&fde_table); - return res; - } - - out_rule = ®_table->rules[0]; - rule = &fde_table.fr_reg[0]; - for (i = 0; i < output_table_real_data_size; - i++, ++out_rule, ++rule) { - out_rule->dw_offset_relevant = rule->ru_is_off; - out_rule->dw_value_type = rule->ru_value_type; - out_rule->dw_regnum = rule->ru_register; - out_rule->dw_offset = rule->ru_offset_or_block_len; - } - for (; i < DW_REG_TABLE_SIZE; ++i, ++out_rule) { - out_rule->dw_offset_relevant = 0; - out_rule->dw_value_type = DW_EXPR_OFFSET; - out_rule->dw_regnum = dbg->de_frame_undefined_value_number; - out_rule->dw_offset = 0; - } - - /* The test is just in case it's not inside the table. For non-MIPS - it could be outside the table and that is just fine, it was - really a mistake to put it in the table in 1993. */ - /* CONSTCOND */ - if (dbg->de_frame_cfa_col_number < DW_REG_TABLE_SIZE) { - out_rule = ®_table->rules[dbg->de_frame_cfa_col_number]; - out_rule->dw_offset_relevant = fde_table.fr_cfa_rule.ru_is_off; - out_rule->dw_value_type = fde_table.fr_cfa_rule.ru_value_type; - out_rule->dw_regnum = fde_table.fr_cfa_rule.ru_register; - out_rule->dw_offset = - fde_table.fr_cfa_rule.ru_offset_or_block_len; - } - - if (row_pc != NULL) - *row_pc = fde_table.fr_loc; - dwarf_free_fde_table(&fde_table); - return DW_DLV_OK; -} - -/* A consumer call for efficiently getting the register info - for all registers in one call. - - The output table rules array is size output_table_real_data_size. - (normally DW_REG_TABLE_SIZE). - The frame info rules array in fde_table is normally of size - DW_FRAME_LAST_REG_NUM. -*/ -int -dwarf_get_fde_info_for_all_regs3(Dwarf_Fde fde, - Dwarf_Addr pc_requested, - Dwarf_Regtable3 * reg_table, - Dwarf_Addr * row_pc, - Dwarf_Error * error) -{ - - struct Dwarf_Frame_s fde_table; - Dwarf_Sword i = 0; - int res = 0; - struct Dwarf_Reg_Rule_s *rule = NULL; - struct Dwarf_Regtable_Entry3_s *out_rule = NULL; - Dwarf_Debug dbg = 0; - int output_table_real_data_size = reg_table->rt3_reg_table_size; - - FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); - - output_table_real_data_size = - MIN(output_table_real_data_size, - dbg->de_frame_reg_rules_entry_count); - - res = dwarf_initialize_fde_table(dbg, &fde_table, - output_table_real_data_size, - error); - - /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks - */ - res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, - &fde_table, - dbg->de_frame_cfa_col_number, - error); - if (res != DW_DLV_OK) { - dwarf_free_fde_table(&fde_table); - return res; - } - - out_rule = ®_table->rt3_rules[0]; - rule = &fde_table.fr_reg[0]; - for (i = 0; i < output_table_real_data_size; - i++, ++out_rule, ++rule) { - out_rule->dw_offset_relevant = rule->ru_is_off; - out_rule->dw_value_type = rule->ru_value_type; - out_rule->dw_regnum = rule->ru_register; - out_rule->dw_offset_or_block_len = rule->ru_offset_or_block_len; - out_rule->dw_block_ptr = rule->ru_block; - } - for (; i < reg_table->rt3_reg_table_size; i++, ++out_rule) { - out_rule->dw_offset_relevant = 0; - out_rule->dw_value_type = DW_EXPR_OFFSET; - out_rule->dw_regnum = dbg->de_frame_undefined_value_number; - out_rule->dw_offset_or_block_len = 0; - out_rule->dw_block_ptr = 0; - } - reg_table->rt3_cfa_rule.dw_offset_relevant = - fde_table.fr_cfa_rule.ru_is_off; - reg_table->rt3_cfa_rule.dw_value_type = - fde_table.fr_cfa_rule.ru_value_type; - reg_table->rt3_cfa_rule.dw_regnum = - fde_table.fr_cfa_rule.ru_register; - reg_table->rt3_cfa_rule.dw_offset_or_block_len = - fde_table.fr_cfa_rule.ru_offset_or_block_len; - reg_table->rt3_cfa_rule.dw_block_ptr = - fde_table.fr_cfa_rule.ru_block; - - if (row_pc != NULL) - *row_pc = fde_table.fr_loc; - - dwarf_free_fde_table(&fde_table); - return DW_DLV_OK; -} - - -/* Gets the register info for a single register at a given PC value - for the FDE specified. - - This is the old MIPS interface and should no longer be used. - Use dwarf_get_fde_info_for_reg3() instead. -*/ -int -dwarf_get_fde_info_for_reg(Dwarf_Fde fde, - Dwarf_Half table_column, - Dwarf_Addr pc_requested, - Dwarf_Signed * offset_relevant, - Dwarf_Signed * register_num, - Dwarf_Signed * offset, - Dwarf_Addr * row_pc, Dwarf_Error * error) -{ - struct Dwarf_Frame_s fde_table; - int res = DW_DLV_ERROR; - Dwarf_Debug dbg = 0; - int output_table_real_data_size = 0; - - FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); - output_table_real_data_size = dbg->de_frame_reg_rules_entry_count; - - res = dwarf_initialize_fde_table(dbg, &fde_table, - output_table_real_data_size, - error); - if (res != DW_DLV_OK) - return res; - - if (table_column >= output_table_real_data_size) { - dwarf_free_fde_table(&fde_table); - _dwarf_error(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD); - return (DW_DLV_ERROR); - } - - /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks - */ - res = - _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table, - dbg->de_frame_cfa_col_number, error); - if (res != DW_DLV_OK) { - dwarf_free_fde_table(&fde_table); - return res; - } - - if (fde_table.fr_reg[table_column].ru_value_type != DW_EXPR_OFFSET) { - /* The problem here is that this interface cannot deal with - other sorts of (newer) dwarf frame values. Code must - use dwarf_get_fde_info_for_reg3() to get these - values correctly. We error rather than return - misleading incomplete data. */ - dwarf_free_fde_table(&fde_table); - _dwarf_error(NULL, error, - DW_DLE_FRAME_REGISTER_UNREPRESENTABLE); - return (DW_DLV_ERROR); - } - if(table_column == dbg->de_frame_cfa_col_number) { - if (register_num != NULL) - *register_num = fde_table.fr_cfa_rule.ru_register; - if (offset != NULL) - *offset = fde_table.fr_cfa_rule.ru_offset_or_block_len; - if (row_pc != NULL) - *row_pc = fde_table.fr_loc; - *offset_relevant = fde_table.fr_cfa_rule.ru_is_off; - - } else { - if (register_num != NULL) - *register_num = fde_table.fr_reg[table_column].ru_register; - if (offset != NULL) - *offset = fde_table.fr_reg[table_column].ru_offset_or_block_len; - if (row_pc != NULL) - *row_pc = fde_table.fr_loc; - - *offset_relevant = fde_table.fr_reg[table_column].ru_is_off; - } - dwarf_free_fde_table(&fde_table); - return DW_DLV_OK; -} - -/* In this interface, table_column of DW_FRAME_CFA_COL - is not meaningful. - Use dwarf_get_fde_info_for_cfa_reg3() to get the CFA. - Call dwarf_set_frame_cfa_value() to set the correct column - after calling dwarf_init() - (DW_FRAME_CFA_COL3 is a sensible column to use). -*/ -int -dwarf_get_fde_info_for_reg3(Dwarf_Fde fde, - Dwarf_Half table_column, - Dwarf_Addr pc_requested, - Dwarf_Small * value_type, - Dwarf_Signed * offset_relevant, - Dwarf_Signed * register_num, - Dwarf_Signed * offset_or_block_len, - Dwarf_Ptr * block_ptr, - Dwarf_Addr * row_pc_out, - Dwarf_Error * error) -{ - struct Dwarf_Frame_s fde_table; - int res = DW_DLV_ERROR; - - Dwarf_Debug dbg = 0; - int table_real_data_size = 0; - - FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); - table_real_data_size = dbg->de_frame_reg_rules_entry_count; - res = dwarf_initialize_fde_table(dbg, &fde_table, - table_real_data_size, error); - if (res != DW_DLV_OK) - return res; - if (table_column >= table_real_data_size) { - dwarf_free_fde_table(&fde_table); - _dwarf_error(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD); - return (DW_DLV_ERROR); - } - - /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks - */ - res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table, - dbg->de_frame_cfa_col_number, - error); - if (res != DW_DLV_OK) { - dwarf_free_fde_table(&fde_table); - return res; - } - - if (register_num != NULL) - *register_num = fde_table.fr_reg[table_column].ru_register; - if (offset_or_block_len != NULL) - *offset_or_block_len = - fde_table.fr_reg[table_column].ru_offset_or_block_len; - if (row_pc_out != NULL) - *row_pc_out = fde_table.fr_loc; - if (block_ptr) - *block_ptr = fde_table.fr_reg[table_column].ru_block; - - /* Without value_type the data cannot be understood, so we insist - on it being present, we don't test it. */ - *value_type = fde_table.fr_reg[table_column].ru_value_type; - *offset_relevant = (fde_table.fr_reg[table_column].ru_is_off); - dwarf_free_fde_table(&fde_table); - return DW_DLV_OK; - -} - -/* For latest DWARF, this is the preferred interface. - It more portably deals with the CFA by not - making the CFA a column number, which means - DW_FRAME_CFA_COL3 becomes, like DW_CFA_SAME_VALUE, - a special value, not something one uses as an index. - - Call dwarf_set_frame_cfa_value() to set the correct column - after calling dwarf_init() - (DW_FRAME_CFA_COL3 is a sensible column to use, and - is the default unless '--enable-oldframecol' - is used to configure libdwarf). */ -int -dwarf_get_fde_info_for_cfa_reg3(Dwarf_Fde fde, - Dwarf_Addr pc_requested, - Dwarf_Small * value_type, - Dwarf_Signed * offset_relevant, - Dwarf_Signed * register_num, - Dwarf_Signed * offset_or_block_len, - Dwarf_Ptr * block_ptr, - Dwarf_Addr * row_pc_out, - Dwarf_Error * error) -{ - struct Dwarf_Frame_s fde_table; - int res = DW_DLV_ERROR; - Dwarf_Debug dbg = 0; - - int table_real_data_size = 0; - - FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); - - table_real_data_size = dbg->de_frame_reg_rules_entry_count; - res = dwarf_initialize_fde_table(dbg, &fde_table, - table_real_data_size, error); - if (res != DW_DLV_OK) - return res; - res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table, - dbg->de_frame_cfa_col_number,error); - if (res != DW_DLV_OK) { - dwarf_free_fde_table(&fde_table); - return res; - } - - if (register_num != NULL) - *register_num = fde_table.fr_cfa_rule.ru_register; - if (offset_or_block_len != NULL) - *offset_or_block_len = - fde_table.fr_cfa_rule.ru_offset_or_block_len; - if (row_pc_out != NULL) - *row_pc_out = fde_table.fr_loc; - if (block_ptr) - *block_ptr = fde_table.fr_cfa_rule.ru_block; - - /* Without value_type the data cannot be understood, so we insist - on it being present, we don't test it. */ - *value_type = fde_table.fr_cfa_rule.ru_value_type; - *offset_relevant = fde_table.fr_cfa_rule.ru_is_off; - dwarf_free_fde_table(&fde_table); - return DW_DLV_OK; -} - - - -/* - Return pointer to the instructions in the dwarf - fde. -*/ -int -dwarf_get_fde_instr_bytes(Dwarf_Fde inFde, Dwarf_Ptr * outinstraddr, - Dwarf_Unsigned * outaddrlen, - Dwarf_Error * error) -{ - Dwarf_Unsigned len = 0; - unsigned char *instrs = 0; - Dwarf_Debug dbg = 0; - - if (inFde == NULL) { - _dwarf_error(dbg, error, DW_DLE_FDE_NULL); - return (DW_DLV_ERROR); - } - - dbg = inFde->fd_dbg; - if (dbg == NULL) { - _dwarf_error(dbg, error, DW_DLE_FDE_DBG_NULL); - return (DW_DLV_ERROR); - } - - instrs = inFde->fd_fde_instr_start; - - len = (inFde->fd_fde_start + inFde->fd_length + - inFde->fd_length_size + inFde->fd_extension_size) - instrs; - - *outinstraddr = instrs; - *outaddrlen = len; - return DW_DLV_OK; -} - -/* Allows getting an fde from its table via an index. - With more error checking than simply indexing oneself. -*/ -int -dwarf_get_fde_n(Dwarf_Fde * fde_data, - Dwarf_Unsigned fde_index, - Dwarf_Fde * returned_fde, Dwarf_Error * error) -{ - Dwarf_Debug dbg = 0; - Dwarf_Signed fdecount = 0; - - if (fde_data == NULL) { - _dwarf_error(dbg, error, DW_DLE_FDE_PTR_NULL); - return (DW_DLV_ERROR); - } - - FDE_NULL_CHECKS_AND_SET_DBG(*fde_data, dbg); - /* Assumes fde_data table has at least one entry. */ - fdecount = fde_data[0]->fd_is_eh? - dbg->de_fde_count_eh:dbg->de_fde_count; - if (fde_index >= fdecount) { - return (DW_DLV_NO_ENTRY); - } - *returned_fde = (*(fde_data + fde_index)); - return DW_DLV_OK; -} - - -/* - Lopc and hipc are extensions to the interface to - return the range of addresses that are described - by the returned fde. -*/ -int -dwarf_get_fde_at_pc(Dwarf_Fde * fde_data, - Dwarf_Addr pc_of_interest, - Dwarf_Fde * returned_fde, - Dwarf_Addr * lopc, - Dwarf_Addr * hipc, Dwarf_Error * error) -{ - Dwarf_Debug dbg = NULL; - Dwarf_Fde fde = NULL; - Dwarf_Fde entryfde = NULL; - Dwarf_Signed fdecount = 0; - - if (fde_data == NULL) { - _dwarf_error(NULL, error, DW_DLE_FDE_PTR_NULL); - return (DW_DLV_ERROR); - } - - /* Assumes fde_data table has at least one entry. */ - entryfde = *fde_data; - FDE_NULL_CHECKS_AND_SET_DBG(entryfde, dbg); - - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL); - return (DW_DLV_ERROR); - } - fdecount = entryfde->fd_is_eh? - dbg->de_fde_count_eh:dbg->de_fde_count; - { - /* The fde's are sorted by their addresses. Binary search to - find correct fde. */ - Dwarf_Signed low = 0; - Dwarf_Signed high = fdecount - 1L; - Dwarf_Signed middle = 0; - Dwarf_Fde cur_fde; - - while (low <= high) { - middle = (low + high) / 2; - cur_fde = fde_data[middle]; - if (pc_of_interest < cur_fde->fd_initial_location) { - high = middle - 1; - } else if (pc_of_interest >= - (cur_fde->fd_initial_location + - cur_fde->fd_address_range)) { - low = middle + 1; - } else { - fde = fde_data[middle]; - break; - } - } - } - - if (fde) { - if (lopc != NULL) - *lopc = fde->fd_initial_location; - if (hipc != NULL) - *hipc = - fde->fd_initial_location + fde->fd_address_range - 1; - *returned_fde = fde; - return (DW_DLV_OK); - } - - return (DW_DLV_NO_ENTRY); -} - - -/* Expands a single frame instruction block - from a specific cie - into a n array of Dwarf_Frame_Op-s. - This depends on having the cfa column set sensibly. - - Call dwarf_set_frame_cfa_value() to set the correct column - after calling dwarf_init() unless you are using - the old MIPS frame interfaces (in which case the default - will be ok). (DW_FRAME_CFA_COL3 is a sensible column to use ). -*/ -int -dwarf_expand_frame_instructions(Dwarf_Cie cie, - Dwarf_Ptr instruction, - Dwarf_Unsigned i_length, - Dwarf_Frame_Op ** returned_op_list, - Dwarf_Signed * returned_op_count, - Dwarf_Error * error) -{ - Dwarf_Sword instr_count; - int res = DW_DLV_ERROR; - int dw_err; - Dwarf_Debug dbg = 0; - - if (cie == 0) { - _dwarf_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - dbg = cie->ci_dbg; - - if (returned_op_list == 0 || returned_op_count == 0) { - _dwarf_error(dbg, error, DW_DLE_RET_OP_LIST_NULL); - return (DW_DLV_ERROR); - } - - /* The cast to Dwarf_Ptr may get a compiler warning, but it is safe - as it is just an i_length offset from 'instruction' itself. A - caller has made a big mistake if the result is not a valid - pointer. */ - res = _dwarf_exec_frame_instr( /* make_instr= */ true, - returned_op_list, - /* search_pc */ false, - /* search_pc_val */ 0, - /* location */ 0, - instruction, - (Dwarf_Ptr)((char *)instruction + i_length), - /* Dwarf_Frame */ NULL, - cie, - dbg, - dbg->de_frame_cfa_col_number, &instr_count, - &dw_err); - if (res != DW_DLV_OK) { - if (res == DW_DLV_ERROR) { - _dwarf_error(dbg, error, dw_err); - } - return (res); - } - - *returned_op_count = instr_count; - return DW_DLV_OK; -} - - -/* Used by dwarfdump -v to print offsets, for debugging - dwarf info. - The dwarf_ version is preferred over the obsolete _dwarf version. - _dwarf version kept for compatibility. -*/ -/* ARGSUSED 4 */ -int -_dwarf_fde_section_offset(Dwarf_Debug dbg, Dwarf_Fde in_fde, - Dwarf_Off * fde_off, Dwarf_Off * cie_off, - Dwarf_Error * err) -{ - return dwarf_fde_section_offset(dbg,in_fde,fde_off, - cie_off,err); -} -/* ARGSUSED 4 */ -int -dwarf_fde_section_offset(Dwarf_Debug dbg, Dwarf_Fde in_fde, - Dwarf_Off * fde_off, Dwarf_Off * cie_off, - Dwarf_Error * err) -{ - char *start = 0; - char *loc = 0; - - - - start = (char *) in_fde->fd_section_ptr; - loc = (char *) in_fde->fd_fde_start; - - *fde_off = (loc - start); - *cie_off = in_fde->fd_cie_offset; - return DW_DLV_OK; -} - -/* Used by dwarfdump -v to print offsets, for debugging - dwarf info. - The dwarf_ version is preferred over the obsolete _dwarf version. - _dwarf version kept for compatibility. -*/ -/* ARGSUSED 4 */ -int -_dwarf_cie_section_offset(Dwarf_Debug dbg, Dwarf_Cie in_cie, - Dwarf_Off * cie_off, Dwarf_Error * err) -{ - return dwarf_cie_section_offset(dbg,in_cie,cie_off,err); -} -/* ARGSUSED 4 */ -int -dwarf_cie_section_offset(Dwarf_Debug dbg, Dwarf_Cie in_cie, - Dwarf_Off * cie_off, Dwarf_Error * err) -{ - char *start = 0; - char *loc = 0; - - start = (char *) in_cie->ci_section_ptr; - loc = (char *) in_cie->ci_cie_start; - - *cie_off = (loc - start); - return DW_DLV_OK; -} - -/* Returns a pointer to target-specific augmentation data thru augdata - and returns the length of the data thru augdata_len. - - It's up to the consumer code to know how to interpret the bytes - of target-specific data (endian issues apply too, these - are just raw bytes pointed to). - See Linux Standard Base Core Specification version 3.0 for - the details on .eh_frame info. - - Returns DW_DLV_ERROR if fde is NULL or some other serious - error. - Returns DW_DLV_NO_ENTRY if there is no target-specific - augmentation data. - - The bytes pointed to are in the Dwarf_Cie, and as long as that - is valid the bytes are there. No 'dealloc' call is needed - for the bytes. -*/ -int -dwarf_get_cie_augmentation_data(Dwarf_Cie cie, - Dwarf_Small ** augdata, - Dwarf_Unsigned * augdata_len, - Dwarf_Error * error) -{ - if (cie == NULL) { - _dwarf_error(NULL, error, DW_DLE_CIE_NULL); - return (DW_DLV_ERROR); - } - if (cie->ci_gnu_eh_augmentation_len == 0) { - return DW_DLV_NO_ENTRY; - } - *augdata = (Dwarf_Small *) (cie->ci_gnu_eh_augmentation_bytes); - *augdata_len = cie->ci_gnu_eh_augmentation_len; - return DW_DLV_OK; -} - - -/* Returns a pointer to target-specific augmentation data thru augdata - and returns the length of the data thru augdata_len. - - It's up to the consumer code to know how to interpret the bytes - of target-specific data (endian issues apply too, these - are just raw bytes pointed to). - See Linux Standard Base Core Specification version 3.0 for - the details on .eh_frame info. - - Returns DW_DLV_ERROR if fde is NULL or some other serious - error. - Returns DW_DLV_NO_ENTRY if there is no target-specific - augmentation data. - - The bytes pointed to are in the Dwarf_Fde, and as long as that - is valid the bytes are there. No 'dealloc' call is needed - for the bytes. - -*/ -int -dwarf_get_fde_augmentation_data(Dwarf_Fde fde, - Dwarf_Small * *augdata, - Dwarf_Unsigned * augdata_len, - Dwarf_Error * error) -{ - Dwarf_Cie cie = 0; - - if (fde == NULL) { - _dwarf_error(NULL, error, DW_DLE_FDE_NULL); - return (DW_DLV_ERROR); - } - cie = fde->fd_cie; - if (cie == NULL) { - _dwarf_error(NULL, error, DW_DLE_CIE_NULL); - return (DW_DLV_ERROR); - } - if (cie->ci_gnu_eh_augmentation_len == 0) { - return DW_DLV_NO_ENTRY; - } - *augdata = (Dwarf_Small *) fde->fd_gnu_eh_augmentation_bytes; - *augdata_len = fde->fd_gnu_eh_augmentation_len; - return DW_DLV_OK; -} - - -/* Initialize with same_value , a value which makes sense - for IRIX/MIPS. - The correct value to use is ABI dependent. - For register-windows machines most - or all registers should get DW_FRAME_UNDEFINED_VAL as the - correct initial value. - Some think DW_FRAME_UNDEFINED_VAL is always the - right value. - - For some ABIs a setting which varies by register - would be more appropriate. - - FIXME. */ - -static void -_dwarf_init_regrule_table(struct Dwarf_Reg_Rule_s *t1reg, - int last_reg_num, int initial_value) -{ - struct Dwarf_Reg_Rule_s *t1end = t1reg + last_reg_num; - - for (; t1reg < t1end; t1reg++) { - t1reg->ru_is_off = 0; - t1reg->ru_value_type = DW_EXPR_OFFSET; - t1reg->ru_register = initial_value; - t1reg->ru_offset_or_block_len = 0; - t1reg->ru_block = 0; - } -} - -#if 0 -/* Used solely for debugging libdwarf. */ -static void -dump_frame_rule(char *msg, struct Dwarf_Reg_Rule_s *reg_rule) -{ - printf - ("%s type %s (" DW_PR_DUx "), is_off " - DW_PR_DUu " reg " DW_PR_DUu " offset " DW_PR_DUx " blockp " - DW_PR_DUx "\n", - msg, - (reg_rule->ru_value_type == DW_EXPR_OFFSET) ? - "DW_EXPR_OFFSET" : - (reg_rule->ru_value_type == DW_EXPR_VAL_OFFSET) ? - "DW_EXPR_VAL_OFFSET" : - (reg_rule->ru_value_type == DW_EXPR_VAL_EXPRESSION) ? - "DW_EXPR_VAL_EXPRESSION" : - (reg_rule->ru_value_type == DW_EXPR_EXPRESSION) ? - "DW_EXPR_EXPRESSION" : "Unknown", - (Dwarf_Unsigned) reg_rule->ru_value_type, - (Dwarf_Unsigned) reg_rule->ru_is_off, - (Dwarf_Unsigned) reg_rule->ru_register, - (Dwarf_Unsigned) reg_rule->ru_offset_or_block_len, - (Dwarf_Unsigned) reg_rule->ru_block); - return; -} -#endif - -/* This allows consumers to set the 'initial value' so that - an ISA/ABI specific default can be used, dynamically, - at run time. Useful for dwarfdump and non-MIPS architectures.. - The value defaults to one of - DW_FRAME_SAME_VALUE or DW_FRAME_UNKNOWN_VALUE - but dwarfdump can dump multiple ISA/ABI objects so - we may want to get this set to what the ABI says is correct. - - Returns the value that was present before we changed it here. -*/ -Dwarf_Half -dwarf_set_frame_rule_initial_value(Dwarf_Debug dbg, Dwarf_Half value) -{ - Dwarf_Half orig = dbg->de_frame_rule_initial_value; - dbg->de_frame_rule_initial_value = value; - return orig; -} - -/* The following spelling for backwards compatibility. */ -Dwarf_Half -dwarf_set_frame_rule_inital_value(Dwarf_Debug dbg, Dwarf_Half value) -{ - return dwarf_set_frame_rule_initial_value(dbg,value); -} - -/* This allows consumers to set the array size of the reg rules - table so that - an ISA/ABI specific value can be used, dynamically, - at run time. Useful for non-MIPS archtectures. - The value defaults to DW_FRAME_LAST_REG_NUM. - but dwarfdump can dump multiple ISA/ABI objects so - consumers want to get this set to what the ABI says is correct. - - Returns the value that was present before we changed it here. -*/ - -Dwarf_Half -dwarf_set_frame_rule_table_size(Dwarf_Debug dbg, Dwarf_Half value) -{ - Dwarf_Half orig = dbg->de_frame_reg_rules_entry_count; - dbg->de_frame_reg_rules_entry_count = value; - return orig; -} -/* This allows consumers to set the CFA register value - * so that an ISA/ABI specific value can be used, dynamically, - * at run time. Useful for non-MIPS archtectures. - * The value defaults to DW_FRAME_CFA_COL3 and should be - * higher than any real register in the ABI. - * Dwarfdump can dump multiple ISA/ABI objects so - * consumers want to get this set to what the ABI says is correct. - - * Returns the value that was present before we changed it here. - * */ - -Dwarf_Half -dwarf_set_frame_cfa_value(Dwarf_Debug dbg, Dwarf_Half value) -{ - Dwarf_Half orig = dbg->de_frame_cfa_col_number; - dbg->de_frame_cfa_col_number = value; - return orig; -} -/* Similar to above, but for the other crucial fields for frames. */ -Dwarf_Half -dwarf_set_frame_same_value(Dwarf_Debug dbg, Dwarf_Half value) -{ - Dwarf_Half orig = dbg->de_frame_same_value_number; - dbg->de_frame_same_value_number = value; - return orig; -} -Dwarf_Half -dwarf_set_frame_undefined_value(Dwarf_Debug dbg, Dwarf_Half value) -{ - Dwarf_Half orig = dbg->de_frame_same_value_number; - dbg->de_frame_undefined_value_number = value; - return orig; -} - - - - - -static int -dwarf_initialize_fde_table(Dwarf_Debug dbg, - struct Dwarf_Frame_s *fde_table, - unsigned table_real_data_size, - Dwarf_Error * error) -{ - unsigned entry_size = sizeof(struct Dwarf_Frame_s); - - fde_table->fr_loc = 0; - fde_table->fr_reg_count = table_real_data_size; - fde_table->fr_next = 0; - - fde_table->fr_reg = (struct Dwarf_Reg_Rule_s *) - calloc(entry_size, table_real_data_size); - if (fde_table->fr_reg == 0) { - _dwarf_error(dbg, error, DW_DLE_DF_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - return DW_DLV_OK; - -} -static void -dwarf_free_fde_table(struct Dwarf_Frame_s *fde_table) -{ - free(fde_table->fr_reg); - fde_table->fr_reg_count = 0; - fde_table->fr_reg = 0; -} - - -/* Return DW_DLV_OK if we succeed. else return DW_DLV_ERROR. -*/ -int -_dwarf_frame_constructor(Dwarf_Debug dbg, void *frame) -{ - struct Dwarf_Frame_s *fp = frame; - - if (!dbg) { - return DW_DLV_ERROR; - } - - fp->fr_reg = calloc(dbg->de_frame_reg_rules_entry_count, - sizeof(struct Dwarf_Reg_Rule_s)); - if (!fp->fr_reg) { - return DW_DLV_ERROR; - } - fp->fr_reg_count = dbg->de_frame_reg_rules_entry_count; - return DW_DLV_OK; -} - -void -_dwarf_frame_destructor(void *frame) -{ - struct Dwarf_Frame_s *fp = frame; - - if (fp->fr_reg) { - free(fp->fr_reg); - } - fp->fr_reg = 0; - fp->fr_reg_count = 0; -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_frame.h b/usr/src/tools/ctf/dwarf/common/dwarf_frame.h deleted file mode 100644 index ceb686335b..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_frame.h +++ /dev/null @@ -1,421 +0,0 @@ -/* - - Copyright (C) 2000, 2004, 2006 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -/* The dwarf 2.0 standard dictates that only the following - * fields can be read when an unexpected augmentation string - * (in the cie) is encountered: CIE length, CIE_id, version and - * augmentation; FDE: length, CIE pointer, initial location and - * address range. Unfortunately, with the above restrictions, it - * is impossible to read the instruction table from a CIE or a FDE - * when a new augmentation string is encountered. - * To fix this problem, the following layout is used, if the - * augmentation string starts with the string "z". - * CIE FDE - * length length - * CIE_id CIE_pointer - * version initial_location - * augmentation address_range - * length_of_augmented_fields (*NEW*) - * code_alignment_factor Any new fields as necessary - * data_alignment_factor instruction_table - * return_address - * length_of_augmented fields - * Any new fields as necessary - * initial_instructions - * - * The type of all the old data items are the same as what is - * described in dwarf 2.0 standard. The length_of_augmented_fields - * is an LEB128 data item that denotes the size (in bytes) of - * the augmented fields (not including the size of - * "length_of_augmented_fields" itself). - - * Handling of cie augmentation strings is necessarly a heuristic. - * See dwarf_frame.c for the currently known augmentation strings. - - - ---START SGI-ONLY COMMENT: - * SGI-IRIX versions of cie or fde were intended to use "z1", "z2" as the - * augmenter strings if required for new augmentation. - * However, that never happened (as of March 2005). - * - * The fde's augmented by the string "z" have a new field - * (signed constant, 4 byte field) - * called offset_into_exception_tables, following the - * length_of_augmented field. This field contains an offset - * into the "_MIPS_eh_region", which describes - * the IRIX CC exception handling tables. - ---END SGI-ONLY COMMENT - - - * GNU .eh_frame has an augmentation string of z[RLP]* (gcc 3.4) - * The similarity to IRIX 'z' (and proposed but never - * implemented IRIX z1, z2 etc) was confusing things. - * If the section is .eh_frame then 'z' means GNU exception - * information 'Augmentation Data' not IRIX 'z'. - * See The Linux Standard Base Core Specification version 3.0 - */ - -#define DW_DEBUG_FRAME_VERSION 1 /* DWARF2 */ -#define DW_DEBUG_FRAME_VERSION3 3 /* DWARF3 */ -#define DW_DEBUG_FRAME_VERSION4 4 /* DWARF4 */ -/* The following is SGI/IRIX specific, and probably no longer - in use anywhere. */ -#define DW_DEBUG_FRAME_AUGMENTER_STRING "mti v1" - -/* The value of the offset field for Cie's. */ -#define DW_CIE_OFFSET ~(0x0) - -/* The augmentation string may be NULL. */ -#define DW_EMPTY_STRING "" - -#define DW_FRAME_INSTR_OPCODE_SHIFT 6 -#define DW_FRAME_INSTR_OFFSET_MASK 0x3f - -/* - This struct denotes the rule for a register in a row of - the frame table. In other words, it is one element of - the table. -*/ -struct Dwarf_Reg_Rule_s { - - /* - Is a flag indicating whether the rule includes the offset - field, ie whether the ru_offset field is valid or not. - Applies only if DW_EXPR_OFFSET or DW_EXPR_VAL_OFFSET. - It is important, since reg+offset (offset of 0) is different from - just 'register' since the former means 'read memory at address - given by the sum of register contents plus offset to get the - value'. whereas the latter means 'the value is in the register'. - - The 'register' numbers are either real registers (ie, table - columns defined as real registers) or defined entries that are - not really hardware registers, such as DW_FRAME_SAME_VAL or - DW_FRAME_CFA_COL. - - */ - Dwarf_Sbyte ru_is_off; - - /* DW_EXPR_OFFSET (0, DWARF2) - DW_EXPR_VAL_OFFSET 1 (dwarf2/3) - DW_EXPR_EXPRESSION 2 (dwarf2/3) - DW_EXPR_VAL_EXPRESSION 3 (dwarf2/3) - See dwarf_frame.h. */ - Dwarf_Sbyte ru_value_type; - - /* Register involved in this rule. */ - Dwarf_Half ru_register; - - /* Offset to add to register, if indicated by ru_is_offset - and if DW_EXPR_OFFSET or DW_EXPR_VAL_OFFSET. - If DW_EXPR_EXPRESSION or DW_EXPR_VAL_EXPRESSION - this is DW_FORM_block block-length, not offset. */ - Dwarf_Unsigned ru_offset_or_block_len; - - /* For DW_EXPR_EXPRESSION DW_EXPR_VAL_EXPRESSION these is set, - else 0. */ - Dwarf_Small *ru_block; -}; - -typedef struct Dwarf_Frame_s *Dwarf_Frame; - -/* - This structure represents a row of the frame table. - Fr_loc is the pc value for this row, and Fr_reg - contains the rule for each column. - - Entry DW_FRAME_CFA_COL of fr_reg was the tradional MIPS - way of setting CFA. cfa_rule is the new one. -*/ -struct Dwarf_Frame_s { - - /* Pc value corresponding to this row of the frame table. */ - Dwarf_Addr fr_loc; - - /* Rules for all the registers in this row. */ - struct Dwarf_Reg_Rule_s fr_cfa_rule; - - /* fr_reg_count is the the number of - entries of the fr_reg array. */ - unsigned long fr_reg_count; - struct Dwarf_Reg_Rule_s *fr_reg; - - Dwarf_Frame fr_next; -}; - -typedef struct Dwarf_Frame_Op_List_s *Dwarf_Frame_Op_List; - -/* This is used to chain together Dwarf_Frame_Op structures. */ -struct Dwarf_Frame_Op_List_s { - Dwarf_Frame_Op *fl_frame_instr; - Dwarf_Frame_Op_List fl_next; -}; - -/* See dwarf_frame.c for the heuristics used to set the - Dwarf_Cie ci_augmentation_type. - - This succinctly helps interpret the size and meaning of .debug_frame - and (for gcc) .eh_frame. - - In the case of gcc .eh_frame (gcc 3.3, 3.4) - z may be followed by one or more of - L R P. - -*/ -enum Dwarf_augmentation_type { - aug_empty_string, /* Default empty augmentation string. */ - aug_irix_exception_table, /* IRIX plain "z", - for exception handling, IRIX CC compiler. - Proposed z1 z2 ... never implemented. */ - aug_gcc_eh_z, /* gcc z augmentation, (including - L R P variations). gcc 3.3 3.4 exception - handling in eh_frame. */ - aug_irix_mti_v1, /* IRIX "mti v1" augmentation string. Probably - never in any released SGI-IRIX compiler. */ - aug_eh, /* For gcc .eh_frame, "eh" is the string., - gcc 1,2, egcs. Older values. */ - aug_armcc, /* "armcc+" meaning the cfa calculation - is corrected to be standard (output by - Arm C RVCT 3.0 SP1 and later). See - http://sourceware.org/ml/gdb-patches/2006-12/msg00249.html - for details. */ - aug_unknown, /* Unknown augmentation, we cannot do much. */ - aug_past_last -}; - - -/* - This structure contains all the pertinent info for a Cie. Most - of the fields are taken straight from the definition of a Cie. - Ci_cie_start points to the address (in .debug_frame) where this - Cie begins. Ci_cie_instr_start points to the first byte of the - frame instructions for this Cie. Ci_dbg points to the associated - Dwarf_Debug structure. Ci_initial_table is a pointer to the table - row generated by the instructions for this Cie. -*/ -struct Dwarf_Cie_s { - Dwarf_Unsigned ci_length; - char *ci_augmentation; - Dwarf_Small ci_code_alignment_factor; - Dwarf_Sbyte ci_data_alignment_factor; - Dwarf_Small ci_return_address_register; - Dwarf_Small *ci_cie_start; - Dwarf_Small *ci_cie_instr_start; - Dwarf_Debug ci_dbg; - Dwarf_Frame ci_initial_table; - Dwarf_Cie ci_next; - Dwarf_Small ci_length_size; - Dwarf_Small ci_extension_size; - Dwarf_Half ci_cie_version_number; - enum Dwarf_augmentation_type ci_augmentation_type; - - /* The following 2 for GNU .eh_frame exception handling - Augmentation Data. Set if ci_augmentation_type - is aug_gcc_eh_z. Zero if unused. */ - Dwarf_Unsigned ci_gnu_eh_augmentation_len; - Dwarf_Ptr ci_gnu_eh_augmentation_bytes; - - /* These are extracted from the gnu eh_frame - augmentation if the - augmentation begins with 'z'. See Linux LSB documents. - Otherwize these are zero. */ - unsigned char ci_gnu_personality_handler_encoding; - unsigned char ci_gnu_lsda_encoding; - unsigned char ci_gnu_fde_begin_encoding; - - /* If 'P' augmentation present, is handler addr. Else - is zero. */ - Dwarf_Addr ci_gnu_personality_handler_addr; - - - /* In creating list of cie's (which will become an array) - record the position so fde can get it on fde creation. */ - Dwarf_Unsigned ci_index; - Dwarf_Small * ci_section_ptr; - /* DWARF4 adds address size and segment size to the CIE: the .debug_info - section may not always be present to allow libdwarf to - find address_size from the compilation-unit. */ - Dwarf_Half ci_address_size; - Dwarf_Half ci_segment_size; - -}; - -/* - This structure contains all the pertinent info for a Fde. - Most of the fields are taken straight from the definition. - fd_cie_index is the index of the Cie associated with this - Fde in the list of Cie's for this debug_frame. Fd_cie - points to the corresponsing Dwarf_Cie structure. Fd_fde_start - points to the start address of the Fde. Fd_fde_instr_start - points to the start of the instructions for this Fde. Fd_dbg - points to the associated Dwarf_Debug structure. -*/ -struct Dwarf_Fde_s { - Dwarf_Unsigned fd_length; - Dwarf_Addr fd_cie_offset; - Dwarf_Unsigned fd_cie_index; - Dwarf_Cie fd_cie; - Dwarf_Addr fd_initial_location; - Dwarf_Small *fd_initial_loc_pos; - Dwarf_Addr fd_address_range; - Dwarf_Small *fd_fde_start; - Dwarf_Small *fd_fde_instr_start; - Dwarf_Debug fd_dbg; - - /* fd_offset_into_exception_tables is SGI/IRIX exception table - offset. Unused and zero if not IRIX .debug_frame. */ - Dwarf_Signed fd_offset_into_exception_tables; - - Dwarf_Fde fd_next; - Dwarf_Small fd_length_size; - Dwarf_Small fd_extension_size; - /* So we know from an fde which 'count' of fde-s in - Dwarf_Debug applies: eh or standard. */ - Dwarf_Small fd_is_eh; - /* The following 2 for GNU .eh_frame exception handling - Augmentation Data. Set if CIE ci_augmentation_type - is aug_gcc_eh_z. Zero if unused. */ - Dwarf_Unsigned fd_gnu_eh_augmentation_len; - Dwarf_Ptr fd_gnu_eh_augmentation_bytes; - Dwarf_Addr fd_gnu_eh_lsda; /* If 'L' augmentation letter - present: is address of the - Language Specific Data Area (LSDA). If not 'L" is zero. */ - - /* The following 3 are about the Elf section the FDEs come from. */ - Dwarf_Small * fd_section_ptr; - Dwarf_Unsigned fd_section_length; - Dwarf_Unsigned fd_section_index; - -}; - - -int - _dwarf_frame_address_offsets(Dwarf_Debug dbg, Dwarf_Addr ** addrlist, - Dwarf_Off ** offsetlist, - Dwarf_Signed * returncount, - Dwarf_Error * err); - -int -_dwarf_get_fde_list_internal(Dwarf_Debug dbg, - Dwarf_Cie ** cie_data, - Dwarf_Signed * cie_element_count, - Dwarf_Fde ** fde_data, - Dwarf_Signed * fde_element_count, - Dwarf_Small * section_ptr, - Dwarf_Unsigned section_index, - Dwarf_Unsigned section_length, - Dwarf_Unsigned cie_id_value, - int use_gnu_cie_calc, /* If non-zero, - this is gcc eh_frame. */ - Dwarf_Error * error); - -enum Dwarf_augmentation_type -_dwarf_get_augmentation_type(Dwarf_Debug dbg, - Dwarf_Small *augmentation_string, - int is_gcc_eh_frame); - -Dwarf_Unsigned _dwarf_get_return_address_reg(Dwarf_Small *frame_ptr, - int version, - unsigned long *size); - -/* Temporary recording of crucial cie/fde prefix data. - * Vastly simplifies some argument lists. - */ -struct cie_fde_prefix_s { - /* cf_start_addr is a pointer to the first byte of this fde/cie - we are reading now. */ - Dwarf_Small * cf_start_addr; - Dwarf_Small * cf_addr_after_prefix; - Dwarf_Unsigned cf_length; - int cf_local_length_size; - int cf_local_extension_size; - Dwarf_Unsigned cf_cie_id; - Dwarf_Small * cf_cie_id_addr; /* used for eh_frame calculations. */ - - /* Simplifies passing around these values to create fde having - these here. */ - /* cf_section_ptr is a pointer to the first byte - of the object section the prefix is read from. */ - Dwarf_Small * cf_section_ptr; - Dwarf_Unsigned cf_section_index; - Dwarf_Unsigned cf_section_length; -}; - -int -_dwarf_exec_frame_instr(Dwarf_Bool make_instr, - Dwarf_Frame_Op ** ret_frame_instr, - Dwarf_Bool search_pc, - Dwarf_Addr search_pc_val, - Dwarf_Addr initial_loc, - Dwarf_Small * start_instr_ptr, - Dwarf_Small * final_instr_ptr, - Dwarf_Frame table, - Dwarf_Cie cie, - Dwarf_Debug dbg, - Dwarf_Half reg_num_of_cfa, - Dwarf_Sword * returned_count, - int *returned_error); - - -int dwarf_read_cie_fde_prefix(Dwarf_Debug dbg, - Dwarf_Small *frame_ptr_in, - Dwarf_Small *section_ptr_in, - Dwarf_Unsigned section_index_in, - Dwarf_Unsigned section_length_in, - struct cie_fde_prefix_s *prefix_out, - Dwarf_Error *error); - -int dwarf_create_fde_from_after_start(Dwarf_Debug dbg, - struct cie_fde_prefix_s * prefix, - Dwarf_Small *section_pointer, - Dwarf_Small *frame_ptr, - int use_gnu_cie_calc, - Dwarf_Cie cie_ptr_in, - Dwarf_Fde *fde_ptr_out, - Dwarf_Error *error); - -int dwarf_create_cie_from_after_start(Dwarf_Debug dbg, - struct cie_fde_prefix_s *prefix, - Dwarf_Small* section_pointer, - Dwarf_Small* frame_ptr, - Dwarf_Unsigned cie_count, - int use_gnu_cie_calc, - Dwarf_Cie *cie_ptr_out, - Dwarf_Error *error); - - -int _dwarf_frame_constructor(Dwarf_Debug dbg,void * ); -void _dwarf_frame_destructor (void *); diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_frame2.c b/usr/src/tools/ctf/dwarf/common/dwarf_frame2.c deleted file mode 100644 index 01b9ec497b..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_frame2.c +++ /dev/null @@ -1,1540 +0,0 @@ -/* - - Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the Crittenden Lane address. -*/ - - -/* - This implements _dwarf_get_fde_list_internal() - and related helper functions for reading cie/fde data. -*/ - - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include -#include -#include "dwarf_frame.h" -#include "dwarf_arange.h" /* using Arange as a way to build a - list */ - - -static int dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr, - Dwarf_Cie cur_cie_ptr, - Dwarf_Cie * cie_ptr_to_use_out, - Dwarf_Cie head_cie_ptr); -static void dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr, - Dwarf_Cie head_cie_ptr); -static int dwarf_create_cie_from_start(Dwarf_Debug dbg, - Dwarf_Small * cie_ptr_val, - Dwarf_Small * section_ptr, - Dwarf_Unsigned section_index, - Dwarf_Unsigned section_length, - Dwarf_Small * frame_ptr_end, - Dwarf_Unsigned cie_id_value, - Dwarf_Unsigned cie_count, - int use_gnu_cie_calc, - Dwarf_Cie * cie_ptr_to_use_out, - Dwarf_Error * error); - -static Dwarf_Small *get_cieptr_given_offset(Dwarf_Unsigned cie_id_value, - int use_gnu_cie_calc, - Dwarf_Small * section_ptr, - Dwarf_Small * cie_id_addr); -static int get_gcc_eh_augmentation(Dwarf_Debug dbg, - Dwarf_Small * frame_ptr, - unsigned long - *size_of_augmentation_data, - enum Dwarf_augmentation_type augtype, - Dwarf_Small * section_pointer, - Dwarf_Small * fde_eh_encoding_out, - char *augmentation); - -static int - gnu_aug_encodings(Dwarf_Debug dbg, char *augmentation, - Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len, - Dwarf_Half address_size, - unsigned char *pers_hand_enc_out, - unsigned char *lsda_enc_out, - unsigned char *fde_begin_enc_out, - Dwarf_Addr * gnu_pers_addr_out); - - -static int read_encoded_ptr(Dwarf_Debug dbg, - Dwarf_Small * section_pointer, - Dwarf_Small * input_field, - int gnu_encoding, - Dwarf_Half address_size, - Dwarf_Unsigned * addr, - Dwarf_Small ** input_field_out); - - - -static int qsort_compare(const void *elem1, const void *elem2); - - -/* Adds 'newone' to the end of the list starting at 'head' - and makes the new one 'cur'rent. */ -static void -chain_up_fde(Dwarf_Fde newone, Dwarf_Fde * head, Dwarf_Fde * cur) -{ - if (*head == NULL) - *head = newone; - else { - (*cur)->fd_next = newone; - } - *cur = newone; - -} - -/* Adds 'newone' to the end of the list starting at 'head' - and makes the new one 'cur'rent. */ -static void -chain_up_cie(Dwarf_Cie newone, Dwarf_Cie * head, Dwarf_Cie * cur) -{ - if (*head == NULL) { - *head = newone; - } else { - (*cur)->ci_next = newone; - } - *cur = newone; -} - -/* The size of the length field plus the - value of length must be an integral - multiple of the address size. Dwarf4 standard. - - A constant that gives the number of bytes of the CIE - structure, not including the length field itself - (where length mod == 0) - (see Section 7.2.2). Dwarf3 standard. - - A uword constant that gives the number of bytes of - the CIE structure, not including the - length field, itself (length mod == 0). - Dwarf2 standard.*/ -static void -validate_length(Dwarf_Debug dbg, - Dwarf_Cie cieptr, Dwarf_Unsigned length, - Dwarf_Unsigned length_size, - Dwarf_Unsigned extension_size, - Dwarf_Small * section_ptr, - Dwarf_Small * ciefde_start, - const char * cieorfde) -{ - Dwarf_Unsigned address_size = cieptr->ci_address_size; - Dwarf_Unsigned length_field_summed = length_size + extension_size; - Dwarf_Unsigned total_len = length + length_field_summed; - Dwarf_Unsigned mod = total_len % address_size; - - if (mod != 0) { - char msg[DW_HARMLESS_ERROR_MSG_STRING_SIZE]; - Dwarf_Unsigned sectionoffset = ciefde_start - section_ptr; - snprintf(msg,sizeof(msg), - "DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE" - " len=0x%" DW_PR_DUx - ", len size=0x%" DW_PR_DUx - ", extn size=0x%" DW_PR_DUx - ", totl length=0x%" DW_PR_DUx - ", addr size=0x%" DW_PR_DUx - ", mod=0x%" DW_PR_DUx " must be zero" - " in %s" - ", offset 0x%" DW_PR_DUx ".", - length, - length_size, - extension_size, - total_len,address_size, mod, - cieorfde, - sectionoffset); - dwarf_insert_harmless_error(dbg,msg); - } - return; -} - - -#if 0 -/* For debugging only. */ -static void -print_prefix(struct cie_fde_prefix_s *prefix, int line) -{ - printf("prefix-print, prefix at 0x%lx, line %d\n", - (long) prefix, line); - printf(" start addr 0x%lx after prefix 0x%lx\n", - (long) prefix->cf_start_addr, - (long) prefix->cf_addr_after_prefix); - printf(" length 0x%" DW_PR_DUx ", len size %d ext size %d\n", - (Dwarf_Unsigned) prefix->cf_length, - prefix->cf_local_length_size, - prefix->cf_local_extension_size); - printf(" cie_id 0x%" DW_PR_DUx " cie_id cie_id_addr 0x%lx\n", - (Dwarf_Unsigned) prefix->cf_cie_id, - (long) prefix->cf_cie_id_addr); - printf - (" sec ptr 0x%lx sec index %" DW_PR_DSd " sec len 0x%" DW_PR_DUx " sec past end 0x%lx\n", - (long) prefix->cf_section_ptr, - (Dwarf_Signed) prefix->cf_section_index, - (Dwarf_Unsigned) prefix->cf_section_length, - (long) prefix->cf_section_ptr + prefix->cf_section_length); -} -#endif - - - -/* Internal function called from various places to create - lists of CIEs and FDEs. Not directly called - by consumer code */ -int -_dwarf_get_fde_list_internal(Dwarf_Debug dbg, Dwarf_Cie ** cie_data, - Dwarf_Signed * cie_element_count, - Dwarf_Fde ** fde_data, - Dwarf_Signed * fde_element_count, - Dwarf_Small * section_ptr, - Dwarf_Unsigned section_index, - Dwarf_Unsigned section_length, - Dwarf_Unsigned cie_id_value, - int use_gnu_cie_calc, Dwarf_Error * error) -{ - /* Scans the debug_frame section. */ - Dwarf_Small *frame_ptr = section_ptr; - Dwarf_Small *frame_ptr_end = section_ptr + section_length; - - - - /* - New_cie points to the Cie being read, and head_cie_ptr and - cur_cie_ptr are used for chaining them up in sequence. - In case cie's are reused aggressively we need tail_cie_ptr - to add to the chain. If we re-use an early cie - later on, that does not mean we chain a new cie to the early one, - we always chain it to the tail. */ - Dwarf_Cie head_cie_ptr = NULL; - Dwarf_Cie cur_cie_ptr = NULL; - Dwarf_Cie tail_cie_ptr = NULL; - Dwarf_Word cie_count = 0; - - /* - Points to a list of contiguous pointers to Dwarf_Cie structures. - */ - Dwarf_Cie *cie_list_ptr = 0; - - - /* - New_fde points to the Fde being created, and head_fde_ptr and - cur_fde_ptr are used to chain them up. */ - Dwarf_Fde head_fde_ptr = NULL; - Dwarf_Fde cur_fde_ptr = NULL; - Dwarf_Word fde_count = 0; - - /* - Points to a list of contiguous pointers to Dwarf_Fde structures. - */ - Dwarf_Fde *fde_list_ptr = NULL; - - Dwarf_Word i = 0; - int res = DW_DLV_ERROR; - - if (frame_ptr == 0) { - return DW_DLV_NO_ENTRY; - } - - /* We create the fde and cie arrays. Processing each CIE as we come - to it or as an FDE refers to it. We cannot process 'late' CIEs - late as GNU .eh_frame complexities mean we need the whole CIE - before we can process the FDE correctly. */ - while (frame_ptr < frame_ptr_end) { - - struct cie_fde_prefix_s prefix; - - /* First read in the 'common prefix' to figure out what we are - to do with this entry. */ - memset(&prefix, 0, sizeof(prefix)); - res = dwarf_read_cie_fde_prefix(dbg, - frame_ptr, section_ptr, - section_index, - section_length, &prefix, error); - if (res == DW_DLV_ERROR) { - dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr); - return res; - } - if (res == DW_DLV_NO_ENTRY) - break; - frame_ptr = prefix.cf_addr_after_prefix; - if (frame_ptr >= frame_ptr_end) { - dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr); - _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD); - return DW_DLV_ERROR; - - } - - if (prefix.cf_cie_id == cie_id_value) { - /* This is a CIE. */ - Dwarf_Cie cie_ptr_to_use = 0; - - int res = dwarf_find_existing_cie_ptr(prefix.cf_start_addr, - cur_cie_ptr, - &cie_ptr_to_use, - head_cie_ptr); - - if (res == DW_DLV_OK) { - cur_cie_ptr = cie_ptr_to_use; - /* Ok. Seen already. */ - } else if (res == DW_DLV_NO_ENTRY) { - /* CIE before its FDE in this case. */ - res = dwarf_create_cie_from_after_start(dbg, - &prefix, - section_ptr, - frame_ptr, - cie_count, - use_gnu_cie_calc, - &cie_ptr_to_use, - error); - /* ASSERT: res==DW_DLV_NO_ENTRY impossible. */ - if (res == DW_DLV_ERROR) { - dealloc_fde_cie_list_internal(head_fde_ptr, - head_cie_ptr); - return res; - } - /* ASSERT res != DW_DLV_NO_ENTRY */ - cie_count++; - chain_up_cie(cie_ptr_to_use, &head_cie_ptr, - &tail_cie_ptr); - cur_cie_ptr = tail_cie_ptr; - } else { /* res == DW_DLV_ERROR */ - - dealloc_fde_cie_list_internal(head_fde_ptr, - head_cie_ptr); - return res; - } - frame_ptr = cie_ptr_to_use->ci_cie_start + - cie_ptr_to_use->ci_length + - cie_ptr_to_use->ci_length_size + - cie_ptr_to_use->ci_extension_size; - continue; - } else { - /* this is an FDE, Frame Description Entry, see the Dwarf - Spec, section 6.4.1 */ - int res = DW_DLV_ERROR; - Dwarf_Cie cie_ptr_to_use = 0; - Dwarf_Fde fde_ptr_to_use = 0; - - /* Do not call this twice on one prefix, as - prefix.cf_cie_id_addr is altered as a side effect. */ - Dwarf_Small *cieptr_val = - get_cieptr_given_offset(prefix.cf_cie_id, - use_gnu_cie_calc, - section_ptr, - prefix.cf_cie_id_addr); - - res = dwarf_find_existing_cie_ptr(cieptr_val, - cur_cie_ptr, - &cie_ptr_to_use, - head_cie_ptr); - if (res == DW_DLV_OK) { - cur_cie_ptr = cie_ptr_to_use; - /* Ok. Seen CIE already. */ - } else if (res == DW_DLV_NO_ENTRY) { - res = dwarf_create_cie_from_start(dbg, - cieptr_val, - section_ptr, - section_index, - section_length, - frame_ptr_end, - cie_id_value, - cie_count, - use_gnu_cie_calc, - &cie_ptr_to_use, - error); - if (res == DW_DLV_ERROR) { - dealloc_fde_cie_list_internal(head_fde_ptr, - head_cie_ptr); - return res; - } else if (res == DW_DLV_NO_ENTRY) { - return res; - } - ++cie_count; - chain_up_cie(cie_ptr_to_use, &head_cie_ptr, - &tail_cie_ptr); - cur_cie_ptr = tail_cie_ptr; - - } else { - /* DW_DLV_ERROR */ - return res; - } - - res = dwarf_create_fde_from_after_start(dbg, - &prefix, - section_ptr, - frame_ptr, - use_gnu_cie_calc, - cie_ptr_to_use, - &fde_ptr_to_use, - error); - if (res == DW_DLV_ERROR) { - return res; - } - chain_up_fde(fde_ptr_to_use, &head_fde_ptr, &cur_fde_ptr); - fde_count++; - /* ASSERT: DW_DLV_OK. */ - frame_ptr = fde_ptr_to_use->fd_fde_start + - fde_ptr_to_use->fd_length + - fde_ptr_to_use->fd_length_size + - fde_ptr_to_use->fd_extension_size; - continue; - - } - - } - - /* Now build list of CIEs from the list. If there are no CIEs - there should be no FDEs. */ - if (cie_count > 0) { - cie_list_ptr = (Dwarf_Cie *) - _dwarf_get_alloc(dbg, DW_DLA_LIST, cie_count); - } else { - if(fde_count > 0) { - dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr); - _dwarf_error(dbg, error, DW_DLE_ORPHAN_FDE); - return DW_DLV_ERROR; - } - dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr); - return DW_DLV_NO_ENTRY; - } - if (cie_list_ptr == NULL) { - dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return DW_DLV_ERROR; - } - cur_cie_ptr = head_cie_ptr; - for (i = 0; i < cie_count; i++) { - *(cie_list_ptr + i) = cur_cie_ptr; - cur_cie_ptr = cur_cie_ptr->ci_next; - } - - - - /* Now build array of FDEs from the list. - With orphan CIEs (meaning no FDEs) lets not return DW_DLV_NO_ENTRY */ - if (fde_count > 0) { - fde_list_ptr = (Dwarf_Fde *) - _dwarf_get_alloc(dbg, DW_DLA_LIST, fde_count); - } - - /* It is ok if fde_list_ptr is NULL, we just have no fdes. */ - cur_fde_ptr = head_fde_ptr; - for (i = 0; i < fde_count; i++) { - *(fde_list_ptr + i) = cur_fde_ptr; - cur_fde_ptr = cur_fde_ptr->fd_next; - } - - - /* Return arguments. */ - *cie_data = cie_list_ptr; - *cie_element_count = cie_count; - - *fde_data = fde_list_ptr; - *fde_element_count = fde_count; - if(use_gnu_cie_calc) { - dbg->de_fde_data_eh = fde_list_ptr; - dbg->de_fde_count_eh = fde_count; - dbg->de_cie_data_eh = cie_list_ptr; - dbg->de_cie_count_eh = cie_count; - } else { - dbg->de_fde_data = fde_list_ptr; - dbg->de_fde_count = fde_count; - dbg->de_cie_data = cie_list_ptr; - dbg->de_cie_count = cie_count; - } - - /* Sort the list by the address so that dwarf_get_fde_at_pc() can - binary search this list. */ - if(fde_count > 0) { - qsort((void *) fde_list_ptr, fde_count, sizeof(Dwarf_Ptr), - qsort_compare); - } - - return (DW_DLV_OK); -} - -/* Internal function, not called by consumer code. - 'prefix' has accumulated the info up thru the cie-id - and now we consume the rest and build a Dwarf_Cie_s structure. -*/ -int -dwarf_create_cie_from_after_start(Dwarf_Debug dbg, - struct cie_fde_prefix_s *prefix, - Dwarf_Small * section_pointer, - Dwarf_Small * frame_ptr, - Dwarf_Unsigned cie_count, - int use_gnu_cie_calc, - Dwarf_Cie * cie_ptr_out, - Dwarf_Error * error) -{ - Dwarf_Cie new_cie = 0; - - /* egcs-1.1.2 .eh_frame uses 0 as the distinguishing id. sgi uses - -1 (in .debug_frame). .eh_frame not quite identical to - .debug_frame */ - /* We here default the address size as it is not present - in DWARF2 or DWARF3 cie data, below we set it right if - it is present. */ - Dwarf_Half address_size = dbg->de_pointer_size; - Dwarf_Small eh_fde_encoding = 0; - Dwarf_Small *augmentation = 0; - Dwarf_Half segment_size = 0; - Dwarf_Sword data_alignment_factor = -1; - Dwarf_Word code_alignment_factor = 4; - Dwarf_Unsigned return_address_register = 31; - int local_length_size = 0; - Dwarf_Word leb128_length = 0; - Dwarf_Unsigned cie_aug_data_len = 0; - Dwarf_Small *cie_aug_data = 0; - Dwarf_Addr gnu_personality_handler_addr = 0; - unsigned char gnu_personality_handler_encoding = 0; - unsigned char gnu_lsda_encoding = 0; - unsigned char gnu_fde_begin_encoding = 0; - - - enum Dwarf_augmentation_type augt = aug_unknown; - - - /* this is a CIE, Common Information Entry: See the dwarf spec, - section 6.4.1 */ - Dwarf_Small version = *(Dwarf_Small *) frame_ptr; - - frame_ptr++; - if (version != DW_CIE_VERSION && version != DW_CIE_VERSION3 && - version != DW_CIE_VERSION4) { - _dwarf_error(dbg, error, DW_DLE_FRAME_VERSION_BAD); - return (DW_DLV_ERROR); - } - - augmentation = frame_ptr; - frame_ptr = frame_ptr + strlen((char *) frame_ptr) + 1; - augt = _dwarf_get_augmentation_type(dbg, - augmentation, use_gnu_cie_calc); - if (augt == aug_eh) { - /* REFERENCED *//* Not used in this instance */ - Dwarf_Unsigned exception_table_addr; - - /* this is per egcs-1.1.2 as on RH 6.0 */ - READ_UNALIGNED(dbg, exception_table_addr, - Dwarf_Unsigned, frame_ptr, local_length_size); - frame_ptr += local_length_size; - } - { - Dwarf_Unsigned lreg = 0; - unsigned long size = 0; - - if( version == DW_CIE_VERSION4) { - address_size = *((unsigned char *)frame_ptr); - ++frame_ptr; - segment_size = *((unsigned char *)frame_ptr); - ++frame_ptr; - } - - DECODE_LEB128_UWORD(frame_ptr, lreg); - code_alignment_factor = (Dwarf_Word) lreg; - - data_alignment_factor = - (Dwarf_Sword) _dwarf_decode_s_leb128(frame_ptr, - &leb128_length); - - frame_ptr = frame_ptr + leb128_length; - - return_address_register = - _dwarf_get_return_address_reg(frame_ptr, version, &size); - if (return_address_register > dbg->de_frame_reg_rules_entry_count) { - _dwarf_error(dbg, error, DW_DLE_CIE_RET_ADDR_REG_ERROR); - return (DW_DLV_ERROR); - } - frame_ptr += size; - } - switch (augt) { - case aug_empty_string: - break; - case aug_irix_mti_v1: - break; - case aug_irix_exception_table:{ - Dwarf_Unsigned lreg = 0; - Dwarf_Word length_of_augmented_fields; - - /* Decode the length of augmented fields. */ - DECODE_LEB128_UWORD(frame_ptr, lreg); - length_of_augmented_fields = (Dwarf_Word) lreg; - - - /* set the frame_ptr to point at the instruction start. */ - frame_ptr += length_of_augmented_fields; - } - break; - - case aug_eh:{ - - int err = 0; - unsigned long increment = 0; - - if (!use_gnu_cie_calc) { - /* This should be impossible. */ - _dwarf_error(dbg, error, - DW_DLE_FRAME_AUGMENTATION_UNKNOWN); - return DW_DLV_ERROR; - } - - err = get_gcc_eh_augmentation(dbg, frame_ptr, &increment, - augt, - prefix->cf_section_ptr, - &eh_fde_encoding, - (char *) augmentation); - if (err == DW_DLV_ERROR) { - _dwarf_error(dbg, error, - DW_DLE_FRAME_AUGMENTATION_UNKNOWN); - return DW_DLV_ERROR; - } - frame_ptr += increment; - break; - } - case aug_gcc_eh_z:{ - /* Here we have Augmentation Data Length (uleb128) followed - by Augmentation Data bytes. */ - int res = DW_DLV_ERROR; - Dwarf_Unsigned adlen = 0; - - DECODE_LEB128_UWORD(frame_ptr, adlen); - cie_aug_data_len = adlen; - cie_aug_data = frame_ptr; - res = gnu_aug_encodings(dbg, - (char *) augmentation, - cie_aug_data, - cie_aug_data_len, - address_size, - &gnu_personality_handler_encoding, - &gnu_lsda_encoding, - &gnu_fde_begin_encoding, - &gnu_personality_handler_addr); - if (res != DW_DLV_OK) { - _dwarf_error(dbg, error, - DW_DLE_FRAME_AUGMENTATION_UNKNOWN); - return res; - } - - - frame_ptr += adlen; - break; - } - case aug_armcc: - break; - default:{ - /* We do not understand the augmentation string. No - assumption can be made about any fields other than what - we have already read. */ - frame_ptr = prefix->cf_start_addr + - prefix->cf_length + prefix->cf_local_length_size - + prefix->cf_local_extension_size; - /* FIX -- What are the values of data_alignment_factor, - code_alignement_factor, return_address_register and - instruction start? They were clearly uninitalized in the - previous version and I am leaving them the same way. */ - break; - } - } /* End switch on augmentation type. */ - - new_cie = (Dwarf_Cie) _dwarf_get_alloc(dbg, DW_DLA_CIE, 1); - if (new_cie == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - new_cie->ci_cie_version_number = version; - new_cie->ci_initial_table = NULL; - new_cie->ci_length = (Dwarf_Word) prefix->cf_length; - new_cie->ci_length_size = prefix->cf_local_length_size; - new_cie->ci_extension_size = prefix->cf_local_extension_size; - new_cie->ci_augmentation = (char *) augmentation; - - new_cie->ci_data_alignment_factor = - (Dwarf_Sbyte) data_alignment_factor; - new_cie->ci_code_alignment_factor = - (Dwarf_Small) code_alignment_factor; - new_cie->ci_return_address_register = return_address_register; - new_cie->ci_cie_start = prefix->cf_start_addr; - new_cie->ci_cie_instr_start = frame_ptr; - new_cie->ci_dbg = dbg; - new_cie->ci_augmentation_type = augt; - new_cie->ci_gnu_eh_augmentation_len = cie_aug_data_len; - new_cie->ci_gnu_eh_augmentation_bytes = cie_aug_data; - new_cie->ci_gnu_personality_handler_encoding = - gnu_personality_handler_encoding; - new_cie->ci_gnu_personality_handler_addr = - gnu_personality_handler_addr; - new_cie->ci_gnu_lsda_encoding = gnu_lsda_encoding; - new_cie->ci_gnu_fde_begin_encoding = gnu_fde_begin_encoding; - - new_cie->ci_index = cie_count; - new_cie->ci_section_ptr = prefix->cf_section_ptr; - /* The Following new in DWARF4 */ - new_cie->ci_address_size = address_size; - new_cie->ci_segment_size = segment_size; - validate_length(dbg,new_cie,new_cie->ci_length, - new_cie->ci_length_size, new_cie->ci_extension_size, - new_cie->ci_section_ptr, - new_cie->ci_cie_start,"cie"); - - *cie_ptr_out = new_cie; - return DW_DLV_OK; - -} - - -/* Internal function, not called by consumer code. - 'prefix' has accumulated the info up thru the cie-id - and now we consume the rest and build a Dwarf_Fde_s structure. -*/ - -int -dwarf_create_fde_from_after_start(Dwarf_Debug dbg, - struct cie_fde_prefix_s *prefix, - Dwarf_Small * section_pointer, - Dwarf_Small * frame_ptr, - int use_gnu_cie_calc, - Dwarf_Cie cie_ptr_in, - Dwarf_Fde * fde_ptr_out, - Dwarf_Error * error) -{ - Dwarf_Fde new_fde = 0; - Dwarf_Cie cieptr = cie_ptr_in; - Dwarf_Small *saved_frame_ptr = 0; - - Dwarf_Small *initloc = frame_ptr; - Dwarf_Signed offset_into_exception_tables - /* must be min dwarf_sfixed in size */ - = (Dwarf_Signed) DW_DLX_NO_EH_OFFSET; - Dwarf_Small *fde_aug_data = 0; - Dwarf_Unsigned fde_aug_data_len = 0; - Dwarf_Addr cie_base_offset = prefix->cf_cie_id; - Dwarf_Addr initial_location = 0; /* must be min de_pointer_size - bytes in size */ - Dwarf_Addr address_range = 0; /* must be min de_pointer_size - bytes in size */ - Dwarf_Half address_size = cie_ptr_in->ci_address_size; - - enum Dwarf_augmentation_type augt = cieptr->ci_augmentation_type; - - if (augt == aug_gcc_eh_z) { - /* If z augmentation this is eh_frame, and initial_location and - address_range in the FDE are read according to the CIE - augmentation string instructions. */ - - { - Dwarf_Small *fp_updated = 0; - int res = read_encoded_ptr(dbg, - section_pointer, - frame_ptr, - cieptr-> ci_gnu_fde_begin_encoding, - address_size, - &initial_location, - &fp_updated); - if (res != DW_DLV_OK) { - _dwarf_error(dbg, error, - DW_DLE_FRAME_AUGMENTATION_UNKNOWN); - return DW_DLV_ERROR; - } - frame_ptr = fp_updated; - /* For the address-range it makes no sense to be - pc-relative, so we turn it off with a section_pointer of - NULL. Masking off DW_EH_PE_pcrel from the - ci_gnu_fde_begin_encoding in this call would also work - to turn off DW_EH_PE_pcrel. */ - res = read_encoded_ptr(dbg, (Dwarf_Small *) NULL, - frame_ptr, - cieptr->ci_gnu_fde_begin_encoding, - address_size, - &address_range, &fp_updated); - if (res != DW_DLV_OK) { - _dwarf_error(dbg, error, - DW_DLE_FRAME_AUGMENTATION_UNKNOWN); - return DW_DLV_ERROR; - } - frame_ptr = fp_updated; - } - { - Dwarf_Unsigned adlen = 0; - - DECODE_LEB128_UWORD(frame_ptr, adlen); - fde_aug_data_len = adlen; - fde_aug_data = frame_ptr; - frame_ptr += adlen; - } - - } else { - READ_UNALIGNED(dbg, initial_location, Dwarf_Addr, - frame_ptr, address_size); - frame_ptr += address_size; - - READ_UNALIGNED(dbg, address_range, Dwarf_Addr, - frame_ptr, address_size); - frame_ptr += address_size; - } - - - - - - switch (augt) { - case aug_irix_mti_v1: - case aug_empty_string: - break; - case aug_irix_exception_table:{ - Dwarf_Unsigned lreg = 0; - Dwarf_Word length_of_augmented_fields = 0; - - DECODE_LEB128_UWORD(frame_ptr, lreg); - length_of_augmented_fields = (Dwarf_Word) lreg; - - saved_frame_ptr = frame_ptr; - /* The first word is an offset into exception tables. - Defined as a 32bit offset even for CC -64. */ - READ_UNALIGNED(dbg, offset_into_exception_tables, - Dwarf_Addr, frame_ptr, sizeof(Dwarf_sfixed)); - SIGN_EXTEND(offset_into_exception_tables, - sizeof(Dwarf_sfixed)); - frame_ptr = saved_frame_ptr + length_of_augmented_fields; - } - break; - case aug_eh:{ - Dwarf_Unsigned eh_table_value = 0; - - if (!use_gnu_cie_calc) { - /* This should be impossible. */ - _dwarf_error(dbg, error, - DW_DLE_FRAME_AUGMENTATION_UNKNOWN); - return DW_DLV_ERROR; - } - - /* gnu eh fde case. we do not need to do anything */ - /*REFERENCED*/ /* Not used in this instance of the - macro */ - READ_UNALIGNED(dbg, eh_table_value, - Dwarf_Unsigned, frame_ptr, - address_size); - frame_ptr += address_size; - } - break; - - case aug_gcc_eh_z:{ - /* The Augmentation Data Length is here, followed by the - Augmentation Data bytes themselves. */ - } - break; - case aug_armcc: - break; - case aug_past_last: - break; - case aug_unknown: - _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN); - return DW_DLV_ERROR; - } /* End switch on augmentation type */ - new_fde = (Dwarf_Fde) _dwarf_get_alloc(dbg, DW_DLA_FDE, 1); - if (new_fde == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - new_fde->fd_length = prefix->cf_length; - new_fde->fd_length_size = prefix->cf_local_length_size; - new_fde->fd_extension_size = prefix->cf_local_extension_size; - new_fde->fd_is_eh = use_gnu_cie_calc; - new_fde->fd_cie_offset = cie_base_offset; - new_fde->fd_cie_index = cieptr->ci_index; - new_fde->fd_cie = cieptr; - new_fde->fd_initial_location = initial_location; - new_fde->fd_initial_loc_pos = initloc; - new_fde->fd_address_range = address_range; - new_fde->fd_fde_start = prefix->cf_start_addr; - new_fde->fd_fde_instr_start = frame_ptr; - new_fde->fd_dbg = dbg; - new_fde->fd_offset_into_exception_tables = - offset_into_exception_tables; - - new_fde->fd_section_ptr = prefix->cf_section_ptr; - new_fde->fd_section_index = prefix->cf_section_index; - new_fde->fd_section_length = prefix->cf_section_length; - - new_fde->fd_gnu_eh_augmentation_bytes = fde_aug_data; - new_fde->fd_gnu_eh_augmentation_len = fde_aug_data_len; - validate_length(dbg,cieptr,new_fde->fd_length, - new_fde->fd_length_size, new_fde->fd_extension_size, - new_fde->fd_section_ptr,new_fde->fd_fde_start,"fde"); - - - *fde_ptr_out = new_fde; - return DW_DLV_OK; -} - -/* called by qsort to compare FDE entries. - Consumer code expects the array of FDE pointers to be in address order. -*/ -static int -qsort_compare(const void *elem1, const void *elem2) -{ - Dwarf_Fde fde1 = *(Dwarf_Fde *) elem1; - Dwarf_Fde fde2 = *(Dwarf_Fde *) elem2; - Dwarf_Addr addr1 = fde1->fd_initial_location; - Dwarf_Addr addr2 = fde2->fd_initial_location; - - if (addr1 < addr2) { - return -1; - } else if (addr1 > addr2) { - return 1; - } - return 0; -} - - -/* Read in the common cie/fde prefix, including reading - * the cie-value which shows which this is: cie or fde. - * */ -int -dwarf_read_cie_fde_prefix(Dwarf_Debug dbg, - Dwarf_Small * frame_ptr_in, - Dwarf_Small * section_ptr_in, - Dwarf_Unsigned section_index_in, - Dwarf_Unsigned section_length_in, - struct cie_fde_prefix_s *data_out, - Dwarf_Error * error) -{ - Dwarf_Unsigned length = 0; - int local_length_size = 0; - int local_extension_size = 0; - Dwarf_Small *frame_ptr = frame_ptr_in; - Dwarf_Small *cie_ptr_addr = 0; - Dwarf_Unsigned cie_id = 0; - - /* READ_AREA_LENGTH updates frame_ptr for consumed bytes */ - READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned, - frame_ptr, local_length_size, - local_extension_size); - - if (length == 0) { - /* nul bytes at end of section, seen at end of egcs eh_frame - sections (in a.out). Take this as meaning no more CIE/FDE - data. We should be very close to end of section. */ - return DW_DLV_NO_ENTRY; - } - - cie_ptr_addr = frame_ptr; - READ_UNALIGNED(dbg, cie_id, Dwarf_Unsigned, - frame_ptr, local_length_size); - SIGN_EXTEND(cie_id, local_length_size); - frame_ptr += local_length_size; - - data_out->cf_start_addr = frame_ptr_in; - data_out->cf_addr_after_prefix = frame_ptr; - - data_out->cf_length = length; - data_out->cf_local_length_size = local_length_size; - data_out->cf_local_extension_size = local_extension_size; - data_out->cf_cie_id = cie_id; - data_out->cf_cie_id_addr = cie_ptr_addr; - data_out->cf_section_ptr = section_ptr_in; - data_out->cf_section_index = section_index_in; - data_out->cf_section_length = section_length_in; - return DW_DLV_OK; -} - -/* On various errors previously-allocated CIEs and FDEs - must be cleaned up. - This helps avoid leaks in case of errors. -*/ -static void -dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr, - Dwarf_Cie head_cie_ptr) -{ - Dwarf_Fde curfde = 0; - Dwarf_Cie curcie = 0; - Dwarf_Fde nextfde = 0; - Dwarf_Cie nextcie = 0; - - for (curfde = head_fde_ptr; curfde; curfde = nextfde) { - nextfde = curfde->fd_next; - dwarf_dealloc(curfde->fd_dbg, curfde, DW_DLA_FDE); - } - for (curcie = head_cie_ptr; curcie; curcie = nextcie) { - Dwarf_Frame frame = curcie->ci_initial_table; - - nextcie = curcie->ci_next; - if (frame) - dwarf_dealloc(curcie->ci_dbg, frame, DW_DLA_FRAME); - dwarf_dealloc(curcie->ci_dbg, curcie, DW_DLA_CIE); - } -} - -/* Find the cie whose id value is given: the id - * value is, per DWARF2/3, an offset in the section. - * For .debug_frame, zero is a legal offset. For - * GNU .eh_frame it is not a legal offset. - * 'cie_ptr' is a pointer into our section, not an offset. */ -static int -dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr, - Dwarf_Cie cur_cie_ptr, - Dwarf_Cie * cie_ptr_to_use_out, - Dwarf_Cie head_cie_ptr) -{ - Dwarf_Cie next = 0; - - if (cur_cie_ptr && cie_ptr == cur_cie_ptr->ci_cie_start) { - /* Usually, we use the same cie again and again. */ - *cie_ptr_to_use_out = cur_cie_ptr; - return DW_DLV_OK; - } - for (next = head_cie_ptr; next; next = next->ci_next) { - if (cie_ptr == next->ci_cie_start) { - *cie_ptr_to_use_out = next; - return DW_DLV_OK; - } - } - return DW_DLV_NO_ENTRY; -} - - -/* We have a valid cie_ptr_val that has not been - * turned into an internal Cie yet. Do so now. - * Returns DW_DLV_OK or DW_DLV_ERROR, never - * DW_DLV_NO_ENTRY. - - 'section_ptr' - Points to first byte of section data. - 'section_length' - Length of the section, in bytes. - 'frame_ptr_end' - Points 1-past last byte of section data. - * */ -static int -dwarf_create_cie_from_start(Dwarf_Debug dbg, - Dwarf_Small * cie_ptr_val, - Dwarf_Small * section_ptr, - Dwarf_Unsigned section_index, - Dwarf_Unsigned section_length, - Dwarf_Small * frame_ptr_end, - Dwarf_Unsigned cie_id_value, - Dwarf_Unsigned cie_count, - int use_gnu_cie_calc, - Dwarf_Cie * cie_ptr_to_use_out, - Dwarf_Error * error) -{ - struct cie_fde_prefix_s prefix; - int res = DW_DLV_ERROR; - Dwarf_Small *frame_ptr = cie_ptr_val; - - if (frame_ptr < section_ptr || frame_ptr > frame_ptr_end) { - _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD); - return DW_DLV_ERROR; - } - /* First read in the 'common prefix' to figure out what * we are to - do with this entry. If it is not a cie * we are in big trouble. */ - memset(&prefix, 0, sizeof(prefix)); - res = dwarf_read_cie_fde_prefix(dbg, frame_ptr, section_ptr, - section_index, section_length, - &prefix, error); - if (res == DW_DLV_ERROR) { - return res; - } - if (res == DW_DLV_NO_ENTRY) { - /* error. */ - _dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR); - return DW_DLV_ERROR; - - } - - if (prefix.cf_cie_id != cie_id_value) { - _dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR); - return DW_DLV_ERROR; - } - frame_ptr = prefix.cf_addr_after_prefix; - res = dwarf_create_cie_from_after_start(dbg, - &prefix, - section_ptr, - frame_ptr, - cie_count, - use_gnu_cie_calc, - cie_ptr_to_use_out, error); - return res; - -} - - -/* This is for gnu eh frames, the 'z' case. - We find the letter involved - Return the augmentation character and, if applicable, - the personality routine address. - - personality_routine_out - - if 'P' is augchar, is personality handler addr. - Otherwise is not set. - aug_data - if 'P' points to data space of the - aug_data_len - length of areas aug_data points to. - -*/ -#if 0 -/* For debugging only. */ -void -dump_bytes(Dwarf_Small * start, long len) -{ - Dwarf_Small *end = start + len; - Dwarf_Small *cur = start; - - for (; cur < end; cur++) { - printf(" byte %d, data %02x\n", (int) (cur - start), *cur); - } - -} -#endif -static int -gnu_aug_encodings(Dwarf_Debug dbg, char *augmentation, - Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len, - Dwarf_Half address_size, - unsigned char *pers_hand_enc_out, - unsigned char *lsda_enc_out, - unsigned char *fde_begin_enc_out, - Dwarf_Addr * gnu_pers_addr_out) -{ - char *nc = 0; - Dwarf_Small *cur_aug_p = aug_data; - Dwarf_Small *end_aug_p = aug_data + aug_data_len; - - for (nc = augmentation; *nc; ++nc) { - char c = *nc; - - switch (c) { - case 'z': - /* Means that the augmentation data is present. */ - continue; - - case 'S': - /* Indicates this is a signal stack frame. Debuggers have to do - special handling. We don't need to do more than print this flag at - the right time, though (see dwarfdump where it prints the augmentation - string). - A signal stack frame (in some OS's) can only be - unwound (backtraced) by knowing it is a signal stack frame - (perhaps by noticing the name of the function for the stack frame - if the name can be found somehow) and figuring - out (or knowing) how the kernel and libc pushed a structure - onto the stack and loading registers from that structure. - Totally different from normal stack unwinding. - This flag gives an unwinder a big leg up by decoupling the - 'hint: this is a stack frame' from knowledge like - the function name (the name might be unavailable at unwind time). - */ - break; - - case 'L': - if (cur_aug_p > end_aug_p) { - return DW_DLV_ERROR; - } - *lsda_enc_out = *(unsigned char *) cur_aug_p; - ++cur_aug_p; - break; - case 'R': - /* Followed by a one byte argument giving the - pointer encoding for the address pointers in the fde. */ - if (cur_aug_p >= end_aug_p) { - return DW_DLV_ERROR; - } - *fde_begin_enc_out = *(unsigned char *) cur_aug_p; - ++cur_aug_p; - break; - case 'P':{ - int res = DW_DLV_ERROR; - Dwarf_Small *updated_aug_p = 0; - unsigned char encoding = 0; - - if (cur_aug_p >= end_aug_p) { - return DW_DLV_ERROR; - } - encoding = *(unsigned char *) cur_aug_p; - *pers_hand_enc_out = encoding; - ++cur_aug_p; - if (cur_aug_p > end_aug_p) { - return DW_DLV_ERROR; - } - /* DW_EH_PE_pcrel makes no sense here, so we turn it - off via a section pointer of NULL. */ - res = read_encoded_ptr(dbg, - (Dwarf_Small *) NULL, - cur_aug_p, - encoding, - address_size, - gnu_pers_addr_out, - &updated_aug_p); - if (res != DW_DLV_OK) { - return res; - } - cur_aug_p = updated_aug_p; - if (cur_aug_p > end_aug_p) { - return DW_DLV_ERROR; - } - } - break; - default: - return DW_DLV_ERROR; - - } - } - - return DW_DLV_OK; -} - -/* Given augmentation character (the encoding) giving the -address format, read the address from input_field -and return an incremented value 1 past the input bytes of the -address. -Push the address read back thru the *addr pointer. -See LSB (Linux Standar Base) exception handling documents. -*/ -static int -read_encoded_ptr(Dwarf_Debug dbg, - Dwarf_Small * section_pointer, - Dwarf_Small * input_field, - int gnu_encoding, - Dwarf_Half address_size, - Dwarf_Unsigned * addr, - Dwarf_Small ** input_field_updated) -{ - Dwarf_Word length = 0; - int value_type = gnu_encoding & 0xf; - Dwarf_Small *input_field_original = input_field; - - if (gnu_encoding == 0xff) { - /* There is no data here. */ - - *addr = 0; - *input_field_updated = input_field; - /* Should we return DW_DLV_NO_ENTRY? */ - return DW_DLV_OK; - } - switch (value_type) { - case DW_EH_PE_absptr:{ - /* value_type is zero. Treat as pointer size of the object. - */ - Dwarf_Unsigned ret_value = 0; - - READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, - input_field, address_size); - *addr = ret_value; - *input_field_updated = input_field + address_size; - } - break; - case DW_EH_PE_uleb128:{ - Dwarf_Unsigned val = _dwarf_decode_u_leb128(input_field, - &length); - - *addr = val; - *input_field_updated = input_field + length; - } - break; - case DW_EH_PE_udata2:{ - Dwarf_Unsigned ret_value = 0; - - READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, - input_field, 2); - *addr = ret_value; - *input_field_updated = input_field + 2; - } - break; - - case DW_EH_PE_udata4:{ - - Dwarf_Unsigned ret_value = 0; - - /* ASSERT: sizeof(Dwarf_ufixed) == 4 */ - READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, - input_field, sizeof(Dwarf_ufixed)); - *addr = ret_value; - *input_field_updated = input_field + sizeof(Dwarf_ufixed); - } - break; - - case DW_EH_PE_udata8:{ - Dwarf_Unsigned ret_value = 0; - - /* ASSERT: sizeof(Dwarf_Unsigned) == 8 */ - READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, - input_field, sizeof(Dwarf_Unsigned)); - *addr = ret_value; - *input_field_updated = input_field + sizeof(Dwarf_Unsigned); - } - break; - - case DW_EH_PE_sleb128:{ - Dwarf_Signed val = _dwarf_decode_s_leb128(input_field, - &length); - - *addr = (Dwarf_Unsigned) val; - *input_field_updated = input_field + length; - } - break; - case DW_EH_PE_sdata2:{ - Dwarf_Unsigned val = 0; - - READ_UNALIGNED(dbg, val, Dwarf_Unsigned, input_field, 2); - SIGN_EXTEND(val, 2); - *addr = (Dwarf_Unsigned) val; - *input_field_updated = input_field + 2; - } - break; - - case DW_EH_PE_sdata4:{ - Dwarf_Unsigned val = 0; - - /* ASSERT: sizeof(Dwarf_ufixed) == 4 */ - READ_UNALIGNED(dbg, val, - Dwarf_Unsigned, input_field, - sizeof(Dwarf_ufixed)); - SIGN_EXTEND(val, sizeof(Dwarf_ufixed)); - *addr = (Dwarf_Unsigned) val; - *input_field_updated = input_field + sizeof(Dwarf_ufixed); - } - break; - case DW_EH_PE_sdata8:{ - Dwarf_Unsigned val = 0; - - /* ASSERT: sizeof(Dwarf_Unsigned) == 8 */ - READ_UNALIGNED(dbg, val, - Dwarf_Unsigned, input_field, - sizeof(Dwarf_Unsigned)); - *addr = (Dwarf_Unsigned) val; - *input_field_updated = input_field + sizeof(Dwarf_Unsigned); - } - break; - default: - return DW_DLV_ERROR; - - }; - /* The ELF ABI for gnu does not document the meaning of - DW_EH_PE_pcrel, which is awkward. It apparently means the value - we got above is pc-relative (meaning section-relative), so we - adjust the value. Section_pointer may be null if it is known - DW_EH_PE_pcrel cannot apply, such as for .debug_frame or for an - address-range value. */ - if (section_pointer && ((gnu_encoding & 0x70) == DW_EH_PE_pcrel)) { - /* Address (*addr) above is pc relative with respect to a - section. Add to the offset the base address (from elf) of - section and the distance of the field we are reading from - the section-beginning to get the actual address. */ - /* ASSERT: input_field_original >= section_pointer */ - Dwarf_Unsigned distance = - input_field_original - section_pointer; - *addr += dbg->de_debug_frame_eh_gnu.dss_addr + distance; - } - - return DW_DLV_OK; -} - - - - -/* - All augmentation string checking done here now. - - For .eh_frame, gcc from 3.3 uses the z style, earlier used - only "eh" as augmentation. We don't yet handle - decoding .eh_frame with the z style extensions like L P. - - These are nasty heuristics, but then that's life - as augmentations are implementation specific. -*/ -/* ARGSUSED */ -enum Dwarf_augmentation_type -_dwarf_get_augmentation_type(Dwarf_Debug dbg, - Dwarf_Small * augmentation_string, - int is_gcc_eh_frame) -{ - enum Dwarf_augmentation_type t = aug_unknown; - char *ag_string = (char *) augmentation_string; - - if (ag_string[0] == 0) { - /* Empty string. We'll just guess that we know what this means: - standard dwarf2/3 with no implementation-defined fields. */ - t = aug_empty_string; - } else if (strcmp(ag_string, DW_DEBUG_FRAME_AUGMENTER_STRING) == 0) { - /* The string is "mti v1". Used internally at SGI, probably - never shipped. Replaced by "z". Treat like 'nothing - special'. */ - t = aug_irix_mti_v1; - } else if (ag_string[0] == 'z') { - /* If it's IRIX cc, z means aug_irix_exception_table. z1 z2 - were designed as for IRIX CC, but never implemented */ - /* If it's gcc, z may be any of several things. "z" or z - followed optionally followed by one or more of L R P, each - of which means a value may be present. Should be in eh_frame - only, I think. */ - if (is_gcc_eh_frame) { - t = aug_gcc_eh_z; - } else if (ag_string[1] == 0) { - /* This is the normal IRIX C++ case, where there is an - offset into a table in each fde. The table being for - IRIX CC exception handling. */ - /* DW_CIE_AUGMENTER_STRING_V0 "z" */ - t = aug_irix_exception_table; - } /* Else unknown. */ - } else if (strncmp(ag_string, "eh", 2) == 0) { - /* gcc .eh_frame augmentation for egcs and gcc 2.x, at least - for x86. */ - t = aug_eh; - } else if (strcmp(ag_string, "armcc+") == 0) { - /* Arm uses this string to mean a bug in - in Arm compilers was fixed, changing to the standard - calculation of the CFA. See - http://sourceware.org/ml/gdb-patches/2006-12/msg00249.html - for details. */ - t = aug_armcc; - } else { - - } - return t; -} - -/* Using augmentation, and version - read in the augmentation data for GNU eh. - - Return DW_DLV_OK if we succeeded, - DW_DLV_ERR if we fail. - - On success, update 'size_of_augmentation_data' with - the length of the fields that are part of augmentation (so the - caller can increment frame_ptr appropriately). - - 'frame_ptr' points within section. - 'section_pointer' points to section base address in memory. -*/ -/* ARGSUSED */ -static int -get_gcc_eh_augmentation(Dwarf_Debug dbg, Dwarf_Small * frame_ptr, - unsigned long *size_of_augmentation_data, - enum Dwarf_augmentation_type augtype, - Dwarf_Small * section_pointer, - Dwarf_Small * fde_eh_encoding_out, - char *augmentation) -{ - char *suffix = 0; - unsigned long augdata_size = 0; - - if (augtype == aug_gcc_eh_z) { - /* Has leading 'z'. */ - Dwarf_Word leb128_length = 0; - - /* Dwarf_Unsigned eh_value = */ - _dwarf_decode_u_leb128(frame_ptr, &leb128_length); - augdata_size += leb128_length; - frame_ptr += leb128_length; - suffix = augmentation + 1; - } else { - /* Prefix is 'eh'. As in gcc 3.2. No suffix present - apparently. */ - suffix = augmentation + 2; - } - for (; *suffix; ++suffix) { - /* We have no idea what this is as yet. Some extensions beyond - dwarf exist which we do not yet handle. */ - return DW_DLV_ERROR; - - } - - *size_of_augmentation_data = augdata_size; - return DW_DLV_OK; -} - - -/* Make the 'cie_id_addr' consistent across .debug_frame and .eh_frame. - Calculate a pointer into section bytes given a cie_id, which is - trivial for .debug_frame, but a bit more work for .eh_frame. -*/ -static Dwarf_Small * -get_cieptr_given_offset(Dwarf_Unsigned cie_id_value, - int use_gnu_cie_calc, - Dwarf_Small * section_ptr, - Dwarf_Small * cie_id_addr) -{ - Dwarf_Small *cieptr = 0; - - if (use_gnu_cie_calc) { - /* cie_id value is offset, in section, of the cie_id itself, to - use vm ptr of the value, less the value, to get to the cie - itself. In addition, munge *cie_id_addr to look *as if* it - was from real dwarf. */ - cieptr = (Dwarf_Small *)(uintptr_t) - ((Dwarf_Unsigned)(uintptr_t)cie_id_addr) - - ((Dwarf_Unsigned) cie_id_value); - } else { - /* Traditional dwarf section offset is in cie_id */ - cieptr = (section_ptr + cie_id_value); - } - return cieptr; -} - -/* To properly release all spaced used. - Earlier approaches (before July 15, 2005) - letting client do the dealloc directly left - some data allocated. - This is directly called by consumer code. -*/ -void -dwarf_fde_cie_list_dealloc(Dwarf_Debug dbg, - Dwarf_Cie * cie_data, - Dwarf_Signed cie_element_count, - Dwarf_Fde * fde_data, - Dwarf_Signed fde_element_count) -{ - Dwarf_Signed i = 0; - - for (i = 0; i < cie_element_count; ++i) { - Dwarf_Frame frame = cie_data[i]->ci_initial_table; - - if (frame) - dwarf_dealloc(dbg, frame, DW_DLA_FRAME); - dwarf_dealloc(dbg, cie_data[i], DW_DLA_CIE); - } - for (i = 0; i < fde_element_count; ++i) { - dwarf_dealloc(dbg, fde_data[i], DW_DLA_FDE); - } - if (cie_data) - dwarf_dealloc(dbg, cie_data, DW_DLA_LIST); - if (fde_data) - dwarf_dealloc(dbg, fde_data, DW_DLA_LIST); - -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_frame3.c b/usr/src/tools/ctf/dwarf/common/dwarf_frame3.c deleted file mode 100644 index 7bd8ec86d5..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_frame3.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - - Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include -#include "dwarf_frame.h" -#include "dwarf_arange.h" /* using Arange as a way to build a list */ - -/* - Used by rqs (an IRIX application). - Not needed except for that one application. - Should be moved to its own source file since - it is so rarely needed. - Returns DW_DLV_OK if returns the arrays. - Returns DW_DLV_NO_ENTRY if no section. ?? (How do I tell?) - Returns DW_DLV_ERROR if there is an error. - - Uses DW_FRAME_CFA_COL because IRIX is only DWARF2 - and that is what IRIX compilers and compatible - compilers support on IRIX. -*/ -int -_dwarf_frame_address_offsets(Dwarf_Debug dbg, Dwarf_Addr ** addrlist, - Dwarf_Off ** offsetlist, - Dwarf_Signed * returncount, - Dwarf_Error * err) -{ - int retval = DW_DLV_OK; - int res = DW_DLV_ERROR; - Dwarf_Cie *cie_data; - Dwarf_Signed cie_count; - Dwarf_Fde *fde_data; - Dwarf_Signed fde_count; - Dwarf_Signed i; - Dwarf_Frame_Op *frame_inst; - Dwarf_Fde fdep; - Dwarf_Cie ciep; - Dwarf_Chain curr_chain = 0; - Dwarf_Chain head_chain = 0; - Dwarf_Chain prev_chain = 0; - Dwarf_Arange arange; - Dwarf_Unsigned arange_count = 0; - Dwarf_Addr *arange_addrs = 0; - Dwarf_Off *arange_offsets = 0; - - res = dwarf_get_fde_list(dbg, &cie_data, &cie_count, - &fde_data, &fde_count, err); - if (res != DW_DLV_OK) { - return res; - } - - res = _dwarf_load_section(dbg, &dbg->de_debug_frame, err); - if (res != DW_DLV_OK) { - return res; - } - - for (i = 0; i < cie_count; i++) { - Dwarf_Off instoff = 0; - Dwarf_Signed initial_instructions_length = 0; - Dwarf_Small *instr_end = 0; - Dwarf_Sword icount = 0; - int j = 0; - int dw_err; - - ciep = cie_data[i]; - instoff = ciep->ci_cie_instr_start - dbg->de_debug_frame.dss_data; - initial_instructions_length = ciep->ci_length + - ciep->ci_length_size + ciep->ci_extension_size - - (ciep->ci_cie_instr_start - ciep->ci_cie_start); - instr_end = ciep->ci_cie_instr_start + - initial_instructions_length; - res = _dwarf_exec_frame_instr( /* make_instr */ true, - &frame_inst, - /* search_pc= */ false, - /* search_pc_val= */ 0, - /* location */ 0, - ciep->ci_cie_instr_start, - instr_end, - /* Dwarf_frame= */ 0, - /* cie= */ 0, - dbg, - DW_FRAME_CFA_COL, - &icount, &dw_err); - if (res == DW_DLV_ERROR) { - _dwarf_error(dbg, err, dw_err); - return (res); - } else if (res == DW_DLV_NO_ENTRY) { - continue; - } - - for (j = 0; j < icount; ++j) { - Dwarf_Frame_Op *finst = frame_inst + j; - - if (finst->fp_base_op == 0 && finst->fp_extended_op == 1) { - /* is DW_CFA_set_loc */ - Dwarf_Addr add = (Dwarf_Addr) finst->fp_offset; - Dwarf_Off off = finst->fp_instr_offset + instoff; - - arange = (Dwarf_Arange) - _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1); - if (arange == NULL) { - _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - arange->ar_address = add; - arange->ar_info_offset = off; - arange_count++; - curr_chain = (Dwarf_Chain) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (curr_chain == NULL) { - _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - curr_chain->ch_item = arange; - if (head_chain == NULL) - head_chain = prev_chain = curr_chain; - else { - prev_chain->ch_next = curr_chain; - prev_chain = curr_chain; - } - } - } - dwarf_dealloc(dbg, frame_inst, DW_DLA_FRAME_BLOCK); - - } - for (i = 0; i < fde_count; i++) { - Dwarf_Small *instr_end = 0; - Dwarf_Sword icount = 0; - Dwarf_Signed instructions_length = 0; - Dwarf_Off instoff = 0; - Dwarf_Off off = 0; - Dwarf_Addr addr = 0; - int j = 0; - int dw_err; - - fdep = fde_data[i]; - off = fdep->fd_initial_loc_pos - dbg->de_debug_frame.dss_data; - addr = fdep->fd_initial_location; - arange = (Dwarf_Arange) - _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1); - if (arange == NULL) { - _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - arange->ar_address = addr; - arange->ar_info_offset = off; - arange_count++; - curr_chain = (Dwarf_Chain) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (curr_chain == NULL) { - _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - curr_chain->ch_item = arange; - if (head_chain == NULL) - head_chain = prev_chain = curr_chain; - else { - prev_chain->ch_next = curr_chain; - prev_chain = curr_chain; - } - - - instoff = fdep->fd_fde_instr_start - dbg->de_debug_frame.dss_data; - instructions_length = fdep->fd_length + - fdep->fd_length_size + fdep->fd_extension_size - - (fdep->fd_fde_instr_start - fdep->fd_fde_start); - instr_end = fdep->fd_fde_instr_start + instructions_length; - res = _dwarf_exec_frame_instr( /* make_instr */ true, - &frame_inst, - /* search_pc= */ false, - /* search_pc_val= */ 0, - /* location */ 0, - fdep->fd_fde_instr_start, - instr_end, - /* Dwarf_frame= */ 0, - /* cie= */ 0, - dbg, - DW_FRAME_CFA_COL, - &icount, &dw_err); - if (res == DW_DLV_ERROR) { - _dwarf_error(dbg, err, dw_err); - return (res); - } else if (res == DW_DLV_NO_ENTRY) { - continue; - } - - for (j = 0; j < icount; ++j) { - Dwarf_Frame_Op *finst2 = frame_inst + j; - - if (finst2->fp_base_op == 0 && finst2->fp_extended_op == 1) { - /* is DW_CFA_set_loc */ - Dwarf_Addr add = (Dwarf_Addr) finst2->fp_offset; - Dwarf_Off off = finst2->fp_instr_offset + instoff; - - arange = (Dwarf_Arange) - _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1); - if (arange == NULL) { - _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - arange->ar_address = add; - arange->ar_info_offset = off; - arange_count++; - curr_chain = (Dwarf_Chain) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (curr_chain == NULL) { - _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - curr_chain->ch_item = arange; - if (head_chain == NULL) - head_chain = prev_chain = curr_chain; - else { - prev_chain->ch_next = curr_chain; - prev_chain = curr_chain; - } - - } - } - dwarf_dealloc(dbg, frame_inst, DW_DLA_FRAME_BLOCK); - - } - dwarf_dealloc(dbg, fde_data, DW_DLA_LIST); - dwarf_dealloc(dbg, cie_data, DW_DLA_LIST); - arange_addrs = (Dwarf_Addr *) - _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count); - if (arange_addrs == NULL) { - _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - arange_offsets = (Dwarf_Off *) - _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count); - if (arange_offsets == NULL) { - _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - curr_chain = head_chain; - for (i = 0; i < arange_count; i++) { - Dwarf_Arange ar = curr_chain->ch_item; - - arange_addrs[i] = ar->ar_address; - arange_offsets[i] = ar->ar_info_offset; - prev_chain = curr_chain; - curr_chain = curr_chain->ch_next; - dwarf_dealloc(dbg, ar, DW_DLA_ARANGE); - dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN); - } - *returncount = arange_count; - *offsetlist = arange_offsets; - *addrlist = arange_addrs; - return retval; -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_funcs.c b/usr/src/tools/ctf/dwarf/common/dwarf_funcs.c deleted file mode 100644 index 8d725ae33f..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_funcs.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - - Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include "dwarf_funcs.h" -#include "dwarf_global.h" - -int -dwarf_get_funcs(Dwarf_Debug dbg, - Dwarf_Func ** funcs, - Dwarf_Signed * ret_func_count, Dwarf_Error * error) -{ - int res = _dwarf_load_section(dbg, &dbg->de_debug_funcnames,error); - if (res != DW_DLV_OK) { - return res; - } - - return _dwarf_internal_get_pubnames_like_data(dbg, - dbg->de_debug_funcnames.dss_data, - dbg->de_debug_funcnames.dss_size, - (Dwarf_Global **) funcs, /* Type punning for sections with identical format. */ - ret_func_count, - error, - DW_DLA_FUNC_CONTEXT, - DW_DLA_FUNC, - DW_DLE_DEBUG_FUNCNAMES_LENGTH_BAD, - DW_DLE_DEBUG_FUNCNAMES_VERSION_ERROR); -} - -/* Deallocating fully requires deallocating the list - and all entries. But some internal data is - not exposed, so we need a function with internal knowledge. -*/ - -void -dwarf_funcs_dealloc(Dwarf_Debug dbg, Dwarf_Func * dwgl, - Dwarf_Signed count) -{ - _dwarf_internal_globals_dealloc(dbg, (Dwarf_Global *) dwgl, - count, - DW_DLA_FUNC_CONTEXT, - DW_DLA_FUNC, DW_DLA_LIST); - return; -} - - - -int -dwarf_funcname(Dwarf_Func func_in, char **ret_name, Dwarf_Error * error) -{ - Dwarf_Global func = (Dwarf_Global) func_in; - - if (func == NULL) { - _dwarf_error(NULL, error, DW_DLE_FUNC_NULL); - return (DW_DLV_ERROR); - } - - *ret_name = (char *) (func->gl_name); - return DW_DLV_OK; -} - -int -dwarf_func_die_offset(Dwarf_Func func_in, - Dwarf_Off * return_offset, Dwarf_Error * error) -{ - Dwarf_Global func = (Dwarf_Global) func_in; - - return dwarf_global_die_offset(func, return_offset, error); -} - - -int -dwarf_func_cu_offset(Dwarf_Func func_in, - Dwarf_Off * return_offset, Dwarf_Error * error) -{ - Dwarf_Global func = (Dwarf_Global) func_in; - - return dwarf_global_cu_offset(func, return_offset, error); -} - - -int -dwarf_func_name_offsets(Dwarf_Func func_in, - char **ret_func_name, - Dwarf_Off * die_offset, - Dwarf_Off * cu_die_offset, Dwarf_Error * error) -{ - Dwarf_Global func = (Dwarf_Global) func_in; - - return dwarf_global_name_offsets(func, - ret_func_name, - die_offset, cu_die_offset, error); -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_funcs.h b/usr/src/tools/ctf/dwarf/common/dwarf_funcs.h deleted file mode 100644 index bf91c32157..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_funcs.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - - Copyright (C) 2000, 2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - - -typedef struct Dwarf_Func_Context_s *Dwarf_Func_Context; - - -/* struct never completed: see dwarf_global.h */ diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_global.c b/usr/src/tools/ctf/dwarf/common/dwarf_global.c deleted file mode 100644 index d1c090fa43..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_global.c +++ /dev/null @@ -1,607 +0,0 @@ -/* - - Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the Crittenden Lane address. -*/ - - - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include "dwarf_global.h" - - -#ifdef __sgi /* __sgi should only be defined for IRIX/MIPS. */ -/* The 'fixup' here intended for IRIX targets only. - With a 2+GB Elf64 IRIX executable (under 4GB in size), - some DIE offsets wrongly - got the 32bit upper bit sign extended. For the cu-header - offset in the .debug_pubnames section and in the - .debug_aranges section. - the 'varp' here is a pointer to an offset into .debug_info. - We fix up the offset here if it seems advisable.. - - As of June 2005 we have identified a series of mistakes - in ldx64 that can cause this (64 bit values getting passed - thru 32-bit signed knothole). -*/ -void -_dwarf_fix_up_offset_irix(Dwarf_Debug dbg, - Dwarf_Unsigned * varp, char *caller_site_name) -{ - - Dwarf_Unsigned var = *varp; - -#define UPPER33 0xffffffff80000000LL -#define LOWER32 0xffffffffLL - /* Restrict the hack to the known case. Upper 32 bits erroneously - sign extended from lower 32 upper bit. */ - if ((var & UPPER33) == UPPER33) { - var &= LOWER32; - /* Apply the fix. Dreadful hack. */ - *varp = var; - } -#undef UPPER33 -#undef LOWER32 - return; -} -#endif - - -int -dwarf_get_globals(Dwarf_Debug dbg, - Dwarf_Global ** globals, - Dwarf_Signed * return_count, Dwarf_Error * error) -{ - int res = _dwarf_load_section(dbg, &dbg->de_debug_pubnames,error); - if (res != DW_DLV_OK) { - return res; - } - - return _dwarf_internal_get_pubnames_like_data(dbg, - dbg->de_debug_pubnames.dss_data, - dbg->de_debug_pubnames.dss_size, - globals, - return_count, - error, - DW_DLA_GLOBAL_CONTEXT, - DW_DLA_GLOBAL, - DW_DLE_PUBNAMES_LENGTH_BAD, - DW_DLE_PUBNAMES_VERSION_ERROR); - -} - -/* Deallocating fully requires deallocating the list - and all entries. But some internal data is - not exposed, so we need a function with internal knowledge. -*/ - -void -dwarf_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl, - Dwarf_Signed count) -{ - _dwarf_internal_globals_dealloc(dbg, dwgl, - count, - DW_DLA_GLOBAL_CONTEXT, - DW_DLA_GLOBAL, DW_DLA_LIST); - return; -} - -void -_dwarf_internal_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl, - Dwarf_Signed count, - int context_code, - int global_code, int list_code) -{ - Dwarf_Signed i; - struct Dwarf_Global_Context_s *gcp = 0; - struct Dwarf_Global_Context_s *lastgcp = 0; - - for (i = 0; i < count; i++) { - Dwarf_Global dgb = dwgl[i]; - - gcp = dgb->gl_context; - - if (lastgcp != gcp) { - lastgcp = gcp; - dwarf_dealloc(dbg, gcp, context_code); - } - dwarf_dealloc(dbg, dgb, global_code); - } - dwarf_dealloc(dbg, dwgl, list_code); - return; -} - - -/* Sweeps the complete section. -*/ -int -_dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg, - Dwarf_Small * section_data_ptr, - Dwarf_Unsigned section_length, - Dwarf_Global ** globals, - Dwarf_Signed * return_count, - Dwarf_Error * error, - int context_code, - int global_code, - int length_err_num, - int version_err_num) -{ - - - Dwarf_Small *pubnames_like_ptr = 0; - - - - /* Points to the context for the current set of global names, and - contains information to identify the compilation-unit that the - set refers to. */ - Dwarf_Global_Context pubnames_context = 0; - - Dwarf_Half version = 0; - - /* - Offset from the start of compilation-unit for the current - global. */ - Dwarf_Off die_offset_in_cu = 0; - - Dwarf_Unsigned global_count = 0; - - /* Points to the current global read. */ - Dwarf_Global global = 0; - - /* Used to chain the Dwarf_Global_s structs for creating contiguous - list of pointers to the structs. */ - Dwarf_Chain curr_chain = 0; - Dwarf_Chain prev_chain = 0; - Dwarf_Chain head_chain = 0; - - /* Points to contiguous block of Dwarf_Global's to be returned. */ - Dwarf_Global *ret_globals = 0; - - /* Temporary counter. */ - Dwarf_Unsigned i = 0; - - - - - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - /* We will eventually need the .debug_info data. Load it now. */ - if (!dbg->de_debug_info.dss_data) { - int res = _dwarf_load_debug_info(dbg, error); - - if (res != DW_DLV_OK) { - return res; - } - } - - if (section_data_ptr == NULL) { - return (DW_DLV_NO_ENTRY); - } - - pubnames_like_ptr = section_data_ptr; - do { - Dwarf_Unsigned length = 0; - int local_extension_size = 0; - int local_length_size = 0; - - /* Some compilers emit padding at the end of each cu's area. - pubnames_ptr_past_end_cu records the true area end for this - cu's data. Essentially the length in the header and the 0 - terminator of the data are redundant information. The - dwarf2/3 spec does not mention what to do if the length is - past the 0 terminator. So we take any bytes left after the 0 - as padding and ignore them. */ - Dwarf_Small *pubnames_ptr_past_end_cu = 0; - - - pubnames_context = (Dwarf_Global_Context) - _dwarf_get_alloc(dbg, context_code, 1); - if (pubnames_context == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - /* READ_AREA_LENGTH updates pubnames_like_ptr for consumed - bytes. */ - READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned, - pubnames_like_ptr, local_length_size, - local_extension_size); - pubnames_context->pu_length_size = local_length_size; - pubnames_context->pu_extension_size = local_extension_size; - pubnames_context->pu_dbg = dbg; - - pubnames_ptr_past_end_cu = pubnames_like_ptr + length; - - READ_UNALIGNED(dbg, version, Dwarf_Half, - pubnames_like_ptr, sizeof(Dwarf_Half)); - pubnames_like_ptr += sizeof(Dwarf_Half); - if (version != CURRENT_VERSION_STAMP) { - _dwarf_error(dbg, error, version_err_num); - return (DW_DLV_ERROR); - } - - /* Offset of CU header in debug section. */ - READ_UNALIGNED(dbg, pubnames_context->pu_offset_of_cu_header, - Dwarf_Off, pubnames_like_ptr, - pubnames_context->pu_length_size); - pubnames_like_ptr += pubnames_context->pu_length_size; - - FIX_UP_OFFSET_IRIX_BUG(dbg, - pubnames_context->pu_offset_of_cu_header, - "pubnames cu header offset"); - - - READ_UNALIGNED(dbg, pubnames_context->pu_info_length, - Dwarf_Unsigned, pubnames_like_ptr, - pubnames_context->pu_length_size); - pubnames_like_ptr += pubnames_context->pu_length_size; - - if (pubnames_like_ptr > (section_data_ptr + section_length)) { - _dwarf_error(dbg, error, length_err_num); - return (DW_DLV_ERROR); - } - - /* Read initial offset (of DIE within CU) of a pubname, final - entry is not a pair, just a zero offset. */ - READ_UNALIGNED(dbg, die_offset_in_cu, Dwarf_Off, - pubnames_like_ptr, - pubnames_context->pu_length_size); - pubnames_like_ptr += pubnames_context->pu_length_size; - FIX_UP_OFFSET_IRIX_BUG(dbg, - die_offset_in_cu, "offset of die in cu"); - - /* Loop thru pairs. DIE off with CU followed by string. */ - while (die_offset_in_cu != 0) { - - /* Already read offset, pubnames_like_ptr now points to the - string. */ - global = - (Dwarf_Global) _dwarf_get_alloc(dbg, global_code, 1); - if (global == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - global_count++; - - global->gl_context = pubnames_context; - - global->gl_named_die_offset_within_cu = die_offset_in_cu; - - global->gl_name = pubnames_like_ptr; - - pubnames_like_ptr = pubnames_like_ptr + - strlen((char *) pubnames_like_ptr) + 1; - - - /* finish off current entry chain */ - curr_chain = - (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (curr_chain == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - /* Put current global on singly_linked list. */ - curr_chain->ch_item = (Dwarf_Global) global; - - if (head_chain == NULL) - head_chain = prev_chain = curr_chain; - else { - prev_chain->ch_next = curr_chain; - prev_chain = curr_chain; - } - - /* read offset for the *next* entry */ - READ_UNALIGNED(dbg, die_offset_in_cu, Dwarf_Off, - pubnames_like_ptr, - pubnames_context->pu_length_size); - - pubnames_like_ptr += pubnames_context->pu_length_size; - FIX_UP_OFFSET_IRIX_BUG(dbg, - die_offset_in_cu, - "offset of next die in cu"); - - if (pubnames_like_ptr > (section_data_ptr + section_length)) { - _dwarf_error(dbg, error, length_err_num); - return (DW_DLV_ERROR); - } - } - /* ASSERT: die_offset_in_cu == 0 */ - if (pubnames_like_ptr > pubnames_ptr_past_end_cu) { - /* This is some kind of error. This simply cannot happen. - The encoding is wrong or the length in the header for - this cu's contribution is wrong. */ - _dwarf_error(dbg, error, length_err_num); - return (DW_DLV_ERROR); - } - /* If there is some kind of padding at the end of the section, - as emitted by some compilers, skip over that padding and - simply ignore the bytes thus passed-over. With most - compilers, pubnames_like_ptr == pubnames_ptr_past_end_cu at - this point */ - pubnames_like_ptr = pubnames_ptr_past_end_cu; - - } while (pubnames_like_ptr < (section_data_ptr + section_length)); - - /* Points to contiguous block of Dwarf_Global's. */ - ret_globals = (Dwarf_Global *) - _dwarf_get_alloc(dbg, DW_DLA_LIST, global_count); - if (ret_globals == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - /* - Store pointers to Dwarf_Global_s structs in contiguous block, - and deallocate the chain. */ - curr_chain = head_chain; - for (i = 0; i < global_count; i++) { - *(ret_globals + i) = curr_chain->ch_item; - prev_chain = curr_chain; - curr_chain = curr_chain->ch_next; - dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN); - } - - *globals = ret_globals; - *return_count = (Dwarf_Signed) global_count; - return DW_DLV_OK; -} - - -/* - Given a pubnames entry (or other like section entry) - return thru the ret_name pointer - a pointer to the string which is the entry name. - -*/ -int -dwarf_globname(Dwarf_Global glob, char **ret_name, Dwarf_Error * error) -{ - if (glob == NULL) { - _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL); - return (DW_DLV_ERROR); - } - - *ret_name = (char *) (glob->gl_name); - return DW_DLV_OK; -} - - -/* - Given a pubnames entry (or other like section entry) - return thru the ret_off pointer the - global offset of the DIE for this entry. - The global offset is the offset within the .debug_info - section as a whole. -*/ -int -dwarf_global_die_offset(Dwarf_Global global, - Dwarf_Off * ret_off, Dwarf_Error * error) -{ - if (global == NULL) { - _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL); - return (DW_DLV_ERROR); - } - - if (global->gl_context == NULL) { - _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL); - return (DW_DLV_ERROR); - } - - *ret_off = (global->gl_named_die_offset_within_cu + - global->gl_context->pu_offset_of_cu_header); - return DW_DLV_OK; -} - -/* - Given a pubnames entry (or other like section entry) - return thru the ret_off pointer the - offset of the compilation unit header of the - compilation unit the global is part of. - - In early versions of this, the value returned was - the offset of the compilation unit die, and - other cu-local die offsets were faked so adding this to - such a cu-local offset got a true section offset. - Now things do as they say (adding *cu_header_offset to - a cu-local offset gets the section offset). - -*/ -int -dwarf_global_cu_offset(Dwarf_Global global, - Dwarf_Off * cu_header_offset, - Dwarf_Error * error) -{ - Dwarf_Global_Context con = 0; - - if (global == NULL) { - _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL); - return (DW_DLV_ERROR); - } - - con = global->gl_context; - - if (con == NULL) { - _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL); - return (DW_DLV_ERROR); - } - - /* In early libdwarf, this incorrectly returned the offset of the - CU DIE. Now correctly returns the header offset. */ - *cu_header_offset = con->pu_offset_of_cu_header; - - return DW_DLV_OK; -} - -/* - Give back the pubnames entry (or any other like section) - name, symbol DIE offset, and the cu-DIE offset. - - Various errors are possible. - - The string pointer returned thru ret_name is not - dwarf_get_alloc()ed, so no dwarf_dealloc() - DW_DLA_STRING should be applied to it. - -*/ -int -dwarf_global_name_offsets(Dwarf_Global global, - char **ret_name, - Dwarf_Off * die_offset, - Dwarf_Off * cu_die_offset, - Dwarf_Error * error) -{ - Dwarf_Global_Context con = 0; - Dwarf_Debug dbg = 0; - Dwarf_Off off = 0; - - if (global == NULL) { - _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL); - return (DW_DLV_ERROR); - } - - con = global->gl_context; - - if (con == NULL) { - _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL); - return (DW_DLV_ERROR); - } - - off = con->pu_offset_of_cu_header; - /* The offset had better not be too close to the end. If it is, - _dwarf_length_of_cu_header() will step off the end and therefore - must not be used. 10 is a meaningless heuristic, but no CU - header is that small so it is safe. An erroneous offset is due - to a bug in the tool chain. A bug like this has been seen on - IRIX with MIPSpro 7.3.1.3 and an executable > 2GB in size and - with 2 million pubnames entries. */ -#define MIN_CU_HDR_SIZE 10 - dbg = con->pu_dbg; - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - if (dbg->de_debug_info.dss_size && - ((off + MIN_CU_HDR_SIZE) >= dbg->de_debug_info.dss_size)) { - _dwarf_error(NULL, error, DW_DLE_OFFSET_BAD); - return (DW_DLV_ERROR); - } -#undef MIN_CU_HDR_SIZE - if (die_offset != NULL) { - *die_offset = global->gl_named_die_offset_within_cu + off; - } - - *ret_name = (char *) global->gl_name; - - if (cu_die_offset != NULL) { - int res = _dwarf_load_debug_info(dbg, error); - - if (res != DW_DLV_OK) { - return res; - } - /* The offset had better not be too close to the end. If it is, - _dwarf_length_of_cu_header() will step off the end and - therefore must not be used. 10 is a meaningless heuristic, - but no CU header is that small so it is safe. */ - if ((off + 10) >= dbg->de_debug_info.dss_size) { - _dwarf_error(NULL, error, DW_DLE_OFFSET_BAD); - return (DW_DLV_ERROR); - } - *cu_die_offset = off + _dwarf_length_of_cu_header(dbg, off); - } - - - return DW_DLV_OK; -} - -/* - We have the offset to a CU header. - Return thru outFileOffset the offset of the CU DIE. - - New June, 2001. - Used by SGI debuggers. - No error is possible. - - See also dwarf_CU_dieoffset_given_die(). -*/ - -/* ARGSUSED */ -int -dwarf_get_cu_die_offset_given_cu_header_offset(Dwarf_Debug dbg, - Dwarf_Off in_cu_header_offset, - Dwarf_Off * out_cu_die_offset, - Dwarf_Error * err) -{ - Dwarf_Off len = - _dwarf_length_of_cu_header(dbg, in_cu_header_offset); - - Dwarf_Off newoff = in_cu_header_offset + len; - - *out_cu_die_offset = newoff; - return DW_DLV_OK; -} -/* dwarf_CU_dieoffset_given_die returns - the global debug_info section offset of the CU die - that is the CU containing the given (passed-in) die. - This information makes it possible for a consumer to - find and print context information for any die. - - Use dwarf_offdie() passing in the offset this returns - to get a die pointer to the CU die. - */ -int -dwarf_CU_dieoffset_given_die(Dwarf_Die die, - Dwarf_Off* return_offset, - Dwarf_Error* error) -{ - Dwarf_Off dieoff = 0; - Dwarf_CU_Context cucontext = 0; - - CHECK_DIE(die, DW_DLV_ERROR); - cucontext = die->di_cu_context; - dieoff = cucontext->cc_debug_info_offset; - /* The following call cannot fail, so no error check. */ - dwarf_get_cu_die_offset_given_cu_header_offset( - cucontext->cc_dbg, dieoff, return_offset,error); - return DW_DLV_OK; -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_global.h b/usr/src/tools/ctf/dwarf/common/dwarf_global.h deleted file mode 100644 index c2bc2cdcc3..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_global.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - - Copyright (C) 2000,2004,2005 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - - -typedef struct Dwarf_Global_Context_s *Dwarf_Global_Context; - -/* - This struct contains header information for a set of pubnames. - Essentially, they contain the context for a set of pubnames - belonging to a compilation-unit. - - This is also used for the sgi-specific - weaknames, typenames, varnames, funcnames data: - the structs for those are incomplete and - instances of this are used instead. - - Also used for DWARF3 .debug_pubtypes. - -*/ -struct Dwarf_Global_Context_s { - - /* Length in .debug_pubnames (etc) of a set of names for a - compilation-unit. Dwarf_Word pu_length; The value is not made - available outside libdwarf and not used inside, so no need to - record it. */ - - /* For this context, size of a length. 4 or 8 */ - unsigned char pu_length_size; - - /* For this CU, size of the extension 0 except for dwarf2 extension - 64bit, in which case is 4. */ - unsigned char pu_extension_size; - - /* - Offset into .debug_info of the compilation-unit header (not DIE) - for this set of pubnames. */ - Dwarf_Off pu_offset_of_cu_header; - - /* Size of compilation-unit that these pubnames are in. */ - Dwarf_Unsigned pu_info_length; - - Dwarf_Debug pu_dbg; -}; - - -/* This struct contains information for a single pubname. */ -struct Dwarf_Global_s { - - /* - Offset from the start of the corresponding compilation-unit of - the DIE for the given pubname CU. */ - Dwarf_Off gl_named_die_offset_within_cu; - - /* Points to the given pubname. */ - Dwarf_Small *gl_name; - - /* Context for this pubname. */ - Dwarf_Global_Context gl_context; -}; - -int _dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg, - Dwarf_Small * - section_data_ptr, - Dwarf_Unsigned - section_length, - Dwarf_Global ** globals, - Dwarf_Signed * return_count, - Dwarf_Error * error, - int context_code, - int global_code, - int length_err_num, - int version_err_num); - -void -_dwarf_internal_globals_dealloc( Dwarf_Debug dbg, Dwarf_Global *dwgl, - Dwarf_Signed count, - int context_code, - int global_code, - int list_code); - - -#ifdef __sgi /* __sgi should only be defined for IRIX/MIPS. */ -void _dwarf_fix_up_offset_irix(Dwarf_Debug dbg, - Dwarf_Unsigned *varp, - char *caller_site_name); -#define FIX_UP_OFFSET_IRIX_BUG(ldbg,var,name) _dwarf_fix_up_offset_irix(ldbg,&var,name) -#else -#define FIX_UP_OFFSET_IRIX_BUG(ldbg,var,name) -#endif - diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_harmless.c b/usr/src/tools/ctf/dwarf/common/dwarf_harmless.c deleted file mode 100644 index 16dbe4bc97..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_harmless.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - - Copyright (C) 2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - -*/ - -/* - This implements _dwarf_insert_harmless_error - and related helper functions for recording - compiler errors that need not make the input - unusable. - - Applications can use dwarf_get_harmless_error_list to - find (and possibly print) a warning about such errors. - - The initial error reported here is - DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE which was a - bug in a specific compiler. - - It is a fixed length circular list to constrain - the space used for errors. - - The assumption is that these errors are exceedingly - rare, and indicate a broken compiler (the one that - produced the object getting the error(s)). - - dh_maxcount is recorded internally as 1 greater than - requested. Hiding the fact we always leave one - slot unused (at least). So a user request for - N slots really gives the user N usable slots. -*/ - - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include -#include "dwarf_frame.h" -#include "dwarf_harmless.h" - - -/* The pointers returned here through errmsg_ptrs_array - become invalidated by any call to libdwarf. Any call. -*/ -int dwarf_get_harmless_error_list(Dwarf_Debug dbg, - unsigned count, - const char ** errmsg_ptrs_array, - unsigned * errs_count) -{ - struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors; - if(!dhp->dh_errors) { - dhp->dh_errs_count = 0; - return DW_DLV_NO_ENTRY; - } - if(dhp->dh_errs_count == 0) { - return DW_DLV_NO_ENTRY; - } - if(errs_count) { - *errs_count = dhp->dh_errs_count; - } - if(count) { - /* NULL terminate the array of pointers */ - --count; - errmsg_ptrs_array[count] = 0; - - if(dhp->dh_next_to_use != dhp->dh_first) { - unsigned i = 0; - unsigned cur = dhp->dh_first; - for(i = 0; cur != dhp->dh_next_to_use; ++i) { - if(i >= count ) { - /* All output spaces are used. */ - break; - } - errmsg_ptrs_array[i] = dhp->dh_errors[cur]; - cur = (cur +1) % dhp->dh_maxcount; - } - errmsg_ptrs_array[i] = 0; - } - } - dhp->dh_next_to_use = 0; - dhp->dh_first = 0; - dhp->dh_errs_count = 0; - return DW_DLV_OK; -} - -/* strncpy does not null-terminate, this does it. */ -static void -safe_strncpy(char *targ, char *src, unsigned spaceavail) -{ - unsigned goodcount = spaceavail-1; - if(spaceavail < 1) { - return; /* impossible */ - } - strncpy(targ,src,goodcount); - targ[goodcount] = 0; -} - -/* Insertion made public is only for testing the harmless error code, - it is not necessarily useful for libdwarf client code aside - from code testing libdwarf. */ -void dwarf_insert_harmless_error(Dwarf_Debug dbg, - char *newerror) -{ - struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors; - unsigned next = 0; - unsigned cur = dhp->dh_next_to_use; - char *msgspace; - if(!dhp->dh_errors) { - dhp->dh_errs_count++; - return; - } - msgspace = dhp->dh_errors[cur]; - safe_strncpy(msgspace, newerror,DW_HARMLESS_ERROR_MSG_STRING_SIZE); - next = (cur+1) % dhp->dh_maxcount; - dhp->dh_errs_count++; - dhp->dh_next_to_use = next; - if (dhp->dh_next_to_use == dhp->dh_first) { - /* Array is full set full invariant. */ - dhp->dh_first = (dhp->dh_first+1) % dhp->dh_maxcount; - } -} - -/* The size of the circular list of strings may be set - and reset as desired. Returns the previous size of - the list. If the list is shortened excess error entries - are simply dropped. - If the reallocation fails the list size is left unchanged. - Do not make this a long list! - - Remember the maxcount we record is 1 > the user count, - so we adjust it so it looks like the user count. -*/ -unsigned dwarf_set_harmless_error_list_size(Dwarf_Debug dbg, - unsigned maxcount ) -{ - struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors; - unsigned prevcount = dhp->dh_maxcount; - if(maxcount != 0) { - ++maxcount; - if(maxcount != dhp->dh_maxcount) { - /* Assign transfers 'ownership' of the malloc areas - to oldarray. */ - struct Dwarf_Harmless_s oldarray = *dhp; - /* Do not double increment the max, the init() func - increments it too. */ - dwarf_harmless_init(dhp,maxcount-1); - if(oldarray.dh_next_to_use != oldarray.dh_first) { - unsigned i = 0; - for(i = oldarray.dh_first; i != oldarray.dh_next_to_use; - i = (i+1)%oldarray.dh_maxcount) { - dwarf_insert_harmless_error(dbg,oldarray.dh_errors[i]); - } - if( oldarray.dh_errs_count > dhp->dh_errs_count) { - dhp->dh_errs_count = oldarray.dh_errs_count; - } - } - dwarf_harmless_cleanout(&oldarray); - } - } - return prevcount-1; -} - -void -dwarf_harmless_init(struct Dwarf_Harmless_s *dhp,unsigned size) -{ - unsigned i = 0; - memset(dhp,0,sizeof(*dhp)); - dhp->dh_maxcount = size +1; - dhp->dh_errors = (char **)malloc(sizeof( char *) *dhp->dh_maxcount); - if (!dhp->dh_errors) { - dhp->dh_maxcount = 0; - return; - } - - for(i = 0; i < dhp->dh_maxcount; ++i) { - char *newstr = - (char *)malloc(DW_HARMLESS_ERROR_MSG_STRING_SIZE); - dhp->dh_errors[i] = newstr; - if(!newstr) { - dhp->dh_maxcount = 0; - /* Let it leak, the leak is a constrained amount. */ - dhp->dh_errors = 0; - return; - } - /* We make the string content well-defined by an initial - NUL byte, but this is not really necessary. */ - newstr[0] = 0; - } -} - -void -dwarf_harmless_cleanout(struct Dwarf_Harmless_s *dhp) -{ - unsigned i = 0; - if(!dhp->dh_errors) { - return; - } - for(i = 0; i < dhp->dh_maxcount; ++i) { - free(dhp->dh_errors[i]); - } - free(dhp->dh_errors); - dhp->dh_errors = 0; - dhp->dh_maxcount = 0; -} - diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_harmless.h b/usr/src/tools/ctf/dwarf/common/dwarf_harmless.h deleted file mode 100644 index 3d4d910ce9..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_harmless.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - - Copyright (C) 2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - -*/ - - - -void dwarf_harmless_init(struct Dwarf_Harmless_s *dhp,unsigned size); -void dwarf_harmless_cleanout(struct Dwarf_Harmless_s *dhp); - diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_incl.h b/usr/src/tools/ctf/dwarf/common/dwarf_incl.h deleted file mode 100644 index df2fbf334c..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_incl.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - - Copyright (C) 2000, 2002, 2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2008-2010 David Anderson. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#ifndef DWARF_INCL_H -#define DWARF_INCL_H -#if (!defined(HAVE_RAW_LIBELF_OK) && defined(HAVE_LIBELF_OFF64_OK) ) -/* At a certain point libelf.h requires _GNU_SOURCE. - here we assume the criteria in configure determine that - usefully. -*/ -#define _GNU_SOURCE 1 -#endif - - -#include "libdwarfdefs.h" -#include - -#ifdef HAVE_ELF_H -#include -#endif - -#include -#include -#include - -#include "dwarf_base_types.h" -#include "dwarf_alloc.h" -#include "dwarf_opaque.h" -#include "dwarf_error.h" -#include "dwarf_util.h" -#endif /* DWARF_INCL_H */ diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_init_finish.c b/usr/src/tools/ctf/dwarf/common/dwarf_init_finish.c deleted file mode 100644 index 1ab9d5fd38..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_init_finish.c +++ /dev/null @@ -1,577 +0,0 @@ -/* - - Copyright (C) 2000,2002,2003,2004,2005 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2008-2010 Arxan Technologies, Inc. All Rights Reserved. - Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - -#include "config.h" -#include "dwarf_incl.h" - -#include -#include -#include -#include -#include - -#include "dwarf_incl.h" -#include "malloc_check.h" - -#define DWARF_DBG_ERROR(dbg,errval,retval) \ - _dwarf_error(dbg, error, errval); return(retval); - -#define FALSE 0 -#define TRUE 1 - - - -/* This static is copied to the dbg on dbg init - so that the static need not be referenced at - run time, preserving better locality of - reference. - Value is 0 means do the string check. - Value non-zero means do not do the check. -*/ -static Dwarf_Small _dwarf_assume_string_bad; -static Dwarf_Small _dwarf_apply_relocs = 1; - -/* Call this after calling dwarf_init but before doing anything else. - * It applies to all objects, not just the current object. - */ -int -dwarf_set_reloc_application(int apply) -{ - int oldval = _dwarf_apply_relocs; - _dwarf_apply_relocs = apply; - return oldval; -} - -int -dwarf_set_stringcheck(int newval) -{ - int oldval = _dwarf_assume_string_bad; - - _dwarf_assume_string_bad = newval; - return oldval; -} - -/* Unifies the basic duplicate/empty testing and section - * data setting to one place. */ -static int -get_basic_section_data(Dwarf_Debug dbg, - struct Dwarf_Section_s *secdata, - struct Dwarf_Obj_Access_Section_s *doas, - Dwarf_Half section_index, - Dwarf_Error* error, - int duperr, int emptyerr ) -{ - if (secdata->dss_index != 0) { - DWARF_DBG_ERROR(dbg, duperr, DW_DLV_ERROR); - } - if (doas->size == 0) { - if (emptyerr == 0 ) { - /* Allow empty section. */ - return DW_DLV_OK; - } - /* Know no reason to allow section */ - DWARF_DBG_ERROR(dbg, emptyerr, DW_DLV_ERROR); - } - secdata->dss_index = section_index; - secdata->dss_size = doas->size; - secdata->dss_addr = doas->addr; - secdata->dss_link = doas->link; - return DW_DLV_OK; -} - - -static void -add_rela_data( struct Dwarf_Section_s *secdata, - struct Dwarf_Obj_Access_Section_s *doas, - Dwarf_Half section_index) -{ - secdata->dss_reloc_index = section_index; - secdata->dss_reloc_size = doas->size; - secdata->dss_reloc_addr = doas->addr; - secdata->dss_reloc_symtab = doas->link; - secdata->dss_reloc_link = doas->link; -} - -/* - Given an Elf ptr, set up dbg with pointers - to all the Dwarf data sections. - Return NULL on error. - - This function is also responsible for determining - whether the given object contains Dwarf information - or not. The test currently used is that it contains - either a .debug_info or a .debug_frame section. If - not, it returns DW_DLV_NO_ENTRY causing dwarf_init() also to - return DW_DLV_NO_ENTRY. Earlier, we had thought of using only - the presence/absence of .debug_info to test, but we - added .debug_frame since there could be stripped objects - that have only a .debug_frame section for exception - processing. - DW_DLV_NO_ENTRY or DW_DLV_OK or DW_DLV_ERROR -*/ -static int -_dwarf_setup(Dwarf_Debug dbg, Dwarf_Error * error) -{ - const char *scn_name = 0; - int foundDwarf = 0; - struct Dwarf_Obj_Access_Interface_s * obj = 0; - - Dwarf_Endianness endianness; - - Dwarf_Unsigned section_size = 0; - Dwarf_Unsigned section_count = 0; - Dwarf_Half section_index = 0; - Dwarf_Addr section_addr = 0; - - foundDwarf = FALSE; - - dbg->de_assume_string_in_bounds = _dwarf_assume_string_bad; - - dbg->de_same_endian = 1; - dbg->de_copy_word = memcpy; - obj = dbg->de_obj_file; - endianness = obj->methods->get_byte_order(obj->object); -#ifdef WORDS_BIGENDIAN - dbg->de_big_endian_object = 1; - if (endianness == DW_OBJECT_LSB ) { - dbg->de_same_endian = 0; - dbg->de_big_endian_object = 0; - dbg->de_copy_word = _dwarf_memcpy_swap_bytes; - } -#else /* little endian */ - dbg->de_big_endian_object = 0; - if (endianness == DW_OBJECT_MSB ) { - dbg->de_same_endian = 0; - dbg->de_big_endian_object = 1; - dbg->de_copy_word = _dwarf_memcpy_swap_bytes; - } -#endif /* !WORDS_BIGENDIAN */ - - - /* The following de_length_size is Not Too Significant. Only used - one calculation, and an approximate one at that. */ - dbg->de_length_size = obj->methods->get_length_size(obj->object); - dbg->de_pointer_size = obj->methods->get_pointer_size(obj->object); - - section_count = obj->methods->get_section_count(obj->object); - - /* We can skip index 0 when considering ELF files, but not other - object types. */ - for (section_index = 0; section_index < section_count; - ++section_index) { - - struct Dwarf_Obj_Access_Section_s doas; - int res = DW_DLV_ERROR; - int err; - - res = obj->methods->get_section_info(obj->object, - section_index, - &doas, &err); - if(res == DW_DLV_ERROR){ - DWARF_DBG_ERROR(dbg, err, DW_DLV_ERROR); - } - - section_addr = doas.addr; - section_size = doas.size; - scn_name = doas.name; - - if (strncmp(scn_name, ".debug_", 7) - && strcmp(scn_name, ".eh_frame") - && strcmp(scn_name, ".symtab") - && strcmp(scn_name, ".strtab") - && strncmp(scn_name, ".rela.",6)) { - continue; - } - else if (strcmp(scn_name, ".debug_info") == 0) { - res = get_basic_section_data(dbg,&dbg->de_debug_info, &doas, - section_index,error, - DW_DLE_DEBUG_INFO_DUPLICATE,DW_DLE_DEBUG_INFO_NULL); - if(res != DW_DLV_OK) { - return res; - } - foundDwarf = TRUE; - } - else if (strcmp(scn_name, ".debug_abbrev") == 0) { - res = get_basic_section_data(dbg,&dbg->de_debug_abbrev, &doas, - section_index,error, - DW_DLE_DEBUG_ABBREV_DUPLICATE,DW_DLE_DEBUG_ABBREV_NULL); - if(res != DW_DLV_OK) { - return res; - } - } - else if (strcmp(scn_name, ".debug_aranges") == 0) { - res = get_basic_section_data(dbg,&dbg->de_debug_aranges, &doas, - section_index,error, - DW_DLE_DEBUG_ARANGES_DUPLICATE,0); - if(res != DW_DLV_OK) { - return res; - } - } - - else if (strcmp(scn_name, ".debug_line") == 0) { - res = get_basic_section_data(dbg,&dbg->de_debug_line, &doas, - section_index,error, - DW_DLE_DEBUG_LINE_DUPLICATE,0); - if(res != DW_DLV_OK) { - return res; - } - } - else if (strcmp(scn_name, ".debug_frame") == 0) { - res = get_basic_section_data(dbg,&dbg->de_debug_frame, &doas, - section_index,error, - DW_DLE_DEBUG_FRAME_DUPLICATE,0); - if(res != DW_DLV_OK) { - return res; - } - foundDwarf = TRUE; - } else if (strcmp(scn_name, ".eh_frame") == 0) { - /* gnu egcs-1.1.2 data */ - res = get_basic_section_data(dbg,&dbg->de_debug_frame_eh_gnu, &doas, - section_index,error, - DW_DLE_DEBUG_FRAME_DUPLICATE,0); - if(res != DW_DLV_OK) { - return res; - } - foundDwarf = TRUE; - } - else if (strcmp(scn_name, ".debug_loc") == 0) { - res = get_basic_section_data(dbg,&dbg->de_debug_loc, &doas, - section_index,error, - DW_DLE_DEBUG_LOC_DUPLICATE,0); - if(res != DW_DLV_OK) { - return res; - } - } - else if (strcmp(scn_name, ".debug_pubnames") == 0) { - res = get_basic_section_data(dbg,&dbg->de_debug_pubnames, &doas, - section_index,error, - DW_DLE_DEBUG_PUBNAMES_DUPLICATE,0); - if(res != DW_DLV_OK) { - return res; - } - } - - else if (strcmp(scn_name, ".debug_str") == 0) { - res = get_basic_section_data(dbg,&dbg->de_debug_str, &doas, - section_index,error, - DW_DLE_DEBUG_STR_DUPLICATE,0); - if(res != DW_DLV_OK) { - return res; - } - } - else if (strcmp(scn_name, ".debug_funcnames") == 0) { - /* SGI IRIX-only. */ - res = get_basic_section_data(dbg,&dbg->de_debug_funcnames, &doas, - section_index,error, - DW_DLE_DEBUG_FUNCNAMES_DUPLICATE,0); - if(res != DW_DLV_OK) { - return res; - } - } - else if (strcmp(scn_name, ".debug_typenames") == 0) { - /* SGI IRIX-only, created years before DWARF3. Content - essentially identical to .debug_pubtypes. */ - res = get_basic_section_data(dbg,&dbg->de_debug_typenames, &doas, - section_index,error, - DW_DLE_DEBUG_TYPENAMES_DUPLICATE,0); - if(res != DW_DLV_OK) { - return res; - } - } else if (strcmp(scn_name, ".debug_pubtypes") == 0) { - /* Section new in DWARF3. */ - res = get_basic_section_data(dbg,&dbg->de_debug_pubtypes, &doas, - section_index,error, - DW_DLE_DEBUG_PUBTYPES_DUPLICATE,0); - if(res != DW_DLV_OK) { - return res; - } - } - else if (strcmp(scn_name, ".debug_varnames") == 0) { - /* SGI IRIX-only. */ - res = get_basic_section_data(dbg,&dbg->de_debug_varnames, &doas, - section_index,error, - DW_DLE_DEBUG_VARNAMES_DUPLICATE,0); - if(res != DW_DLV_OK) { - return res; - } - } - else if (strcmp(scn_name, ".debug_weaknames") == 0) { - /* SGI IRIX-only. */ - res = get_basic_section_data(dbg,&dbg->de_debug_weaknames, &doas, - section_index,error, - DW_DLE_DEBUG_WEAKNAMES_DUPLICATE,0); - if(res != DW_DLV_OK) { - return res; - } - } else if (strcmp(scn_name, ".debug_macinfo") == 0) { - res = get_basic_section_data(dbg,&dbg->de_debug_macinfo, &doas, - section_index,error, - DW_DLE_DEBUG_MACINFO_DUPLICATE,0); - if(res != DW_DLV_OK) { - return res; - } - } - else if (strcmp(scn_name, ".debug_ranges") == 0) { - res = get_basic_section_data(dbg,&dbg->de_debug_ranges, &doas, - section_index,error, - DW_DLE_DEBUG_RANGES_DUPLICATE,0); - if(res != DW_DLV_OK) { - return res; - } - foundDwarf = TRUE; - } - else if (strcmp(scn_name, ".symtab") == 0) { - res = get_basic_section_data(dbg,&dbg->de_elf_symtab, &doas, - section_index,error, - DW_DLE_DEBUG_SYMTAB_ERR,0); - if(res != DW_DLV_OK) { - return res; - } - } - else if (strcmp(scn_name, ".strtab") == 0) { - res = get_basic_section_data(dbg,&dbg->de_elf_strtab, &doas, - section_index,error, - DW_DLE_DEBUG_STRTAB_ERR,0); - if(res != DW_DLV_OK) { - return res; - } - } - else if (strncmp(scn_name, ".rela.debug_",12) == 0) { - const char *rcn_name = scn_name + 5; - if (strcmp(rcn_name, ".debug_info") == 0) { - add_rela_data(&dbg->de_debug_info,&doas,section_index); - } else if (strcmp(rcn_name, ".debug_abbrev") == 0) { - add_rela_data(&dbg->de_debug_abbrev,&doas,section_index); - } else if (strcmp(rcn_name, ".debug_aranges") == 0) { - add_rela_data(&dbg->de_debug_aranges,&doas,section_index); - } else if (strcmp(rcn_name, ".debug_line") == 0) { - add_rela_data(&dbg->de_debug_line,&doas,section_index); - } else if (strcmp(rcn_name, ".debug_frame") == 0) { - add_rela_data(&dbg->de_debug_frame,&doas,section_index); - } else if (strcmp(rcn_name, ".eh_frame") == 0) { - add_rela_data(&dbg->de_debug_frame_eh_gnu,&doas,section_index); - } else if (strcmp(rcn_name, ".debug_loc") == 0) { - add_rela_data(&dbg->de_debug_loc,&doas,section_index); - } else if (strcmp(rcn_name, ".debug_pubnames") == 0) { - add_rela_data(&dbg->de_debug_pubnames,&doas,section_index); - } else if (strcmp(rcn_name, ".debug_str") == 0) { - add_rela_data(&dbg->de_debug_str,&doas,section_index); - } else if (strcmp(rcn_name, ".debug_funcnames") == 0) { - add_rela_data(&dbg->de_debug_funcnames,&doas,section_index); - } else if (strcmp(rcn_name, ".debug_typenames") == 0) { - add_rela_data(&dbg->de_debug_typenames,&doas,section_index); - } else if (strcmp(rcn_name, ".debug_pubtypes") == 0) { - add_rela_data(&dbg->de_debug_pubtypes,&doas,section_index); - } else if (strcmp(rcn_name, ".debug_varnames") == 0) { - add_rela_data(&dbg->de_debug_varnames,&doas,section_index); - } else if (strcmp(rcn_name, ".debug_weaknames") == 0) { - add_rela_data(&dbg->de_debug_weaknames,&doas,section_index); - } else if (strcmp(rcn_name, ".debug_macinfo") == 0) { - add_rela_data(&dbg->de_debug_macinfo,&doas,section_index); - } - } - } - if (foundDwarf) { - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} - - -/* - Use a Dwarf_Obj_Access_Interface to kick things off. All other - init routines eventually use this one. - The returned Dwarf_Debug contains a copy of *obj - the callers copy of *obj may be freed whenever the caller - wishes. -*/ -int -dwarf_object_init(Dwarf_Obj_Access_Interface* obj, Dwarf_Handler errhand, - Dwarf_Ptr errarg, Dwarf_Debug* ret_dbg, - Dwarf_Error* error) -{ - Dwarf_Debug dbg = 0; - int setup_result = DW_DLV_OK; - - dbg = _dwarf_get_debug(); - if (dbg == NULL) { - DWARF_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, DW_DLV_ERROR); - } - dbg->de_errhand = errhand; - dbg->de_errarg = errarg; - dbg->de_frame_rule_initial_value = DW_FRAME_REG_INITIAL_VALUE; - dbg->de_frame_reg_rules_entry_count = DW_FRAME_LAST_REG_NUM; -#ifdef HAVE_OLD_FRAME_CFA_COL - /* DW_FRAME_CFA_COL is really only suitable for old libdwarf frame - interfaces and its value of 0 there is only usable where - (as in MIPS) register 0 has no value other than 0 so - we can use the frame table column 0 for the CFA value - (and rely on client software to know when 'register 0' - is the cfa and when to just use a value 0 for register 0). - */ - dbg->de_frame_cfa_col_number = DW_FRAME_CFA_COL; -#else - dbg->de_frame_cfa_col_number = DW_FRAME_CFA_COL3; -#endif - dbg->de_frame_same_value_number = DW_FRAME_SAME_VAL; - dbg->de_frame_undefined_value_number = DW_FRAME_UNDEFINED_VAL; - - dbg->de_obj_file = obj; - - setup_result = _dwarf_setup(dbg, error); - if (setup_result != DW_DLV_OK) { - /* The status we want to return here is of _dwarf_setup, - not of the _dwarf_free_all_of_one_debug(dbg) call. - So use a local status variable for the free. */ - int freeresult = _dwarf_free_all_of_one_debug(dbg); - if (freeresult == DW_DLV_ERROR) { - DWARF_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, DW_DLV_ERROR); - } - dwarf_malloc_check_complete("After Final free"); - return setup_result; - } - - dwarf_harmless_init(&dbg->de_harmless_errors, - DW_HARMLESS_ERROR_CIRCULAR_LIST_DEFAULT_SIZE); - - /* This call cannot fail: allocates nothing, releases nothing */ - _dwarf_setup_debug(dbg); - - - *ret_dbg = dbg; - return DW_DLV_OK; -} - - -/* - A finish routine that is completely unaware of ELF. - - Frees all memory that was not previously freed by - dwarf_dealloc. - Aside frmo certain categories. - */ -int -dwarf_object_finish(Dwarf_Debug dbg, Dwarf_Error * error) -{ - int res = DW_DLV_OK; - - res = _dwarf_free_all_of_one_debug(dbg); - if (res == DW_DLV_ERROR) { - DWARF_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, DW_DLV_ERROR); - } - dwarf_malloc_check_complete("After Final free"); - - return res; -} - - -/* - Load the ELF section with the specified index and set the - pointer pointed to by section_data to the memory where it - was loaded. - */ -int -_dwarf_load_section(Dwarf_Debug dbg, - struct Dwarf_Section_s *section, - Dwarf_Error * error) -{ - int res = DW_DLV_ERROR; - int err = 0; - struct Dwarf_Obj_Access_Interface_s *o = 0; - - /* check to see if the section is already loaded */ - if (section->dss_data != NULL) { - return DW_DLV_OK; - } - o = dbg->de_obj_file; - res = o->methods->load_section( - o->object, section->dss_index, - §ion->dss_data, &err); - if(res == DW_DLV_ERROR){ - DWARF_DBG_ERROR(dbg, err, DW_DLV_ERROR); - } - if(_dwarf_apply_relocs == 0) { - return res; - } - if(section->dss_reloc_size == 0) { - return res; - } - if(!o->methods->relocate_a_section) { - return res; - } - /*apply relocations */ - res = o->methods->relocate_a_section( o->object, section->dss_index, - dbg, &err); - if(res == DW_DLV_ERROR) { - DWARF_DBG_ERROR(dbg, err, DW_DLV_ERROR); - } - return res; -} - -/* This is a hack so clients can verify offsets. - Added April 2005 so that debugger can detect broken offsets - (which happened in an IRIX -64 executable larger than 2GB - using MIPSpro 7.3.1.3 compilers. A couple .debug_pubnames - offsets were wrong.). -*/ -int -dwarf_get_section_max_offsets(Dwarf_Debug dbg, - Dwarf_Unsigned * debug_info_size, - Dwarf_Unsigned * debug_abbrev_size, - Dwarf_Unsigned * debug_line_size, - Dwarf_Unsigned * debug_loc_size, - Dwarf_Unsigned * debug_aranges_size, - Dwarf_Unsigned * debug_macinfo_size, - Dwarf_Unsigned * debug_pubnames_size, - Dwarf_Unsigned * debug_str_size, - Dwarf_Unsigned * debug_frame_size, - Dwarf_Unsigned * debug_ranges_size, - Dwarf_Unsigned * debug_typenames_size) -{ - *debug_info_size = dbg->de_debug_info.dss_size; - *debug_abbrev_size = dbg->de_debug_abbrev.dss_size; - *debug_line_size = dbg->de_debug_line.dss_size; - *debug_loc_size = dbg->de_debug_loc.dss_size; - *debug_aranges_size = dbg->de_debug_aranges.dss_size; - *debug_macinfo_size = dbg->de_debug_macinfo.dss_size; - *debug_pubnames_size = dbg->de_debug_pubnames.dss_size; - *debug_str_size = dbg->de_debug_str.dss_size; - *debug_frame_size = dbg->de_debug_frame.dss_size; - *debug_ranges_size = dbg->de_debug_ranges.dss_size; - *debug_typenames_size = dbg->de_debug_typenames.dss_size; - return DW_DLV_OK; -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_leb.c b/usr/src/tools/ctf/dwarf/common/dwarf_leb.c deleted file mode 100644 index b3b5d262f5..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_leb.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "dwarf_incl.h" -#include - - -/* - decode ULEB -*/ -Dwarf_Unsigned -_dwarf_decode_u_leb128(Dwarf_Small * leb128, Dwarf_Word * leb128_length) -{ - unsigned char byte; - Dwarf_Word word_number; - Dwarf_Unsigned number; - Dwarf_Sword shift; - Dwarf_Sword byte_length; - - /* The following unrolls-the-loop for the first few bytes and - unpacks into 32 bits to make this as fast as possible. - word_number is assumed big enough that the shift has a defined - result. */ - if ((*leb128 & 0x80) == 0) { - if (leb128_length != NULL) - *leb128_length = 1; - return (*leb128); - } else if ((*(leb128 + 1) & 0x80) == 0) { - if (leb128_length != NULL) - *leb128_length = 2; - - word_number = *leb128 & 0x7f; - word_number |= (*(leb128 + 1) & 0x7f) << 7; - return (word_number); - } else if ((*(leb128 + 2) & 0x80) == 0) { - if (leb128_length != NULL) - *leb128_length = 3; - - word_number = *leb128 & 0x7f; - word_number |= (*(leb128 + 1) & 0x7f) << 7; - word_number |= (*(leb128 + 2) & 0x7f) << 14; - return (word_number); - } else if ((*(leb128 + 3) & 0x80) == 0) { - if (leb128_length != NULL) - *leb128_length = 4; - - word_number = *leb128 & 0x7f; - word_number |= (*(leb128 + 1) & 0x7f) << 7; - word_number |= (*(leb128 + 2) & 0x7f) << 14; - word_number |= (*(leb128 + 3) & 0x7f) << 21; - return (word_number); - } - - /* The rest handles long numbers Because the 'number' may be larger - than the default int/unsigned, we must cast the 'byte' before - the shift for the shift to have a defined result. */ - number = 0; - shift = 0; - byte_length = 1; - byte = *(leb128); - for (;;) { - number |= ((Dwarf_Unsigned) (byte & 0x7f)) << shift; - - if ((byte & 0x80) == 0) { - if (leb128_length != NULL) - *leb128_length = byte_length; - return (number); - } - shift += 7; - - byte_length++; - ++leb128; - byte = *leb128; - } -} - -#define BITSINBYTE 8 - -/* - decode SLEB -*/ -Dwarf_Signed -_dwarf_decode_s_leb128(Dwarf_Small * leb128, Dwarf_Word * leb128_length) -{ - Dwarf_Signed number = 0; - Dwarf_Bool sign = 0; - Dwarf_Sword shift = 0; - unsigned char byte = *leb128; - Dwarf_Sword byte_length = 1; - - /* byte_length being the number of bytes of data absorbed so far in - turning the leb into a Dwarf_Signed. */ - - for (;;) { - sign = byte & 0x40; - number |= ((Dwarf_Signed) ((byte & 0x7f))) << shift; - shift += 7; - - if ((byte & 0x80) == 0) { - break; - } - ++leb128; - byte = *leb128; - byte_length++; - } - - if ((shift < sizeof(Dwarf_Signed) * BITSINBYTE) && sign) { - number |= -((Dwarf_Signed) 1 << shift); - } - - if (leb128_length != NULL) - *leb128_length = byte_length; - return (number); -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_line.c b/usr/src/tools/ctf/dwarf/common/dwarf_line.c deleted file mode 100644 index e7e15e7c1a..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_line.c +++ /dev/null @@ -1,1951 +0,0 @@ -/* - Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the Crittenden Lane address. -*/ - - - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include -#include "dwarf_line.h" - -static int -is_path_separator(Dwarf_Small s) -{ - if(s == '/') { - return 1; - } -#ifdef HAVE_WINDOWS_PATH - if(s == '\\') { - return 1; - } -#endif - return 0; -} - -/* Return 0 if false, 1 if true. - If HAVE_WINDOWS_PATH is defined we - attempt to handle windows full paths: - \\something or C:cwdpath.c -*/ -static int -file_name_is_full_path(Dwarf_Small *fname) -{ - Dwarf_Small firstc = *fname; - if(is_path_separator(firstc)) { - /* Full path. */ - return 1; - } - if(!firstc) { - return 0; - } -#ifdef HAVE_WINDOWS_PATH - if((firstc >= 'A' && firstc <= 'Z') || - (firstc >= 'a' && firstc <= 'z')) { - Dwarf_Small secondc = fname[1]; - if (secondc == ':') { - return 1; - } - } -#endif - return 0; -} - -/* - Although source files is supposed to return the - source files in the compilation-unit, it does - not look for any in the statement program. In - other words, it ignores those defined using the - extended opcode DW_LNE_define_file. -*/ -int -dwarf_srcfiles(Dwarf_Die die, - char ***srcfiles, - Dwarf_Signed * srcfilecount, Dwarf_Error * error) -{ - /* This pointer is used to scan the portion of the .debug_line - section for the current cu. */ - Dwarf_Small *line_ptr; - - /* Pointer to a DW_AT_stmt_list attribute in case it exists in the - die. */ - Dwarf_Attribute stmt_list_attr; - - /* Pointer to DW_AT_comp_dir attribute in die. */ - Dwarf_Attribute comp_dir_attr; - - /* Pointer to name of compilation directory. */ - Dwarf_Small *comp_dir = 0; - - /* Offset into .debug_line specified by a DW_AT_stmt_list - attribute. */ - Dwarf_Unsigned line_offset = 0; - - /* This points to a block of char *'s, each of which points to a - file name. */ - char **ret_files = 0; - - /* The Dwarf_Debug this die belongs to. */ - Dwarf_Debug dbg = 0; - - /* Used to chain the file names. */ - Dwarf_Chain curr_chain = NULL; - Dwarf_Chain prev_chain = NULL; - Dwarf_Chain head_chain = NULL; - Dwarf_Half attrform = 0; - int resattr = DW_DLV_ERROR; - int lres = DW_DLV_ERROR; - struct Line_Table_Prefix_s line_prefix; - int i = 0; - int res = DW_DLV_ERROR; - - /* ***** BEGIN CODE ***** */ - /* Reset error. */ - if (error != NULL) - *error = NULL; - - CHECK_DIE(die, DW_DLV_ERROR); - dbg = die->di_cu_context->cc_dbg; - - resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error); - if (resattr != DW_DLV_OK) { - return resattr; - } - - if (dbg->de_debug_line.dss_index == 0) { - _dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_NULL); - return (DW_DLV_ERROR); - } - - res = _dwarf_load_section(dbg, &dbg->de_debug_line,error); - if (res != DW_DLV_OK) { - return res; - } - - lres = dwarf_whatform(stmt_list_attr,&attrform,error); - if (lres != DW_DLV_OK) { - return lres; - } - if (attrform != DW_FORM_data4 && attrform != DW_FORM_data8 && - attrform != DW_FORM_sec_offset ) { - _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); - return (DW_DLV_ERROR); - } - lres = dwarf_global_formref(stmt_list_attr, &line_offset, error); - if (lres != DW_DLV_OK) { - return lres; - } - if (line_offset >= dbg->de_debug_line.dss_size) { - _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); - return (DW_DLV_ERROR); - } - line_ptr = dbg->de_debug_line.dss_data + line_offset; - dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR); - - /* - If die has DW_AT_comp_dir attribute, get the string that names - the compilation directory. */ - resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error); - if (resattr == DW_DLV_ERROR) { - return resattr; - } - if (resattr == DW_DLV_OK) { - int cres = DW_DLV_ERROR; - char *cdir = 0; - - cres = dwarf_formstring(comp_dir_attr, &cdir, error); - if (cres == DW_DLV_ERROR) { - return cres; - } else if (cres == DW_DLV_OK) { - comp_dir = (Dwarf_Small *) cdir; - } - } - if (resattr == DW_DLV_OK) { - dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR); - } - dwarf_init_line_table_prefix(&line_prefix); - { - Dwarf_Small *line_ptr_out = 0; - int dres = dwarf_read_line_table_prefix(dbg, - line_ptr, - dbg->de_debug_line.dss_size, - &line_ptr_out, - &line_prefix, - NULL, NULL,error, - 0); - - if (dres == DW_DLV_ERROR) { - dwarf_free_line_table_prefix(&line_prefix); - return dres; - } - if (dres == DW_DLV_NO_ENTRY) { - dwarf_free_line_table_prefix(&line_prefix); - return dres; - } - - line_ptr = line_ptr_out; - } - - for (i = 0; i < line_prefix.pf_files_count; ++i) { - struct Line_Table_File_Entry_s *fe = - line_prefix.pf_line_table_file_entries + i; - char *file_name = (char *) fe->lte_filename; - char *dir_name = 0; - char *full_name = 0; - Dwarf_Unsigned dir_index = fe->lte_directory_index; - - if (dir_index == 0) { - dir_name = (char *) comp_dir; - } else { - dir_name = - (char *) line_prefix.pf_include_directories[ - fe->lte_directory_index - 1]; - } - - /* dir_name can be NULL if there is no DW_AT_comp_dir */ - if(dir_name == 0 || file_name_is_full_path((unsigned char *)file_name)) { - /* This is safe because dwarf_dealloc is careful to not - dealloc strings which are part of the raw .debug_* data. - */ - full_name = file_name; - } else { - full_name = (char *) _dwarf_get_alloc(dbg, DW_DLA_STRING, - strlen(dir_name) + 1 + - strlen(file_name) + - 1); - if (full_name == NULL) { - dwarf_free_line_table_prefix(&line_prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - /* This is not careful to avoid // in the output, Nothing - forces a 'canonical' name format here. Unclear if this - needs to be fixed. */ - strcpy(full_name, dir_name); - strcat(full_name, "/"); - strcat(full_name, file_name); - } - curr_chain = - (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (curr_chain == NULL) { - dwarf_free_line_table_prefix(&line_prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - curr_chain->ch_item = full_name; - if (head_chain == NULL) - head_chain = prev_chain = curr_chain; - else { - prev_chain->ch_next = curr_chain; - prev_chain = curr_chain; - } - } - - curr_chain = (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (curr_chain == NULL) { - dwarf_free_line_table_prefix(&line_prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - - - - if (line_prefix.pf_files_count == 0) { - *srcfiles = NULL; - *srcfilecount = 0; - dwarf_free_line_table_prefix(&line_prefix); - return (DW_DLV_NO_ENTRY); - } - - ret_files = (char **) - _dwarf_get_alloc(dbg, DW_DLA_LIST, line_prefix.pf_files_count); - if (ret_files == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - dwarf_free_line_table_prefix(&line_prefix); - return (DW_DLV_ERROR); - } - - curr_chain = head_chain; - for (i = 0; i < line_prefix.pf_files_count; i++) { - *(ret_files + i) = curr_chain->ch_item; - prev_chain = curr_chain; - curr_chain = curr_chain->ch_next; - dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN); - } - - *srcfiles = ret_files; - *srcfilecount = line_prefix.pf_files_count; - dwarf_free_line_table_prefix(&line_prefix); - return (DW_DLV_OK); -} - - -/* - return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR -*/ -int -_dwarf_internal_srclines(Dwarf_Die die, - Dwarf_Line ** linebuf, - Dwarf_Signed * count, - Dwarf_Bool doaddrs, - Dwarf_Bool dolines, Dwarf_Error * error) -{ - /* This pointer is used to scan the portion of the .debug_line - section for the current cu. */ - Dwarf_Small *line_ptr = 0; - - /* This points to the last byte of the .debug_line portion for the - current cu. */ - Dwarf_Small *line_ptr_end = 0; - - /* Pointer to a DW_AT_stmt_list attribute in case it exists in the - die. */ - Dwarf_Attribute stmt_list_attr = 0; - - /* Pointer to DW_AT_comp_dir attribute in die. */ - Dwarf_Attribute comp_dir_attr = 0; - - /* Pointer to name of compilation directory. */ - Dwarf_Small *comp_dir = NULL; - - /* Offset into .debug_line specified by a DW_AT_stmt_list - attribute. */ - Dwarf_Unsigned line_offset = 0; - - Dwarf_File_Entry file_entries = 0; - - /* These are the state machine state variables. */ - Dwarf_Addr address = 0; - Dwarf_Word file = 1; - Dwarf_Word line = 1; - Dwarf_Word column = 0; - - /* Phony init. See below for true initialization. */ - Dwarf_Bool is_stmt = false; - - Dwarf_Bool basic_block = false; - Dwarf_Bool prologue_end = false; - Dwarf_Bool epilogue_begin = false; - Dwarf_Small isa = 0; - Dwarf_Bool end_sequence = false; - - /* These pointers are used to build the list of files names by this - cu. cur_file_entry points to the file name being added, and - prev_file_entry to the previous one. */ - Dwarf_File_Entry cur_file_entry, prev_file_entry; - - Dwarf_Sword i = 0; - Dwarf_Sword file_entry_count = 0; - - /* This is the current opcode read from the statement program. */ - Dwarf_Small opcode = 0; - - /* Pointer to a Dwarf_Line_Context_s structure that contains the - context such as file names and include directories for the set - of lines being generated. */ - Dwarf_Line_Context line_context = 0; - - /* This is a pointer to the current line being added to the line - matrix. */ - Dwarf_Line curr_line = 0; - - /* These variables are used to decode leb128 numbers. Leb128_num - holds the decoded number, and leb128_length is its length in - bytes. */ - Dwarf_Word leb128_num = 0; - Dwarf_Word leb128_length = 0; - Dwarf_Sword advance_line = 0; - - /* This is the operand of the latest fixed_advance_pc extended - opcode. */ - Dwarf_Half fixed_advance_pc = 0; - - /* Counts the number of lines in the line matrix. */ - Dwarf_Sword line_count = 0; - - /* This is the length of an extended opcode instr. */ - Dwarf_Word instr_length = 0; - Dwarf_Small ext_opcode = 0; - struct Line_Table_Prefix_s prefix; - - /* Used to chain together pointers to line table entries that are - later used to create a block of Dwarf_Line entries. */ - Dwarf_Chain chain_line = NULL; - Dwarf_Chain head_chain = NULL; - Dwarf_Chain curr_chain = NULL; - - /* This points to a block of Dwarf_Lines, a pointer to which is - returned in linebuf. */ - Dwarf_Line *block_line = 0; - - /* The Dwarf_Debug this die belongs to. */ - Dwarf_Debug dbg = 0; - int resattr = DW_DLV_ERROR; - int lres = DW_DLV_ERROR; - Dwarf_Half address_size = 0; - - int res = DW_DLV_ERROR; - - /* ***** BEGIN CODE ***** */ - if (error != NULL) - *error = NULL; - - CHECK_DIE(die, DW_DLV_ERROR); - dbg = die->di_cu_context->cc_dbg; - - res = _dwarf_load_section(dbg, &dbg->de_debug_line,error); - if (res != DW_DLV_OK) { - return res; - } - address_size = _dwarf_get_address_size(dbg, die); - resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error); - if (resattr != DW_DLV_OK) { - return resattr; - } - - lres = dwarf_formudata(stmt_list_attr, &line_offset, error); - if (lres != DW_DLV_OK) { - return lres; - } - - if (line_offset >= dbg->de_debug_line.dss_size) { - _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); - return (DW_DLV_ERROR); - } - line_ptr = dbg->de_debug_line.dss_data + line_offset; - dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR); - - /* If die has DW_AT_comp_dir attribute, get the string that names - the compilation directory. */ - resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error); - if (resattr == DW_DLV_ERROR) { - return resattr; - } - if (resattr == DW_DLV_OK) { - int cres = DW_DLV_ERROR; - char *cdir = 0; - - cres = dwarf_formstring(comp_dir_attr, &cdir, error); - if (cres == DW_DLV_ERROR) { - return cres; - } else if (cres == DW_DLV_OK) { - comp_dir = (Dwarf_Small *) cdir; - } - } - if (resattr == DW_DLV_OK) { - dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR); - } - dwarf_init_line_table_prefix(&prefix); - - { - Dwarf_Small *newlinep = 0; - int res = dwarf_read_line_table_prefix(dbg, - line_ptr, - dbg->de_debug_line.dss_size, - &newlinep, - &prefix, - NULL,NULL, - error, - 0); - - if (res == DW_DLV_ERROR) { - dwarf_free_line_table_prefix(&prefix); - return res; - } - if (res == DW_DLV_NO_ENTRY) { - dwarf_free_line_table_prefix(&prefix); - return res; - } - line_ptr_end = prefix.pf_line_ptr_end; - line_ptr = newlinep; - } - - - /* Set up context structure for this set of lines. */ - line_context = (Dwarf_Line_Context) - _dwarf_get_alloc(dbg, DW_DLA_LINE_CONTEXT, 1); - if (line_context == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - /* Fill out a Dwarf_File_Entry list as we use that to implement the - define_file operation. */ - file_entries = prev_file_entry = NULL; - for (i = 0; i < prefix.pf_files_count; ++i) { - struct Line_Table_File_Entry_s *pfxfile = - prefix.pf_line_table_file_entries + i; - - cur_file_entry = (Dwarf_File_Entry) - _dwarf_get_alloc(dbg, DW_DLA_FILE_ENTRY, 1); - if (cur_file_entry == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - cur_file_entry->fi_file_name = pfxfile->lte_filename; - cur_file_entry->fi_dir_index = pfxfile->lte_directory_index; - cur_file_entry->fi_time_last_mod = - pfxfile->lte_last_modification_time; - - cur_file_entry->fi_file_length = pfxfile->lte_length_of_file; - - if (file_entries == NULL) - file_entries = cur_file_entry; - else - prev_file_entry->fi_next = cur_file_entry; - prev_file_entry = cur_file_entry; - - file_entry_count++; - } - - - /* Initialize the one state machine variable that depends on the - prefix. */ - is_stmt = prefix.pf_default_is_stmt; - - - /* Start of statement program. */ - while (line_ptr < line_ptr_end) { - int type; - - opcode = *(Dwarf_Small *) line_ptr; - line_ptr++; - - - /* 'type' is the output */ - WHAT_IS_OPCODE(type, opcode, prefix.pf_opcode_base, - prefix.pf_opcode_length_table, line_ptr, - prefix.pf_std_op_count); - - if (type == LOP_DISCARD) { - int oc; - int opcnt = prefix.pf_opcode_length_table[opcode]; - - for (oc = 0; oc < opcnt; oc++) { - /* - ** Read and discard operands we don't - ** understand. - ** arbitrary choice of unsigned read. - ** signed read would work as well. - */ - Dwarf_Unsigned utmp2; - - DECODE_LEB128_UWORD(line_ptr, utmp2); - } - } else if (type == LOP_SPECIAL) { - /* This op code is a special op in the object, no matter - that it might fall into the standard op range in this - compile. That is, these are special opcodes between - opcode_base and MAX_LINE_OP_CODE. (including - opcode_base and MAX_LINE_OP_CODE) */ - - opcode = opcode - prefix.pf_opcode_base; - address = address + prefix.pf_minimum_instruction_length * - (opcode / prefix.pf_line_range); - line = - line + prefix.pf_line_base + - opcode % prefix.pf_line_range; - - if (dolines) { - curr_line = - (Dwarf_Line) _dwarf_get_alloc(dbg, DW_DLA_LINE, 1); - if (curr_line == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - curr_line->li_address = address; - curr_line->li_addr_line.li_l_data.li_file = - (Dwarf_Sword) file; - curr_line->li_addr_line.li_l_data.li_line = - (Dwarf_Sword) line; - curr_line->li_addr_line.li_l_data.li_column = - (Dwarf_Half) column; - curr_line->li_addr_line.li_l_data.li_is_stmt = is_stmt; - curr_line->li_addr_line.li_l_data.li_basic_block = - basic_block; - curr_line->li_addr_line.li_l_data.li_end_sequence = - curr_line->li_addr_line.li_l_data. - li_epilogue_begin = epilogue_begin; - curr_line->li_addr_line.li_l_data.li_prologue_end = - prologue_end; - curr_line->li_addr_line.li_l_data.li_isa = isa; - curr_line->li_context = line_context; - line_count++; - - chain_line = (Dwarf_Chain) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (chain_line == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - chain_line->ch_item = curr_line; - - if (head_chain == NULL) - head_chain = curr_chain = chain_line; - else { - curr_chain->ch_next = chain_line; - curr_chain = chain_line; - } - } - - basic_block = false; - } else if (type == LOP_STANDARD) { - switch (opcode) { - - case DW_LNS_copy:{ - if (dolines) { - - curr_line = - (Dwarf_Line) _dwarf_get_alloc(dbg, - DW_DLA_LINE, - 1); - if (curr_line == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - curr_line->li_address = address; - curr_line->li_addr_line.li_l_data.li_file = - (Dwarf_Sword) file; - curr_line->li_addr_line.li_l_data.li_line = - (Dwarf_Sword) line; - curr_line->li_addr_line.li_l_data.li_column = - (Dwarf_Half) column; - curr_line->li_addr_line.li_l_data.li_is_stmt = - is_stmt; - curr_line->li_addr_line.li_l_data. - li_basic_block = basic_block; - curr_line->li_addr_line.li_l_data. - li_end_sequence = end_sequence; - curr_line->li_context = line_context; - curr_line->li_addr_line.li_l_data. - li_epilogue_begin = epilogue_begin; - curr_line->li_addr_line.li_l_data. - li_prologue_end = prologue_end; - curr_line->li_addr_line.li_l_data.li_isa = isa; - line_count++; - - chain_line = (Dwarf_Chain) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (chain_line == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - chain_line->ch_item = curr_line; - if (head_chain == NULL) - head_chain = curr_chain = chain_line; - else { - curr_chain->ch_next = chain_line; - curr_chain = chain_line; - } - } - - basic_block = false; - prologue_end = false; - epilogue_begin = false; - break; - } - - case DW_LNS_advance_pc:{ - Dwarf_Unsigned utmp2; - - DECODE_LEB128_UWORD(line_ptr, utmp2); - leb128_num = (Dwarf_Word) utmp2; - address = - address + - prefix.pf_minimum_instruction_length * - leb128_num; - break; - } - - case DW_LNS_advance_line:{ - Dwarf_Signed stmp; - - DECODE_LEB128_SWORD(line_ptr, stmp); - advance_line = (Dwarf_Sword) stmp; - line = line + advance_line; - break; - } - - case DW_LNS_set_file:{ - Dwarf_Unsigned utmp2; - - DECODE_LEB128_UWORD(line_ptr, utmp2); - file = (Dwarf_Word) utmp2; - break; - } - - case DW_LNS_set_column:{ - Dwarf_Unsigned utmp2; - - DECODE_LEB128_UWORD(line_ptr, utmp2); - column = (Dwarf_Word) utmp2; - break; - } - - case DW_LNS_negate_stmt:{ - - is_stmt = !is_stmt; - break; - } - - case DW_LNS_set_basic_block:{ - - basic_block = true; - break; - } - - case DW_LNS_const_add_pc:{ - opcode = MAX_LINE_OP_CODE - prefix.pf_opcode_base; - address = address + - prefix.pf_minimum_instruction_length * (opcode / - prefix. - pf_line_range); - break; - } - - case DW_LNS_fixed_advance_pc:{ - - READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half, - line_ptr, sizeof(Dwarf_Half)); - line_ptr += sizeof(Dwarf_Half); - address = address + fixed_advance_pc; - break; - } - - /* New in DWARF3 */ - case DW_LNS_set_prologue_end:{ - - prologue_end = true; - break; - - - } - /* New in DWARF3 */ - case DW_LNS_set_epilogue_begin:{ - epilogue_begin = true; - break; - } - - /* New in DWARF3 */ - case DW_LNS_set_isa:{ - Dwarf_Unsigned utmp2; - - DECODE_LEB128_UWORD(line_ptr, utmp2); - isa = utmp2; - if (isa != utmp2) { - /* The value of the isa did not fit in our - local so we record it wrong. declare an - error. */ - dwarf_free_line_table_prefix(&prefix); - - _dwarf_error(dbg, error, - DW_DLE_LINE_NUM_OPERANDS_BAD); - return (DW_DLV_ERROR); - } - break; - } - } - - } else if (type == LOP_EXTENDED) { - Dwarf_Unsigned utmp3; - - DECODE_LEB128_UWORD(line_ptr, utmp3); - instr_length = (Dwarf_Word) utmp3; - /* Dwarf_Small is a ubyte and the extended opcode is a - ubyte, though not stated as clearly in the 2.0.0 spec as - one might hope. */ - ext_opcode = *(Dwarf_Small *) line_ptr; - line_ptr++; - switch (ext_opcode) { - - case DW_LNE_end_sequence:{ - end_sequence = true; - - if (dolines) { - curr_line = (Dwarf_Line) - _dwarf_get_alloc(dbg, DW_DLA_LINE, 1); - if (curr_line == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - curr_line->li_address = address; - curr_line->li_addr_line.li_l_data.li_file = - (Dwarf_Sword) file; - curr_line->li_addr_line.li_l_data.li_line = - (Dwarf_Sword) line; - curr_line->li_addr_line.li_l_data.li_column = - (Dwarf_Half) column; - curr_line->li_addr_line.li_l_data.li_is_stmt = - prefix.pf_default_is_stmt; - curr_line->li_addr_line.li_l_data. - li_basic_block = basic_block; - curr_line->li_addr_line.li_l_data. - li_end_sequence = end_sequence; - curr_line->li_context = line_context; - curr_line->li_addr_line.li_l_data. - li_epilogue_begin = epilogue_begin; - curr_line->li_addr_line.li_l_data. - li_prologue_end = prologue_end; - curr_line->li_addr_line.li_l_data.li_isa = isa; - line_count++; - - chain_line = (Dwarf_Chain) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (chain_line == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - chain_line->ch_item = curr_line; - - if (head_chain == NULL) - head_chain = curr_chain = chain_line; - else { - curr_chain->ch_next = chain_line; - curr_chain = chain_line; - } - } - - address = 0; - file = 1; - line = 1; - column = 0; - is_stmt = prefix.pf_default_is_stmt; - basic_block = false; - end_sequence = false; - prologue_end = false; - epilogue_begin = false; - - - break; - } - - case DW_LNE_set_address:{ - { - READ_UNALIGNED(dbg, address, Dwarf_Addr, - line_ptr, address_size); - if (doaddrs) { - curr_line = - (Dwarf_Line) _dwarf_get_alloc(dbg, - DW_DLA_LINE, - 1); - if (curr_line == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, - DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - curr_line->li_address = address; - curr_line->li_addr_line.li_offset = - line_ptr - dbg->de_debug_line.dss_data; - - line_count++; - - chain_line = (Dwarf_Chain) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (chain_line == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, - DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - chain_line->ch_item = curr_line; - - if (head_chain == NULL) - head_chain = curr_chain = chain_line; - else { - curr_chain->ch_next = chain_line; - curr_chain = chain_line; - } - } - - line_ptr += address_size; - } - - break; - } - - case DW_LNE_define_file:{ - - if (dolines) { - cur_file_entry = (Dwarf_File_Entry) - _dwarf_get_alloc(dbg, DW_DLA_FILE_ENTRY, 1); - if (cur_file_entry == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - cur_file_entry->fi_file_name = - (Dwarf_Small *) line_ptr; - line_ptr = - line_ptr + strlen((char *) line_ptr) + 1; - - cur_file_entry->fi_dir_index = (Dwarf_Sword) - _dwarf_decode_u_leb128(line_ptr, - &leb128_length); - line_ptr = line_ptr + leb128_length; - - cur_file_entry->fi_time_last_mod = - _dwarf_decode_u_leb128(line_ptr, - &leb128_length); - line_ptr = line_ptr + leb128_length; - - cur_file_entry->fi_file_length = - _dwarf_decode_u_leb128(line_ptr, - &leb128_length); - line_ptr = line_ptr + leb128_length; - - if (file_entries == NULL) - file_entries = cur_file_entry; - else - prev_file_entry->fi_next = cur_file_entry; - prev_file_entry = cur_file_entry; - - file_entry_count++; - } - break; - } - - default:{ - /* This is an extended op code we do not know about, - other than we know now many bytes it is - and the op code and the bytes of operand. */ - Dwarf_Unsigned remaining_bytes = instr_length -1; - if(instr_length < 1 || remaining_bytes > DW_LNE_LEN_MAX) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, - DW_DLE_LINE_EXT_OPCODE_BAD); - return (DW_DLV_ERROR); - } - line_ptr += remaining_bytes; - break; - } - } - - } - } - - block_line = (Dwarf_Line *) - _dwarf_get_alloc(dbg, DW_DLA_LIST, line_count); - if (block_line == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - curr_chain = head_chain; - for (i = 0; i < line_count; i++) { - *(block_line + i) = curr_chain->ch_item; - head_chain = curr_chain; - curr_chain = curr_chain->ch_next; - dwarf_dealloc(dbg, head_chain, DW_DLA_CHAIN); - } - - line_context->lc_file_entries = file_entries; - line_context->lc_file_entry_count = file_entry_count; - line_context->lc_include_directories_count = - prefix.pf_include_directories_count; - if (prefix.pf_include_directories_count > 0) { - /* This gets a pointer to the *first* include dir. The others - follow directly with the standard DWARF2/3 NUL byte - following the last. */ - line_context->lc_include_directories = - prefix.pf_include_directories[0]; - } - - line_context->lc_line_count = line_count; - line_context->lc_compilation_directory = comp_dir; - line_context->lc_version_number = prefix.pf_version; - line_context->lc_dbg = dbg; - *count = line_count; - - *linebuf = block_line; - dwarf_free_line_table_prefix(&prefix); - return (DW_DLV_OK); -} - -int -dwarf_srclines(Dwarf_Die die, - Dwarf_Line ** linebuf, - Dwarf_Signed * linecount, Dwarf_Error * error) -{ - Dwarf_Signed count = 0; - int res = _dwarf_internal_srclines(die, linebuf, &count, - /* addrlist= */ false, - /* linelist= */ true, error); - if (res != DW_DLV_OK) { - return res; - } - *linecount = count; - return res; -} - - - -/* Every line table entry (except DW_DLE_end_sequence, - which is returned using dwarf_lineendsequence()) - potentially has the begin-statement - flag marked 'on'. This returns thru *return_bool, - the begin-statement flag. -*/ - -int -dwarf_linebeginstatement(Dwarf_Line line, - Dwarf_Bool * return_bool, Dwarf_Error * error) -{ - if (line == NULL || return_bool == 0) { - _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); - return (DW_DLV_ERROR); - } - - *return_bool = (line->li_addr_line.li_l_data.li_is_stmt); - return DW_DLV_OK; -} - -/* At the end of any contiguous line-table there may be - a DW_LNE_end_sequence operator. - This returns non-zero thru *return_bool - if and only if this 'line' entry was a DW_LNE_end_sequence. - - Within a compilation unit or function there may be multiple - line tables, each ending with a DW_LNE_end_sequence. - Each table describes a contiguous region. - Because compilers may split function code up in arbitrary ways - compilers may need to emit multiple contigous regions (ie - line tables) for a single function. - See the DWARF3 spec section 6.2. -*/ -int -dwarf_lineendsequence(Dwarf_Line line, - Dwarf_Bool * return_bool, Dwarf_Error * error) -{ - if (line == NULL) { - _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); - return (DW_DLV_ERROR); - } - - *return_bool = (line->li_addr_line.li_l_data.li_end_sequence); - return DW_DLV_OK; -} - - -/* Each 'line' entry has a line-number. - If the entry is a DW_LNE_end_sequence the line-number is - meaningless (see dwarf_lineendsequence(), just above). -*/ -int -dwarf_lineno(Dwarf_Line line, - Dwarf_Unsigned * ret_lineno, Dwarf_Error * error) -{ - if (line == NULL || ret_lineno == 0) { - _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); - return (DW_DLV_ERROR); - } - - *ret_lineno = (line->li_addr_line.li_l_data.li_line); - return DW_DLV_OK; -} - -/* Each 'line' entry has a file-number, and index into the file table. - If the entry is a DW_LNE_end_sequence the index is - meaningless (see dwarf_lineendsequence(), just above). - The file number returned is an index into the file table - produced by dwarf_srcfiles(), but care is required: the - li_file begins with 1 for real files, so that the li_file returned here - is 1 greater than its index into the dwarf_srcfiles() output array. - And entries from DW_LNE_define_file don't appear in - the dwarf_srcfiles() output so file indexes from here may exceed - the size of the dwarf_srcfiles() output array size. -*/ -int -dwarf_line_srcfileno(Dwarf_Line line, - Dwarf_Unsigned * ret_fileno, Dwarf_Error * error) -{ - if (line == NULL || ret_fileno == 0) { - _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); - return (DW_DLV_ERROR); - } - /* li_file must be <= line->li_context->lc_file_entry_count else it - is trash. li_file 0 means not attributable to any source file - per dwarf2/3 spec. */ - - *ret_fileno = (line->li_addr_line.li_l_data.li_file); - return DW_DLV_OK; -} - - -/* Each 'line' entry has a line-address. - If the entry is a DW_LNE_end_sequence the adddress - is one-beyond the last address this contigous region - covers, so the address is not inside the region, - but is just outside it. -*/ -int -dwarf_lineaddr(Dwarf_Line line, - Dwarf_Addr * ret_lineaddr, Dwarf_Error * error) -{ - if (line == NULL || ret_lineaddr == 0) { - _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); - return (DW_DLV_ERROR); - } - - *ret_lineaddr = (line->li_address); - return DW_DLV_OK; -} - - -/* Each 'line' entry has a column-within-line (offset - within the line) where the - source text begins. - If the entry is a DW_LNE_end_sequence the line-number is - meaningless (see dwarf_lineendsequence(), just above). - Lines of text begin at column 1. The value 0 - means the line begins at the left edge of the line. - (See the DWARF3 spec, section 6.2.2). -*/ -int -dwarf_lineoff(Dwarf_Line line, - Dwarf_Signed * ret_lineoff, Dwarf_Error * error) -{ - if (line == NULL || ret_lineoff == 0) { - _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); - return (DW_DLV_ERROR); - } - - *ret_lineoff = - (line->li_addr_line.li_l_data.li_column == - 0 ? -1 : line->li_addr_line.li_l_data.li_column); - return DW_DLV_OK; -} - - -int -dwarf_linesrc(Dwarf_Line line, char **ret_linesrc, Dwarf_Error * error) -{ - Dwarf_Signed i = 0; - Dwarf_File_Entry file_entry; - Dwarf_Small *name_buffer = 0; - Dwarf_Small *include_directories = 0; - Dwarf_Small include_direc_full_path = 0; - Dwarf_Small file_name_full_path = 0; - Dwarf_Debug dbg = 0; - unsigned int comp_dir_len = 0; - - if (line == NULL) { - _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); - return (DW_DLV_ERROR); - } - - if (line->li_context == NULL) { - _dwarf_error(NULL, error, DW_DLE_LINE_CONTEXT_NULL); - return (DW_DLV_ERROR); - } - dbg = line->li_context->lc_dbg; - - if (line->li_addr_line.li_l_data.li_file > - line->li_context->lc_file_entry_count) { - _dwarf_error(dbg, error, DW_DLE_LINE_FILE_NUM_BAD); - return (DW_DLV_ERROR); - } - - if (line->li_addr_line.li_l_data.li_file == 0) { - /* No file name known: see dwarf2/3 spec. */ - _dwarf_error(dbg, error, DW_DLE_NO_FILE_NAME); - return (DW_DLV_ERROR); - } - file_entry = line->li_context->lc_file_entries; - /* ASSERT: li_file > 0, dwarf correctness issue, see line table - definition of dwarf2/3 spec. */ - /* Example: if li_file is 2 and lc_file_entry_count is 3, - file_entry is file 3 (1 based), aka 2( 0 based) file_entry->next - is file 2 (1 based), aka 1( 0 based) file_entry->next->next is - file 1 (1 based), aka 0( 0 based) file_entry->next->next->next - is NULL. - - and this loop finds the file_entry we need (2 (1 based) in this - case). Because lc_file_entries are in reverse order and - effectively zero based as a count whereas li_file is 1 based. */ - for (i = line->li_addr_line.li_l_data.li_file - 1; i > 0; i--) - file_entry = file_entry->fi_next; - - if (file_entry->fi_file_name == NULL) { - _dwarf_error(dbg, error, DW_DLE_NO_FILE_NAME); - return (DW_DLV_ERROR); - } - - file_name_full_path = file_name_is_full_path(file_entry->fi_file_name); - if (file_name_full_path) { - *ret_linesrc = ((char *) file_entry->fi_file_name); - return DW_DLV_OK; - } - - if (file_entry->fi_dir_index == 0) { - - /* dir_index of 0 means that the compilation was in the - 'current directory of compilation' */ - if (line->li_context->lc_compilation_directory == NULL) { - /* we don't actually *have* a current directory of - compilation: DW_AT_comp_dir was not present Rather than - emitting DW_DLE_NO_COMP_DIR lets just make an empty name - here. In other words, do the best we can with what we do - have instead of reporting an error. _dwarf_error(dbg, - error, DW_DLE_NO_COMP_DIR); return(DW_DLV_ERROR); */ - comp_dir_len = 0; - } else { - comp_dir_len = strlen((char *) - (line->li_context-> - lc_compilation_directory)); - } - - name_buffer = - _dwarf_get_alloc(line->li_context->lc_dbg, DW_DLA_STRING, - comp_dir_len + 1 + - strlen((char *) file_entry->fi_file_name) + - 1); - if (name_buffer == NULL) { - _dwarf_error(line->li_context->lc_dbg, error, - DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - if (comp_dir_len > 0) { - /* if comp_dir_len is 0 we do not want to put a / in front - of the fi_file_name as we just don't know anything. */ - strcpy((char *) name_buffer, - (char *) (line->li_context-> - lc_compilation_directory)); - strcat((char *) name_buffer, "/"); - } - strcat((char *) name_buffer, (char *) file_entry->fi_file_name); - *ret_linesrc = ((char *) name_buffer); - return DW_DLV_OK; - } - - if (file_entry->fi_dir_index > - line->li_context->lc_include_directories_count) { - _dwarf_error(dbg, error, DW_DLE_INCL_DIR_NUM_BAD); - return (DW_DLV_ERROR); - } - - include_directories = line->li_context->lc_include_directories; - for (i = file_entry->fi_dir_index - 1; i > 0; i--) - include_directories += strlen((char *) include_directories) + 1; - - if (line->li_context->lc_compilation_directory) { - comp_dir_len = strlen((char *) - (line->li_context->lc_compilation_directory)); - } else { - /* No DW_AT_comp_dir present. Do the best we can without it. */ - comp_dir_len = 0; - } - - include_direc_full_path = file_name_is_full_path(include_directories); - name_buffer = _dwarf_get_alloc(dbg, DW_DLA_STRING, - (include_direc_full_path ? 0 : comp_dir_len + 1) + - strlen((char *)include_directories) + 1 + - strlen((char *)file_entry->fi_file_name) + 1); - if (name_buffer == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - if (!include_direc_full_path) { - if (comp_dir_len > 0) { - strcpy((char *)name_buffer, - (char *)line->li_context->lc_compilation_directory); - /* Who provides the / needed after the compilation - directory? */ - if (!is_path_separator(name_buffer[comp_dir_len - 1])) { - /* Here we provide the / separator. It - should work ok for Windows */ - /* Overwrite previous nul terminator with needed / */ - name_buffer[comp_dir_len] = '/'; - name_buffer[comp_dir_len + 1] = 0; - } - } - } else { - strcpy((char *) name_buffer, ""); - } - strcat((char *) name_buffer, (char *) include_directories); - strcat((char *) name_buffer, "/"); - strcat((char *) name_buffer, (char *) file_entry->fi_file_name); - *ret_linesrc = ((char *) name_buffer); - return DW_DLV_OK; -} - -/* Every line table entry potentially has the basic-block-start - flag marked 'on'. This returns thru *return_bool, - the basic-block-start flag. -*/ -int -dwarf_lineblock(Dwarf_Line line, - Dwarf_Bool * return_bool, Dwarf_Error * error) -{ - if (line == NULL) { - _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); - return (DW_DLV_ERROR); - } - *return_bool = (line->li_addr_line.li_l_data.li_basic_block); - return DW_DLV_OK; -} - - -#if 0 /* Ignore this. This needs major - re-work. */ -/* - This routine works by looking for exact matches between - the current line address and pc, and crossovers from - from less than pc value to greater than. At each line - that satisfies the above, it records a pointer to the - line, and the difference between the address and pc. - It then scans these pointers and picks out those with - the smallest difference between pc and address. -*/ -int -dwarf_pclines(Dwarf_Debug dbg, - Dwarf_Addr pc, - Dwarf_Line ** linebuf, - Dwarf_Signed slide, - Dwarf_Signed * linecount, Dwarf_Error * error) -{ - /* - Scans the line matrix for the current cu to which a pointer - exists in dbg. */ - Dwarf_Line line; - Dwarf_Line prev_line; - - /* - These flags are for efficiency reasons. Check_line is true - initially, but set false when the address of the current line is - greater than pc. It is set true only when the address of the - current line falls below pc. This assumes that addresses within - the same segment increase, and we are only interested in the - switch from a less than pc address to a greater than. First_line - is set true initially, but set false after the first line is - scanned. This is to prevent looking at the address of previous - line when slide is DW_DLS_BACKWARD, and the first line is being - scanned. */ - Dwarf_Bool check_line, first_line; - - /* - Diff tracks the smallest difference a line address and the input - pc value. */ - Dwarf_Signed diff, i; - - /* - For the slide = DW_DLS_BACKWARD case, pc_less is the value of - the address of the line immediately preceding the first line - that has value greater than pc. For the slide = DW_DLS_FORWARD - case, pc_more is the values of address for the first line that - is greater than pc. Diff is the difference between either of the - these values and pc. */ - Dwarf_Addr pc_less, pc_more; - - /* - Pc_line_buf points to a chain of pointers to lines of which - those with a diff equal to the smallest difference will be - returned. */ - Dwarf_Line *pc_line_buf, *pc_line; - - /* - Chain_count counts the number of lines in the above chain for - which the diff is equal to the smallest difference This is the - number returned by this routine. */ - Dwarf_Signed chain_count; - - chain_head = NULL; - - check_line = true; - first_line = true; - diff = MAX_LINE_DIFF; - - for (i = 0; i < dbg->de_cu_line_count; i++) { - - line = *(dbg->de_cu_line_ptr + i); - prev_line = first_line ? NULL : *(dbg->de_cu_line_ptr + i - 1); - - if (line->li_address == pc) { - chain_ptr = (struct chain *) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (chain_ptr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - chain_ptr->line = line; - chain_ptr->diff = diff = 0; - chain_ptr->next = chain_head; - chain_head = chain_ptr; - } else - /* - Look for crossover from less than pc address to greater - than. */ - if (check_line && line->li_address > pc && - (first_line ? 0 : prev_line->li_address) < pc) - - if (slide == DW_DLS_BACKWARD && !first_line) { - pc_less = prev_line->li_address; - if (pc - pc_less <= diff) { - chain_ptr = (struct chain *) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (chain_ptr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - chain_ptr->line = prev_line; - chain_ptr->diff = diff = pc - pc_less; - chain_ptr->next = chain_head; - chain_head = chain_ptr; - } - check_line = false; - } else if (slide == DW_DLS_FORWARD) { - pc_more = line->li_address; - if (pc_more - pc <= diff) { - chain_ptr = (struct chain *) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (chain_ptr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - chain_ptr->line = line; - chain_ptr->diff = diff = pc_more - pc; - chain_ptr->next = chain_head; - chain_head = chain_ptr; - } - check_line = false; - } else - /* Check addresses only when they go */ - /* below pc. */ - if (line->li_address < pc) - check_line = true; - - first_line = false; - } - - chain_count = 0; - for (chain_ptr = chain_head; chain_ptr != NULL; - chain_ptr = chain_ptr->next) - if (chain_ptr->diff == diff) - chain_count++; - - pc_line_buf = pc_line = (Dwarf_Line) - _dwarf_get_alloc(dbg, DW_DLA_LIST, chain_count); - for (chain_ptr = chain_head; chain_ptr != NULL; - chain_ptr = chain_ptr->next) - if (chain_ptr->diff == diff) { - *pc_line = chain_ptr->line; - pc_line++; - } - - for (chain_ptr = chain_head; chain_ptr != NULL;) { - chain_head = chain_ptr; - chain_ptr = chain_ptr->next; - dwarf_dealloc(dbg, chain_head, DW_DLA_CHAIN); - } - - *linebuf = pc_line_buf; - return (chain_count); -} -#endif - - - -/* - It's impossible for callers of dwarf_srclines() to get to and - free all the resources (in particular, the li_context and its - lc_file_entries). - So this function, new July 2005, does it. -*/ - -void -dwarf_srclines_dealloc(Dwarf_Debug dbg, Dwarf_Line * linebuf, - Dwarf_Signed count) -{ - - Dwarf_Signed i = 0; - struct Dwarf_Line_Context_s *context = 0; - - if (count > 0) { - /* All these entries share a single context */ - context = linebuf[0]->li_context; - } - for (i = 0; i < count; ++i) { - dwarf_dealloc(dbg, linebuf[i], DW_DLA_LINE); - } - dwarf_dealloc(dbg, linebuf, DW_DLA_LIST); - - if (context) { - Dwarf_File_Entry fe = context->lc_file_entries; - - while (fe) { - Dwarf_File_Entry fenext = fe->fi_next; - - dwarf_dealloc(dbg, fe, DW_DLA_FILE_ENTRY); - fe = fenext; - } - dwarf_dealloc(dbg, context, DW_DLA_LINE_CONTEXT); - } - - return; -} - -/* Operand counts per standard operand. - The initial zero is for DW_LNS_copy. - This is an economical way to verify we understand the table - of standard-opcode-lengths in the line table prologue. */ -#define STANDARD_OPERAND_COUNT_DWARF2 9 -#define STANDARD_OPERAND_COUNT_DWARF3 12 -static unsigned char - dwarf_standard_opcode_operand_count[STANDARD_OPERAND_COUNT_DWARF3] = { - /* DWARF2 */ - 0, - 1, 1, 1, 1, - 0, 0, 0, - 1, - /* Following are new for DWARF3. */ - 0, 0, 1 -}; - -/* We have a normal standard opcode base, but - an arm compiler emitted a non-standard table! - This could lead to problems... - ARM C/C++ Compiler, RVCT4.0 [Build 4 - 00] seems to get the table wrong . */ -static unsigned char -dwarf_arm_standard_opcode_operand_count[STANDARD_OPERAND_COUNT_DWARF3] = { - /* DWARF2 */ - 0, - 1, 1, 1, 1, - 0, 0, 0, - 0, /* <<< --- this is wrong */ - /* Following are new for DWARF3. */ - 0, 0, 1 -}; - -static void -print_header_issue(Dwarf_Debug dbg, - char *specific_msg, - Dwarf_Small *data_start, - int *err_count_out) -{ - if(!err_count_out) - return; - printf("*** DWARF CHECK: " - "line table header: %s", - specific_msg); - if( data_start >= dbg->de_debug_line.dss_data && - (data_start < (dbg->de_debug_line.dss_data + - dbg->de_debug_line.dss_size))) { - Dwarf_Unsigned off = data_start - dbg->de_debug_line.dss_data; - printf(" at .debug_line section offset 0x%" DW_PR_DUx - " ( %" DW_PR_DUu " ) ", - off,off); - } else { - printf(" (unknown section location) "); - } - printf("***\n"); - *err_count_out += 1; -} - - - -/* Common line table prefix reading code. - Returns DW_DLV_OK, DW_DLV_ERROR. - DW_DLV_NO_ENTRY cannot be returned, but callers should - assume it is possible. - - The prefix_out area must be initialized properly before calling this. - - Has the side effect of allocating arrays which - must be freed (see the Line_Table_Prefix_s struct which - holds the pointers to space we allocate here). - - bogus_bytes_ptr and bogus_bytes are output values which - let a print-program notify the user of some surprising bytes - after a line table header and before the line table instructions. - These can be ignored unless one is printing. - And are ignored if NULL passed as the pointer. -*/ - -/* err_count_out may be NULL, in which case we - make no attempt to count checking-type errors. - Checking-type errors do not stop us, we just report them. -*/ -int -dwarf_read_line_table_prefix(Dwarf_Debug dbg, - Dwarf_Small * data_start, - Dwarf_Unsigned data_length, - Dwarf_Small ** updated_data_start_out, - struct Line_Table_Prefix_s *prefix_out, - Dwarf_Small ** bogus_bytes_ptr, - Dwarf_Unsigned *bogus_bytes, - Dwarf_Error * err, - int *err_count_out) -{ - Dwarf_Small *line_ptr = data_start; - Dwarf_Unsigned total_length = 0; - int local_length_size = 0; - int local_extension_size = 0; - Dwarf_Unsigned prologue_length = 0; - Dwarf_Half version = 0; - Dwarf_Unsigned directories_count = 0; - Dwarf_Unsigned directories_malloc = 0; - Dwarf_Unsigned files_count = 0; - Dwarf_Unsigned files_malloc = 0; - Dwarf_Small *line_ptr_end = 0; - Dwarf_Small *lp_begin = 0; - if(bogus_bytes_ptr) *bogus_bytes_ptr = 0; - if(bogus_bytes) *bogus_bytes= 0; - - prefix_out->pf_line_ptr_start = line_ptr; - /* READ_AREA_LENGTH updates line_ptr for consumed bytes */ - READ_AREA_LENGTH(dbg, total_length, Dwarf_Unsigned, - line_ptr, local_length_size, local_extension_size); - - - line_ptr_end = line_ptr + total_length; - prefix_out->pf_line_ptr_end = line_ptr_end; - prefix_out->pf_length_field_length = local_length_size + - local_extension_size; - /* ASSERT: prefix_out->pf_length_field_length == line_ptr - -prefix_out->pf_line_ptr_start; */ - if (line_ptr_end > dbg->de_debug_line.dss_data + - dbg->de_debug_line.dss_size) { - _dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD); - return (DW_DLV_ERROR); - } - if (line_ptr_end > data_start + data_length) { - _dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD); - return (DW_DLV_ERROR); - } - prefix_out->pf_total_length = total_length; - - READ_UNALIGNED(dbg, version, Dwarf_Half, - line_ptr, sizeof(Dwarf_Half)); - prefix_out->pf_version = version; - line_ptr += sizeof(Dwarf_Half); - if (version != CURRENT_VERSION_STAMP && - version != CURRENT_VERSION_STAMP3) { - _dwarf_error(dbg, err, DW_DLE_VERSION_STAMP_ERROR); - return (DW_DLV_ERROR); - } - - READ_UNALIGNED(dbg, prologue_length, Dwarf_Unsigned, - line_ptr, local_length_size); - prefix_out->pf_prologue_length = prologue_length; - line_ptr += local_length_size; - prefix_out->pf_line_prologue_start = line_ptr; - - prefix_out->pf_minimum_instruction_length = - *(unsigned char *) line_ptr; - line_ptr = line_ptr + sizeof(Dwarf_Small); - - prefix_out->pf_default_is_stmt = *(unsigned char *) line_ptr; - line_ptr = line_ptr + sizeof(Dwarf_Small); - - prefix_out->pf_line_base = *(signed char *) line_ptr; - line_ptr = line_ptr + sizeof(Dwarf_Sbyte); - - prefix_out->pf_line_range = *(unsigned char *) line_ptr; - line_ptr = line_ptr + sizeof(Dwarf_Small); - - prefix_out->pf_opcode_base = *(unsigned char *) line_ptr; - line_ptr = line_ptr + sizeof(Dwarf_Small); - - /* Set up the array of standard opcode lengths. */ - /* We think this works ok even for cross-endian processing of - objects. It might be wrong, we might need to specially process - the array of ubyte into host order. */ - prefix_out->pf_opcode_length_table = line_ptr; - - /* pf_opcode_base is one greater than the size of the array. */ - line_ptr += prefix_out->pf_opcode_base - 1; - - { - /* Determine (as best we can) whether the - pf_opcode_length_table holds 9 or 12 standard-conforming - entries. gcc4 upped to DWARF3's 12 without updating the - version number. */ - int operand_ck_fail = true; - - if (prefix_out->pf_opcode_base >= STANDARD_OPERAND_COUNT_DWARF3) { - int mismatch = memcmp(dwarf_standard_opcode_operand_count, - prefix_out->pf_opcode_length_table, - STANDARD_OPERAND_COUNT_DWARF3); - if(mismatch) { - if(err_count_out) { - print_header_issue(dbg,"standard-operands did not match", - data_start,err_count_out); - } - mismatch = memcmp(dwarf_arm_standard_opcode_operand_count, - prefix_out->pf_opcode_length_table, - STANDARD_OPERAND_COUNT_DWARF3); - if(!mismatch && err_count_out) { - print_header_issue(dbg,"arm (incorrect) operands in use", - data_start,err_count_out); - } - } - if (!mismatch) { - if (version == 2) { - if(err_count_out) { - print_header_issue(dbg, - "standard DWARF3 operands matched, but is DWARF2 linetable", - data_start,err_count_out); - } - } - operand_ck_fail = false; - prefix_out->pf_std_op_count = - STANDARD_OPERAND_COUNT_DWARF3; - } - } - if (operand_ck_fail) { - if (prefix_out->pf_opcode_base >= - STANDARD_OPERAND_COUNT_DWARF2) { - - int mismatch = - memcmp(dwarf_standard_opcode_operand_count, - prefix_out->pf_opcode_length_table, - STANDARD_OPERAND_COUNT_DWARF2); - if(mismatch) { - if(err_count_out) { - print_header_issue(dbg,"standard-operands-lengths did not match", - data_start,err_count_out); - } - mismatch = memcmp(dwarf_arm_standard_opcode_operand_count, - prefix_out->pf_opcode_length_table, - STANDARD_OPERAND_COUNT_DWARF2); - if(!mismatch && err_count_out) { - print_header_issue(dbg,"arm (incorrect) operand in use", - data_start,err_count_out); - } - } - - if (!mismatch) { - operand_ck_fail = false; - prefix_out->pf_std_op_count = - STANDARD_OPERAND_COUNT_DWARF2; - } - } - } - if (operand_ck_fail) { - /* Here we are not sure what the pf_std_op_count is. */ - _dwarf_error(dbg, err, DW_DLE_LINE_NUM_OPERANDS_BAD); - return (DW_DLV_ERROR); - } - } - /* At this point we no longer need to check operand counts. */ - - - directories_count = 0; - directories_malloc = 5; - prefix_out->pf_include_directories = malloc(sizeof(Dwarf_Small *) * - directories_malloc); - if (prefix_out->pf_include_directories == NULL) { - _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - memset(prefix_out->pf_include_directories, 0, - sizeof(Dwarf_Small *) * directories_malloc); - - while ((*(char *) line_ptr) != '\0') { - if (directories_count >= directories_malloc) { - Dwarf_Unsigned expand = 2 * directories_malloc; - Dwarf_Unsigned bytesalloc = sizeof(Dwarf_Small *) * expand; - Dwarf_Small **newdirs = - realloc(prefix_out->pf_include_directories, - bytesalloc); - - if (!newdirs) { - _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - /* Doubled size, zero out second half. */ - memset(newdirs + directories_malloc, 0, - sizeof(Dwarf_Small *) * directories_malloc); - directories_malloc = expand; - prefix_out->pf_include_directories = newdirs; - } - prefix_out->pf_include_directories[directories_count] = - line_ptr; - line_ptr = line_ptr + strlen((char *) line_ptr) + 1; - directories_count++; - } - prefix_out->pf_include_directories_count = directories_count; - line_ptr++; - - files_count = 0; - files_malloc = 5; - prefix_out->pf_line_table_file_entries = - malloc(sizeof(struct Line_Table_File_Entry_s) * files_malloc); - if (prefix_out->pf_line_table_file_entries == NULL) { - _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - memset(prefix_out->pf_line_table_file_entries, 0, - sizeof(struct Line_Table_File_Entry_s) * files_malloc); - - while (*(char *) line_ptr != '\0') { - Dwarf_Unsigned utmp; - Dwarf_Unsigned dir_index = 0; - Dwarf_Unsigned lastmod = 0; - Dwarf_Unsigned file_length = 0; - struct Line_Table_File_Entry_s *curline; - Dwarf_Word leb128_length = 0; - - - if (files_count >= files_malloc) { - Dwarf_Unsigned expand = 2 * files_malloc; - struct Line_Table_File_Entry_s *newfiles = - realloc(prefix_out->pf_line_table_file_entries, - sizeof(struct Line_Table_File_Entry_s) * - expand); - if (!newfiles) { - _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - memset(newfiles + files_malloc, 0, - sizeof(struct Line_Table_File_Entry_s) * - files_malloc); - files_malloc = expand; - prefix_out->pf_line_table_file_entries = newfiles; - } - curline = prefix_out->pf_line_table_file_entries + files_count; - - curline->lte_filename = line_ptr; - line_ptr = line_ptr + strlen((char *) line_ptr) + 1; - - DECODE_LEB128_UWORD(line_ptr, utmp); - dir_index = (Dwarf_Sword) utmp; - if (dir_index > directories_count) { - _dwarf_error(dbg, err, DW_DLE_DIR_INDEX_BAD); - return (DW_DLV_ERROR); - } - curline->lte_directory_index = dir_index; - - lastmod = _dwarf_decode_u_leb128(line_ptr, &leb128_length); - line_ptr = line_ptr + leb128_length; - curline->lte_last_modification_time = lastmod; - - /* Skip over file length. */ - file_length = _dwarf_decode_u_leb128(line_ptr, &leb128_length); - line_ptr = line_ptr + leb128_length; - curline->lte_length_of_file = file_length; - - ++files_count; - - } - prefix_out->pf_files_count = files_count; - /* Skip trailing nul byte */ - ++line_ptr; - - - lp_begin = prefix_out->pf_line_prologue_start + - prefix_out->pf_prologue_length; - if (line_ptr != lp_begin) { - if(line_ptr > lp_begin) { - _dwarf_error(dbg, err, DW_DLE_LINE_PROLOG_LENGTH_BAD); - return (DW_DLV_ERROR); - } else { - /* Bug in compiler. These - * bytes are really part of the instruction - * stream. The prefix_out->pf_prologue_length is - * wrong (12 too high). */ - if(bogus_bytes_ptr) { - *bogus_bytes_ptr = line_ptr; - } - if(bogus_bytes) { - /* How far off things are. We expect the - value 12 ! */ - *bogus_bytes = (lp_begin - line_ptr); - } - } - /* Ignore the lp_begin calc. Assume line_ptr right. - Making up for compiler bug. */ - lp_begin = line_ptr; - - } - - *updated_data_start_out = lp_begin; - return DW_DLV_OK; -} - - -/* Initialize the Line_Table_Prefix_s struct. - memset is not guaranteed a portable initializer, but works - fine for current architectures. AFAIK. -*/ -void -dwarf_init_line_table_prefix(struct Line_Table_Prefix_s *pf) -{ - memset(pf, 0, sizeof(*pf)); -} - -/* Free any malloc'd area. of the Line_Table_Prefix_s struct. */ -void -dwarf_free_line_table_prefix(struct Line_Table_Prefix_s *pf) -{ - if (pf->pf_include_directories) { - free(pf->pf_include_directories); - pf->pf_include_directories = 0; - } - if (pf->pf_line_table_file_entries) { - free(pf->pf_line_table_file_entries); - pf->pf_line_table_file_entries = 0; - } - return; -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_line.h b/usr/src/tools/ctf/dwarf/common/dwarf_line.h deleted file mode 100644 index 66d6062754..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_line.h +++ /dev/null @@ -1,331 +0,0 @@ -/* - - Copyright (C) 2000, 2004, 2006 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#define DW_EXTENDED_OPCODE 0 - -/* - This is used as the starting value for an algorithm - to get the minimum difference between 2 values. - UINT_MAX is used as our approximation to infinity. -*/ -#define MAX_LINE_DIFF UINT_MAX - -/* This is for a sanity check on line - table extended opcodes. - It is entirely arbitrary, and 100 is surely too small if - someone was inserting strings in the opcode. */ -#define DW_LNE_LEN_MAX 100 - - -/* - This structure is used to build a list of all the - files that are used in the current compilation unit. - All of the fields execpt fi_next have meanings that - are obvious from section 6.2.4 of the Libdwarf Doc. -*/ -struct Dwarf_File_Entry_s { - /* Points to string naming the file. */ - Dwarf_Small *fi_file_name; - - /* - Index into the list of directories of the directory in which - this file exits. */ - Dwarf_Sword fi_dir_index; - - /* Time of last modification of the file. */ - Dwarf_Unsigned fi_time_last_mod; - - /* Length in bytes of the file. */ - Dwarf_Unsigned fi_file_length; - - /* Pointer for chaining file entries. */ - Dwarf_File_Entry fi_next; -}; - - -typedef struct Dwarf_Line_Context_s *Dwarf_Line_Context; - -/* - This structure provides the context in which the fields of - a Dwarf_Line structure are interpreted. They come from the - statement program prologue. **Updated by dwarf_srclines in - dwarf_line.c. -*/ -struct Dwarf_Line_Context_s { - /* - Points to a chain of entries providing info about source files - for the current set of Dwarf_Line structures. File number - 'li_file 1' is last on the list, the first list entry is the - file numbered lc_file_entry_count. The numbering of the file - names matches the dwarf2/3 line table specification file table - and DW_LNE_define_file numbering rules. */ - Dwarf_File_Entry lc_file_entries; - /* - Count of number of source files for this set of Dwarf_Line - structures. */ - Dwarf_Sword lc_file_entry_count; - /* - Points to the portion of .debug_line section that contains a - list of strings naming the included directories. */ - Dwarf_Small *lc_include_directories; - - /* Count of the number of included directories. */ - Dwarf_Sword lc_include_directories_count; - - /* Count of the number of lines for this cu. */ - Dwarf_Sword lc_line_count; - - /* Points to name of compilation directory. */ - Dwarf_Small *lc_compilation_directory; - - Dwarf_Debug lc_dbg; - - Dwarf_Half lc_version_number; /* DWARF2/3 version number, 2 - for DWARF2, 3 for DWARF3. */ -}; - - -/* - This structure defines a row of the line table. - All of the fields except li_offset have the exact - same meaning that is defined in Section 6.2.2 - of the Libdwarf Document. - - li_offset is used by _dwarf_addr_finder() which is called - by rqs(1), an sgi utility for 'moving' shared libraries - as if the static linker (ld) had linked the shared library - at the newly-specified address. Most libdwarf-using - apps will ignore li_offset and _dwarf_addr_finder(). - -*/ -struct Dwarf_Line_s { - Dwarf_Addr li_address; /* pc value of machine instr */ - union addr_or_line_s { - struct li_inner_s { - Dwarf_Sword li_file; /* int identifying src file */ - /* li_file is a number 1-N, indexing into a conceptual - source file table as described in dwarf2/3 spec line - table doc. (see Dwarf_File_Entry lc_file_entries; and - Dwarf_Sword lc_file_entry_count;) */ - - Dwarf_Sword li_line; /* source file line number. */ - Dwarf_Half li_column; /* source file column number */ - Dwarf_Small li_isa; - - /* To save space, use bit flags. */ - /* indicate start of stmt */ - unsigned char li_is_stmt:1; - - /* indicate start basic block */ - unsigned char li_basic_block:1; - - /* first post sequence instr */ - unsigned char li_end_sequence:1; - - unsigned char li_prologue_end:1; - unsigned char li_epilogue_begin:1; - } li_l_data; - Dwarf_Off li_offset; /* for rqs */ - } li_addr_line; - Dwarf_Line_Context li_context; /* assoc Dwarf_Line_Context_s */ -}; - - -int _dwarf_line_address_offsets(Dwarf_Debug dbg, - Dwarf_Die die, - Dwarf_Addr ** addrs, - Dwarf_Off ** offs, - Dwarf_Unsigned * returncount, - Dwarf_Error * err); -int _dwarf_internal_srclines(Dwarf_Die die, - Dwarf_Line ** linebuf, - Dwarf_Signed * count, - Dwarf_Bool doaddrs, - Dwarf_Bool dolines, Dwarf_Error * error); - - - -/* The LOP, WHAT_IS_OPCODE stuff is here so it can - be reused in 3 places. Seemed hard to keep - the 3 places the same without an inline func or - a macro. - - Handling the line section where the header and the - file being processed do not match (unusual, but - planned for in the design of .debug_line) - is too tricky to recode this several times and keep - it right. - - As it is the code starting up line-reading is duplicated - and that is just wrong to do. FIXME! -*/ -#define LOP_EXTENDED 1 -#define LOP_DISCARD 2 -#define LOP_STANDARD 3 -#define LOP_SPECIAL 4 - -#define WHAT_IS_OPCODE(type,opcode,base,opcode_length,line_ptr,highest_std) \ - if( (opcode) < (base) ) { \ - /* we know we must treat as a standard op \ - or a special case. \ - */ \ - if((opcode) == DW_EXTENDED_OPCODE) { \ - type = LOP_EXTENDED; \ - } else if( ((highest_std)+1) >= (base)) { \ - /* == Standard case: compile of \ - dwarf_line.c and object \ - have same standard op codes set. \ - \ - > Special case: compile of dwarf_line.c\ - has things in standard op codes list \ - in dwarf.h header not \ - in the object: handle this as a standard\ - op code in switch below. \ - The header special ops overlap the \ - object standard ops. \ - The new standard op codes will not \ - appear in the object. \ - */ \ - type = LOP_STANDARD; \ - } else { \ - /* These are standard opcodes in the object\ - ** that were not defined in the header \ - ** at the time dwarf_line.c \ - ** was compiled. Provides the ability of \ - ** out-of-date dwarf reader to read newer \ - ** line table data transparently. \ - */ \ - type = LOP_DISCARD; \ - } \ - \ - } else { \ - /* Is a special op code. \ - */ \ - type = LOP_SPECIAL; \ - } - -/* The following is from the dwarf definition of 'ubyte' - and is specifically mentioned in section 6.2.5.1, page 54 - of the Rev 2.0.0 dwarf specification. -*/ - -#define MAX_LINE_OP_CODE 255 - - -/* The following structs (Line_Table_File_Entry_s,Line_Table_Prefix_s) - and functions allow refactoring common code into a single - reader routine. -*/ -/* There can be zero of more of these needed for 1 line prologue. */ -struct Line_Table_File_Entry_s { - Dwarf_Small *lte_filename; - Dwarf_Unsigned lte_directory_index; - Dwarf_Unsigned lte_last_modification_time; - Dwarf_Unsigned lte_length_of_file; -}; - -/* Data picked up from the line table prologue for a single -CU. */ -struct Line_Table_Prefix_s { - - /* pf_total_length is the value of the length field for the line - table of this CU. So it does not count the length of itself (the - length value) for consistency with the say lenghts recorded in - DWARF2/3. */ - Dwarf_Unsigned pf_total_length; - - /* Length of the initial length field itself. */ - Dwarf_Half pf_length_field_length; - - /* The version is 2 for DWARF2, 3 for DWARF3 */ - Dwarf_Half pf_version; - - Dwarf_Unsigned pf_prologue_length; - Dwarf_Small pf_minimum_instruction_length; - - /* Start and end of this CU line area. pf_line_ptr_start + - pf_total_length + pf_length_field_length == pf_line_ptr_end. - Meaning pf_line_ptr_start is before the length info. */ - Dwarf_Small *pf_line_ptr_start; - Dwarf_Small *pf_line_ptr_end; - - /* Used to check that decoding of the line prologue is done right. */ - Dwarf_Small *pf_line_prologue_start; - - Dwarf_Small pf_default_is_stmt; - Dwarf_Sbyte pf_line_base; - Dwarf_Small pf_line_range; - - /* Highest std opcode (+1). */ - Dwarf_Small pf_opcode_base; - - /* pf_opcode_base -1 entries (each a count, normally the value of - each entry is 0 or 1). */ - Dwarf_Small *pf_opcode_length_table; - - Dwarf_Unsigned pf_include_directories_count; - /* Array of pointers to dir strings. pf_include_directories_count - entriesin the array. */ - Dwarf_Small **pf_include_directories; - - /* Count of entries in line_table_file_entries array. */ - Dwarf_Unsigned pf_files_count; - struct Line_Table_File_Entry_s *pf_line_table_file_entries; - - /* The number to treat as standard ops. This is a special - accomodation of gcc using the new standard opcodes but not - updating the version number. It's legal dwarf2, but much better - for the user to understand as dwarf3 when 'it looks ok'. */ - Dwarf_Bool pf_std_op_count; - -}; - -void dwarf_init_line_table_prefix(struct Line_Table_Prefix_s *pf); -void dwarf_free_line_table_prefix(struct Line_Table_Prefix_s *pf); - -int dwarf_read_line_table_prefix(Dwarf_Debug dbg, - Dwarf_Small * data_start, - Dwarf_Unsigned data_length, - Dwarf_Small ** updated_data_start_out, - struct Line_Table_Prefix_s *prefix_out, - /* The following 2 arguments are solely for warning users - * when there is a surprising 'gap' in the .debug_line info. */ - Dwarf_Small ** bogus_bytes_ptr, - Dwarf_Unsigned * bogus_bytes_count, - Dwarf_Error * err, - int * err_count_out); diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_line2.c b/usr/src/tools/ctf/dwarf/common/dwarf_line2.c deleted file mode 100644 index 634b848167..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_line2.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - - Copyright (C) 2000,2002,2004,2005,2006 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2008-2010 David Anderson, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - -/* This source file used for SGI-IRIX rqs processing. - Unused otherwise. -*/ - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include "dwarf_line.h" - -/* - Return DW_DLV_OK or, if error, - DW_DLV_ERROR. - - Thru pointers, return 2 arrays and a count - for rqs. -*/ -int -_dwarf_line_address_offsets(Dwarf_Debug dbg, - Dwarf_Die die, - Dwarf_Addr ** addrs, - Dwarf_Off ** offs, - Dwarf_Unsigned * returncount, - Dwarf_Error * err) -{ - Dwarf_Addr *laddrs; - Dwarf_Off *loffsets; - Dwarf_Signed lcount; - Dwarf_Signed i; - int res; - Dwarf_Line *linebuf; - - res = _dwarf_internal_srclines(die, &linebuf, &lcount, /* addrlist= - */ true, - /* linelist= */ false, err); - if (res != DW_DLV_OK) { - return res; - } - laddrs = (Dwarf_Addr *) - _dwarf_get_alloc(dbg, DW_DLA_ADDR, lcount); - if (laddrs == NULL) { - dwarf_srclines_dealloc(dbg, linebuf, lcount); - _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - loffsets = (Dwarf_Off *) - _dwarf_get_alloc(dbg, DW_DLA_ADDR, lcount); - if (loffsets == NULL) { - dwarf_srclines_dealloc(dbg, linebuf, lcount); - /* We already allocated what laddrs points at, so we'e better - deallocate that space since we are not going to return the - pointer to the caller. */ - dwarf_dealloc(dbg, laddrs, DW_DLA_ADDR); - _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - for (i = 0; i < lcount; i++) { - laddrs[i] = linebuf[i]->li_address; - loffsets[i] = linebuf[i]->li_addr_line.li_offset; - } - dwarf_srclines_dealloc(dbg, linebuf, lcount); - *returncount = lcount; - *offs = loffsets; - *addrs = laddrs; - return DW_DLV_OK; -} - -/* - It's impossible for callers of dwarf_srclines() to get to and - free all the resources (in particular, the li_context and its - lc_file_entries). - So this function, new July 2005, does it. -*/ diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_loc.c b/usr/src/tools/ctf/dwarf/common/dwarf_loc.c deleted file mode 100644 index f28b27b630..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_loc.c +++ /dev/null @@ -1,1073 +0,0 @@ -/* - - Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the Crittenden Lane address. -*/ - - - - -#include "config.h" -#include "dwarf_incl.h" -#include "dwarf_loc.h" -#include /* for debugging only. */ -#include - -/* - Given a Dwarf_Block that represents a location expression, - this function returns a pointer to a Dwarf_Locdesc struct - that has its ld_cents field set to the number of location - operators in the block, and its ld_s field pointing to a - contiguous block of Dwarf_Loc structs. However, the - ld_lopc and ld_hipc values are uninitialized. Returns - NULL on error. This function assumes that the length of - the block is greater than 0. Zero length location expressions - to represent variables that have been optimized away are - handled in the calling function. -*/ -static Dwarf_Locdesc * -_dwarf_get_locdesc(Dwarf_Debug dbg, - Dwarf_Block * loc_block, - Dwarf_Half address_size, - Dwarf_Addr lowpc, - Dwarf_Addr highpc, - Dwarf_Error * error) -{ - /* Size of the block containing the location expression. */ - Dwarf_Unsigned loc_len = 0; - - /* Sweeps the block containing the location expression. */ - Dwarf_Small *loc_ptr = 0; - - /* Current location operator. */ - Dwarf_Small atom = 0; - - /* Offset of current operator from start of block. */ - Dwarf_Unsigned offset = 0; - - /* Operands of current location operator. */ - Dwarf_Unsigned operand1, operand2; - - /* Used to chain the Dwarf_Loc_Chain_s structs. */ - Dwarf_Loc_Chain curr_loc = NULL; - Dwarf_Loc_Chain prev_loc = NULL; - Dwarf_Loc_Chain head_loc = NULL; - - /* Count of the number of location operators. */ - Dwarf_Unsigned op_count = 0; - - /* Contiguous block of Dwarf_Loc's for Dwarf_Locdesc. */ - Dwarf_Loc *block_loc = 0; - - /* Dwarf_Locdesc pointer to be returned. */ - Dwarf_Locdesc *locdesc = 0; - - Dwarf_Word leb128_length = 0; - Dwarf_Unsigned i = 0; - - /* ***** BEGIN CODE ***** */ - - loc_len = loc_block->bl_len; - loc_ptr = loc_block->bl_data; - - offset = 0; - op_count = 0; - while (offset < loc_len) { - - operand1 = 0; - operand2 = 0; - op_count++; - - atom = *(Dwarf_Small *) loc_ptr; - loc_ptr++; - offset++; - - curr_loc = - (Dwarf_Loc_Chain) _dwarf_get_alloc(dbg, DW_DLA_LOC_CHAIN, - 1); - if (curr_loc == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (NULL); - } - curr_loc->lc_offset = offset; - curr_loc->lc_atom = atom; - switch (atom) { - - case DW_OP_reg0: - case DW_OP_reg1: - case DW_OP_reg2: - case DW_OP_reg3: - case DW_OP_reg4: - case DW_OP_reg5: - case DW_OP_reg6: - case DW_OP_reg7: - case DW_OP_reg8: - case DW_OP_reg9: - case DW_OP_reg10: - case DW_OP_reg11: - case DW_OP_reg12: - case DW_OP_reg13: - case DW_OP_reg14: - case DW_OP_reg15: - case DW_OP_reg16: - case DW_OP_reg17: - case DW_OP_reg18: - case DW_OP_reg19: - case DW_OP_reg20: - case DW_OP_reg21: - case DW_OP_reg22: - case DW_OP_reg23: - case DW_OP_reg24: - case DW_OP_reg25: - case DW_OP_reg26: - case DW_OP_reg27: - case DW_OP_reg28: - case DW_OP_reg29: - case DW_OP_reg30: - case DW_OP_reg31: - break; - - case DW_OP_regx: - operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - break; - - case DW_OP_lit0: - case DW_OP_lit1: - case DW_OP_lit2: - case DW_OP_lit3: - case DW_OP_lit4: - case DW_OP_lit5: - case DW_OP_lit6: - case DW_OP_lit7: - case DW_OP_lit8: - case DW_OP_lit9: - case DW_OP_lit10: - case DW_OP_lit11: - case DW_OP_lit12: - case DW_OP_lit13: - case DW_OP_lit14: - case DW_OP_lit15: - case DW_OP_lit16: - case DW_OP_lit17: - case DW_OP_lit18: - case DW_OP_lit19: - case DW_OP_lit20: - case DW_OP_lit21: - case DW_OP_lit22: - case DW_OP_lit23: - case DW_OP_lit24: - case DW_OP_lit25: - case DW_OP_lit26: - case DW_OP_lit27: - case DW_OP_lit28: - case DW_OP_lit29: - case DW_OP_lit30: - case DW_OP_lit31: - operand1 = atom - DW_OP_lit0; - break; - - case DW_OP_addr: - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, - loc_ptr, address_size); - loc_ptr += address_size; - offset += address_size; - break; - - case DW_OP_const1u: - operand1 = *(Dwarf_Small *) loc_ptr; - loc_ptr = loc_ptr + 1; - offset = offset + 1; - break; - - case DW_OP_const1s: - operand1 = *(Dwarf_Sbyte *) loc_ptr; - SIGN_EXTEND(operand1,1); - loc_ptr = loc_ptr + 1; - offset = offset + 1; - break; - - case DW_OP_const2u: - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2); - loc_ptr = loc_ptr + 2; - offset = offset + 2; - break; - - case DW_OP_const2s: - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2); - SIGN_EXTEND(operand1,2); - loc_ptr = loc_ptr + 2; - offset = offset + 2; - break; - - case DW_OP_const4u: - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4); - loc_ptr = loc_ptr + 4; - offset = offset + 4; - break; - - case DW_OP_const4s: - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4); - SIGN_EXTEND(operand1,4); - loc_ptr = loc_ptr + 4; - offset = offset + 4; - break; - - case DW_OP_const8u: - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 8); - loc_ptr = loc_ptr + 8; - offset = offset + 8; - break; - - case DW_OP_const8s: - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 8); - loc_ptr = loc_ptr + 8; - offset = offset + 8; - break; - - case DW_OP_constu: - operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - break; - - case DW_OP_consts: - operand1 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - break; - - case DW_OP_fbreg: - operand1 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - break; - - case DW_OP_breg0: - case DW_OP_breg1: - case DW_OP_breg2: - case DW_OP_breg3: - case DW_OP_breg4: - case DW_OP_breg5: - case DW_OP_breg6: - case DW_OP_breg7: - case DW_OP_breg8: - case DW_OP_breg9: - case DW_OP_breg10: - case DW_OP_breg11: - case DW_OP_breg12: - case DW_OP_breg13: - case DW_OP_breg14: - case DW_OP_breg15: - case DW_OP_breg16: - case DW_OP_breg17: - case DW_OP_breg18: - case DW_OP_breg19: - case DW_OP_breg20: - case DW_OP_breg21: - case DW_OP_breg22: - case DW_OP_breg23: - case DW_OP_breg24: - case DW_OP_breg25: - case DW_OP_breg26: - case DW_OP_breg27: - case DW_OP_breg28: - case DW_OP_breg29: - case DW_OP_breg30: - case DW_OP_breg31: - operand1 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - break; - - case DW_OP_bregx: - /* uleb reg num followed by sleb offset */ - operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - - operand2 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - break; - - case DW_OP_dup: - case DW_OP_drop: - break; - - case DW_OP_pick: - operand1 = *(Dwarf_Small *) loc_ptr; - loc_ptr = loc_ptr + 1; - offset = offset + 1; - break; - - case DW_OP_over: - case DW_OP_swap: - case DW_OP_rot: - case DW_OP_deref: - break; - - case DW_OP_deref_size: - operand1 = *(Dwarf_Small *) loc_ptr; - loc_ptr = loc_ptr + 1; - offset = offset + 1; - break; - - case DW_OP_xderef: - break; - - case DW_OP_xderef_size: - operand1 = *(Dwarf_Small *) loc_ptr; - loc_ptr = loc_ptr + 1; - offset = offset + 1; - break; - - case DW_OP_abs: - case DW_OP_and: - case DW_OP_div: - case DW_OP_minus: - case DW_OP_mod: - case DW_OP_mul: - case DW_OP_neg: - case DW_OP_not: - case DW_OP_or: - case DW_OP_plus: - break; - - case DW_OP_plus_uconst: - operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - break; - - case DW_OP_shl: - case DW_OP_shr: - case DW_OP_shra: - case DW_OP_xor: - break; - - case DW_OP_le: - case DW_OP_ge: - case DW_OP_eq: - case DW_OP_lt: - case DW_OP_gt: - case DW_OP_ne: - break; - - case DW_OP_skip: - case DW_OP_bra: - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2); - loc_ptr = loc_ptr + 2; - offset = offset + 2; - break; - - case DW_OP_piece: - operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - break; - - case DW_OP_nop: - break; - case DW_OP_push_object_address: /* DWARF3 */ - break; - case DW_OP_call2: /* DWARF3 */ - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2); - loc_ptr = loc_ptr + 2; - offset = offset + 2; - break; - - case DW_OP_call4: /* DWARF3 */ - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4); - loc_ptr = loc_ptr + 4; - offset = offset + 4; - break; - case DW_OP_call_ref: /* DWARF3 */ - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, - dbg->de_length_size); - loc_ptr = loc_ptr + dbg->de_length_size; - offset = offset + dbg->de_length_size; - break; - - case DW_OP_form_tls_address: /* DWARF3f */ - break; - case DW_OP_call_frame_cfa: /* DWARF3f */ - break; - case DW_OP_bit_piece: /* DWARF3f */ - /* uleb size in bits followed by uleb offset in bits */ - operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - - operand2 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - break; - case DW_OP_implicit_value: /* DWARF4 */ - /* uleb length of value bytes followed by that - number of bytes of the value. */ - operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - - /* Second operand is block of 'operand1' bytes of stuff. */ - /* This using the second operand as a pointer - is quite ugly. */ - /* This gets an ugly compiler warning. Sorry. */ - operand2 = (Dwarf_Unsigned)(uintptr_t)loc_ptr; - offset = offset + operand1; - loc_ptr = loc_ptr + operand1; - break; - case DW_OP_stack_value: /* DWARF4 */ - break; - - - default: - _dwarf_error(dbg, error, DW_DLE_LOC_EXPR_BAD); - return (NULL); - } - - - curr_loc->lc_number = operand1; - curr_loc->lc_number2 = operand2; - - if (head_loc == NULL) - head_loc = prev_loc = curr_loc; - else { - prev_loc->lc_next = curr_loc; - prev_loc = curr_loc; - } - } - - block_loc = - (Dwarf_Loc *) _dwarf_get_alloc(dbg, DW_DLA_LOC_BLOCK, op_count); - if (block_loc == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (NULL); - } - - curr_loc = head_loc; - for (i = 0; i < op_count; i++) { - (block_loc + i)->lr_atom = curr_loc->lc_atom; - (block_loc + i)->lr_number = curr_loc->lc_number; - (block_loc + i)->lr_number2 = curr_loc->lc_number2; - (block_loc + i)->lr_offset = curr_loc->lc_offset; - - prev_loc = curr_loc; - curr_loc = curr_loc->lc_next; - dwarf_dealloc(dbg, prev_loc, DW_DLA_LOC_CHAIN); - } - - locdesc = - (Dwarf_Locdesc *) _dwarf_get_alloc(dbg, DW_DLA_LOCDESC, 1); - if (locdesc == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (NULL); - } - - locdesc->ld_cents = op_count; - locdesc->ld_s = block_loc; - locdesc->ld_from_loclist = loc_block->bl_from_loclist; - locdesc->ld_section_offset = loc_block->bl_section_offset; - locdesc->ld_lopc = lowpc; - locdesc->ld_hipc = highpc; - - return (locdesc); -} - -/* Using a loclist offset to get the in-memory - address of .debug_loc data to read, returns the loclist - 'header' info in return_block. -*/ - -#define MAX_ADDR ((address_size == 8)?0xffffffffffffffffULL:0xffffffff) - -static int -_dwarf_read_loc_section(Dwarf_Debug dbg, - Dwarf_Block * return_block, - Dwarf_Addr * lowpc, Dwarf_Addr * hipc, - Dwarf_Off sec_offset, - Dwarf_Half address_size, - Dwarf_Error * error) -{ - Dwarf_Small *beg = dbg->de_debug_loc.dss_data + sec_offset; - - Dwarf_Addr start_addr = 0; - Dwarf_Addr end_addr = 0; - Dwarf_Half exprblock_size = 0; - Dwarf_Unsigned exprblock_off = - 2 * address_size + sizeof(Dwarf_Half); - - if (sec_offset >= dbg->de_debug_loc.dss_size) { - /* We're at the end. No more present. */ - return DW_DLV_NO_ENTRY; - } - - /* If it goes past end, error */ - if (exprblock_off > dbg->de_debug_loc.dss_size) { - _dwarf_error(NULL, error, DW_DLE_DEBUG_LOC_SECTION_SHORT); - return DW_DLV_ERROR; - } - - READ_UNALIGNED(dbg, start_addr, Dwarf_Addr, beg, address_size); - READ_UNALIGNED(dbg, end_addr, Dwarf_Addr, - beg + address_size, address_size); - if (start_addr == 0 && end_addr == 0) { - /* If start_addr and end_addr are 0, it's the end and no - exprblock_size field follows. */ - exprblock_size = 0; - exprblock_off -= sizeof(Dwarf_Half); - } else if (start_addr == MAX_ADDR) { - /* end address is a base address, no exprblock_size field here - either */ - exprblock_size = 0; - exprblock_off -= sizeof(Dwarf_Half); - } else { - - READ_UNALIGNED(dbg, exprblock_size, Dwarf_Half, - beg + 2 * address_size, sizeof(Dwarf_Half)); - /* exprblock_size can be zero, means no expression */ - if ((exprblock_off + exprblock_size) > dbg->de_debug_loc.dss_size) { - _dwarf_error(NULL, error, DW_DLE_DEBUG_LOC_SECTION_SHORT); - return DW_DLV_ERROR; - } - } -#undef MAX_ADDR - *lowpc = start_addr; - *hipc = end_addr; - - return_block->bl_len = exprblock_size; - return_block->bl_from_loclist = 1; - return_block->bl_data = beg + exprblock_off; - return_block->bl_section_offset = - ((Dwarf_Small *) return_block->bl_data) - dbg->de_debug_loc.dss_data; - - return DW_DLV_OK; - -} -static int -_dwarf_get_loclist_count(Dwarf_Debug dbg, - Dwarf_Off loclist_offset, - Dwarf_Half address_size, - int *loclist_count, Dwarf_Error * error) -{ - int count = 0; - Dwarf_Off offset = loclist_offset; - - - for (;;) { - Dwarf_Block b; - Dwarf_Addr lowpc; - Dwarf_Addr highpc; - int res = _dwarf_read_loc_section(dbg, &b, - &lowpc, &highpc, - offset, address_size,error); - - if (res != DW_DLV_OK) { - return res; - } - offset = b.bl_len + b.bl_section_offset; - if (lowpc == 0 && highpc == 0) { - break; - } - count++; - } - *loclist_count = count; - return DW_DLV_OK; -} - -/* Helper routine to avoid code duplication. -*/ -static int -_dwarf_setup_loc(Dwarf_Attribute attr, - Dwarf_Debug * dbg_ret, - Dwarf_CU_Context *cucontext_ret, - Dwarf_Half * form_ret, Dwarf_Error * error) -{ - Dwarf_Debug dbg = 0; - Dwarf_Half form = 0; - int blkres = DW_DLV_ERROR; - - if (attr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); - return (DW_DLV_ERROR); - } - if (attr->ar_cu_context == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); - return (DW_DLV_ERROR); - } - *cucontext_ret = attr->ar_cu_context; - - dbg = attr->ar_cu_context->cc_dbg; - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); - return (DW_DLV_ERROR); - } - *dbg_ret = dbg; - blkres = dwarf_whatform(attr, &form, error); - if (blkres != DW_DLV_OK) { - _dwarf_error(dbg, error, DW_DLE_LOC_EXPR_BAD); - return blkres; - } - *form_ret = form; - return DW_DLV_OK; -} - -/* Helper routine to avoid code duplication. -*/ -static int -_dwarf_get_loclist_header_start(Dwarf_Debug dbg, - Dwarf_Attribute attr, - Dwarf_Unsigned * loclist_offset, - Dwarf_Error * error) -{ - int blkres = dwarf_formudata(attr, loclist_offset, error); - if (blkres != DW_DLV_OK) { - return (blkres); - } - - if (!dbg->de_debug_loc.dss_data) { - int secload = _dwarf_load_section(dbg, &dbg->de_debug_loc,error); - if (secload != DW_DLV_OK) { - return secload; - } - } - return DW_DLV_OK; -} - -/* When llbuf (see dwarf_loclist_n) is partially set up - and an error is encountered, tear it down as it - won't be used. -*/ -static void -_dwarf_cleanup_llbuf(Dwarf_Debug dbg, Dwarf_Locdesc ** llbuf, int count) -{ - int i; - for (i = 0; i < count; ++i) { - dwarf_dealloc(dbg, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK); - dwarf_dealloc(dbg, llbuf[i], DW_DLA_LOCDESC); - } - dwarf_dealloc(dbg, llbuf, DW_DLA_LIST); -} - -/* - Handles simple location entries and loclists. - Returns all the Locdesc's thru llbuf. - -*/ -int -dwarf_loclist_n(Dwarf_Attribute attr, - Dwarf_Locdesc *** llbuf_out, - Dwarf_Signed * listlen_out, Dwarf_Error * error) -{ - Dwarf_Debug dbg; - - /* - Dwarf_Attribute that describes the DW_AT_location in die, if - present. */ - Dwarf_Attribute loc_attr = attr; - - /* Dwarf_Block that describes a single location expression. */ - Dwarf_Block loc_block; - - /* A pointer to the current Dwarf_Locdesc read. */ - Dwarf_Locdesc *locdesc = 0; - - Dwarf_Half form = 0; - Dwarf_Addr lowpc = 0; - Dwarf_Addr highpc = 0; - Dwarf_Signed listlen = 0; - Dwarf_Locdesc **llbuf = 0; - Dwarf_CU_Context cucontext = 0; - unsigned address_size = 0; - - int blkres = DW_DLV_ERROR; - int setup_res = DW_DLV_ERROR; - - /* ***** BEGIN CODE ***** */ - setup_res = _dwarf_setup_loc(attr, &dbg,&cucontext, &form, error); - if (setup_res != DW_DLV_OK) { - return setup_res; - } - address_size = cucontext->cc_address_size; - /* If this is a form_block then it's a location expression. If it's - DW_FORM_data4 or DW_FORM_data8 it's a loclist offset */ - if (((cucontext->cc_version_stamp == CURRENT_VERSION_STAMP || - cucontext->cc_version_stamp == CURRENT_VERSION_STAMP3) && - (form == DW_FORM_data4 || form == DW_FORM_data8)) || - (cucontext->cc_version_stamp == CURRENT_VERSION_STAMP4 && - form == DW_FORM_sec_offset)) - { - - - /* A reference to .debug_loc, with an offset in .debug_loc of a - loclist */ - Dwarf_Unsigned loclist_offset = 0; - int off_res = DW_DLV_ERROR; - int count_res = DW_DLV_ERROR; - int loclist_count; - int lli; - - off_res = _dwarf_get_loclist_header_start(dbg, - attr, &loclist_offset, - error); - if (off_res != DW_DLV_OK) { - return off_res; - } - count_res = _dwarf_get_loclist_count(dbg, loclist_offset, - address_size, - &loclist_count, error); - listlen = loclist_count; - if (count_res != DW_DLV_OK) { - return count_res; - } - if (loclist_count == 0) { - return DW_DLV_NO_ENTRY; - } - - llbuf = (Dwarf_Locdesc **) - _dwarf_get_alloc(dbg, DW_DLA_LIST, loclist_count); - if (!llbuf) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - for (lli = 0; lli < loclist_count; ++lli) { - blkres = _dwarf_read_loc_section(dbg, &loc_block, - &lowpc, - &highpc, - loclist_offset, - address_size, - error); - if (blkres != DW_DLV_OK) { - _dwarf_cleanup_llbuf(dbg, llbuf, lli); - return (blkres); - } - locdesc = _dwarf_get_locdesc(dbg, &loc_block, - address_size, - lowpc, highpc, error); - if (locdesc == NULL) { - _dwarf_cleanup_llbuf(dbg, llbuf, lli); - /* low level error already set: let it be passed back */ - return (DW_DLV_ERROR); - } - llbuf[lli] = locdesc; - - /* Now get to next loclist entry offset. */ - loclist_offset = loc_block.bl_section_offset + - loc_block.bl_len; - } - - - } else { - Dwarf_Block *tblock = 0; - - blkres = dwarf_formblock(loc_attr, &tblock, error); - if (blkres != DW_DLV_OK) { - return (blkres); - } - loc_block = *tblock; - /* We copied tblock contents to the stack var, so can dealloc - tblock now. Avoids leaks. */ - dwarf_dealloc(dbg, tblock, DW_DLA_BLOCK); - listlen = 1; /* One by definition of a location entry. */ - lowpc = 0; /* HACK */ - highpc = (Dwarf_Unsigned) (-1LL); /* HACK */ - - /* An empty location description (block length 0) means the - code generator emitted no variable, the variable was not - generated, it was unused or perhaps never tested after being - set. Dwarf2, section 2.4.1 In other words, it is not an - error, and we don't test for block length 0 specially here. */ - locdesc = _dwarf_get_locdesc(dbg, &loc_block, - address_size, - lowpc, highpc, error); - if (locdesc == NULL) { - /* low level error already set: let it be passed back */ - return (DW_DLV_ERROR); - } - llbuf = (Dwarf_Locdesc **) - _dwarf_get_alloc(dbg, DW_DLA_LIST, listlen); - if (!llbuf) { - /* Free the locdesc we allocated but won't use. */ - dwarf_dealloc(dbg, locdesc, DW_DLA_LOCDESC); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - llbuf[0] = locdesc; - } - - *llbuf_out = llbuf; - *listlen_out = listlen; - return (DW_DLV_OK); -} - - -/* - Handles only a location expression. - If called on a loclist, just returns one of those. - Cannot not handle a real loclist. - It returns the location expression as a loclist with - a single entry. - See dwarf_loclist_n() which handles any number - of location list entries. - - This is the original definition, and it simply - does not work for loclists. Kept for compatibility. -*/ -int -dwarf_loclist(Dwarf_Attribute attr, - Dwarf_Locdesc ** llbuf, - Dwarf_Signed * listlen, Dwarf_Error * error) -{ - Dwarf_Debug dbg; - - /* Dwarf_Attribute that describes the DW_AT_location in die, if - present. */ - Dwarf_Attribute loc_attr = attr; - - /* Dwarf_Block that describes a single location expression. */ - Dwarf_Block loc_block; - - /* A pointer to the current Dwarf_Locdesc read. */ - Dwarf_Locdesc *locdesc = 0; - - Dwarf_Half form = 0; - Dwarf_Addr lowpc = 0; - Dwarf_Addr highpc = 0; - Dwarf_CU_Context cucontext = 0; - unsigned address_size = 0; - - int blkres = DW_DLV_ERROR; - int setup_res = DW_DLV_ERROR; - - /* ***** BEGIN CODE ***** */ - setup_res = _dwarf_setup_loc(attr, &dbg, &cucontext, &form, error); - if (setup_res != DW_DLV_OK) { - return setup_res; - } - address_size = cucontext->cc_address_size; - /* If this is a form_block then it's a location expression. If it's - DW_FORM_data4 or DW_FORM_data8 it's a loclist offset */ - if (((cucontext->cc_version_stamp == CURRENT_VERSION_STAMP || - cucontext->cc_version_stamp == CURRENT_VERSION_STAMP3) && - (form == DW_FORM_data4 || form == DW_FORM_data8)) || - (cucontext->cc_version_stamp == CURRENT_VERSION_STAMP4 && - form == DW_FORM_sec_offset)) - { - - /* A reference to .debug_loc, with an offset in .debug_loc of a - loclist */ - Dwarf_Unsigned loclist_offset = 0; - int off_res = DW_DLV_ERROR; - - off_res = _dwarf_get_loclist_header_start(dbg, - attr, &loclist_offset, - error); - if (off_res != DW_DLV_OK) { - return off_res; - } - - /* With dwarf_loclist, just read a single entry */ - blkres = _dwarf_read_loc_section(dbg, &loc_block, - &lowpc, - &highpc, - loclist_offset, - address_size, - error); - if (blkres != DW_DLV_OK) { - return (blkres); - } - } else { - Dwarf_Block *tblock = 0; - - blkres = dwarf_formblock(loc_attr, &tblock, error); - if (blkres != DW_DLV_OK) { - return (blkres); - } - loc_block = *tblock; - /* We copied tblock contents to the stack var, so can dealloc - tblock now. Avoids leaks. */ - dwarf_dealloc(dbg, tblock, DW_DLA_BLOCK); - lowpc = 0; /* HACK */ - highpc = (Dwarf_Unsigned) (-1LL); /* HACK */ - } - - /* An empty location description (block length 0) means the code - generator emitted no variable, the variable was not generated, - it was unused or perhaps never tested after being set. Dwarf2, - section 2.4.1 In other words, it is not an error, and we don't - test for block length 0 specially here. - See *dwarf_loclist_n() which handles the general case, this case - handles only a single location expression. */ - locdesc = _dwarf_get_locdesc(dbg, &loc_block, - address_size, - lowpc, highpc, error); - if (locdesc == NULL) { - /* low level error already set: let it be passed back */ - return (DW_DLV_ERROR); - } - - *llbuf = locdesc; - *listlen = 1; - return (DW_DLV_OK); -} - - - -/* - Handles only a location expression. - It returns the location expression as a loclist with - a single entry. - - Usable to access dwarf expressions from any source, but - specifically from - DW_CFA_def_cfa_expression - DW_CFA_expression - DW_CFA_val_expression - - expression_in must point to a valid dwarf expression - set of bytes of length expression_length. Not - a DW_FORM_block*, just the expression bytes. - - If the address_size != de_pointer_size this will not work - right. FIXME. -*/ -int -dwarf_loclist_from_expr(Dwarf_Debug dbg, - Dwarf_Ptr expression_in, - Dwarf_Unsigned expression_length, - Dwarf_Locdesc ** llbuf, - Dwarf_Signed * listlen, Dwarf_Error * error) -{ - int res = 0; - Dwarf_Half addr_size = dbg->de_pointer_size; - res = dwarf_loclist_from_expr_a(dbg,expression_in, - expression_length, addr_size,llbuf,listlen,error); - return res; -} -/* New April 27 2009. Adding addr_size argument for the rare - * cases where an object has CUs with a different address_size. */ -int -dwarf_loclist_from_expr_a(Dwarf_Debug dbg, - Dwarf_Ptr expression_in, - Dwarf_Unsigned expression_length, - Dwarf_Half addr_size, - Dwarf_Locdesc ** llbuf, - Dwarf_Signed * listlen, Dwarf_Error * error) -{ - /* Dwarf_Block that describes a single location expression. */ - Dwarf_Block loc_block; - - /* A pointer to the current Dwarf_Locdesc read. */ - Dwarf_Locdesc *locdesc = 0; - Dwarf_Addr lowpc = 0; - Dwarf_Addr highpc = (Dwarf_Unsigned) (-1LL); - - memset(&loc_block,0,sizeof(loc_block)); - loc_block.bl_len = expression_length; - loc_block.bl_data = expression_in; - loc_block.bl_from_loclist = 0; /* Not from loclist. */ - loc_block.bl_section_offset = 0; /* Fake. Not meaningful. */ - - /* An empty location description (block length 0) means the code - generator emitted no variable, the variable was not generated, - it was unused or perhaps never tested after being set. Dwarf2, - section 2.4.1 In other words, it is not an error, and we don't - test for block length 0 specially here. */ - locdesc = _dwarf_get_locdesc(dbg, &loc_block, - addr_size,lowpc, highpc, error); - if (locdesc == NULL) { - /* low level error already set: let it be passed back */ - return (DW_DLV_ERROR); - } - - *llbuf = locdesc; - *listlen = 1; - return (DW_DLV_OK); -} - -/* Usable to read a single loclist or to read a block of them - or to read an entire section's loclists. - - It's broken because it's not safe to read a loclist entry - when we do not know the address size (in any object where - address size can vary by compilation unit). -*/ - - /*ARGSUSED*/ int -dwarf_get_loclist_entry(Dwarf_Debug dbg, - Dwarf_Unsigned offset, - Dwarf_Addr * hipc_offset, - Dwarf_Addr * lopc_offset, - Dwarf_Ptr * data, - Dwarf_Unsigned * entry_len, - Dwarf_Unsigned * next_entry, - Dwarf_Error * error) -{ - Dwarf_Block b; - Dwarf_Addr lowpc = 0; - Dwarf_Addr highpc = 0; - Dwarf_Half address_size = 0; - int res = DW_DLV_ERROR; - - if (!dbg->de_debug_loc.dss_data) { - int secload = _dwarf_load_section(dbg, &dbg->de_debug_loc,error); - if (secload != DW_DLV_OK) { - return secload; - } - } - - /* FIXME: address_size is not necessarily the same in every frame. */ - address_size = dbg->de_pointer_size; - res = _dwarf_read_loc_section(dbg, - &b, &lowpc, &highpc, offset, - address_size,error); - if (res != DW_DLV_OK) { - return res; - } - *hipc_offset = highpc; - *lopc_offset = lowpc; - *entry_len = b.bl_len; - *data = b.bl_data; - *next_entry = b.bl_len + b.bl_section_offset; - return DW_DLV_OK; -} - - diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_loc.h b/usr/src/tools/ctf/dwarf/common/dwarf_loc.h deleted file mode 100644 index 685d199f29..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_loc.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - - Copyright (C) 2000, 2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -typedef struct Dwarf_Loc_Chain_s *Dwarf_Loc_Chain; - -struct Dwarf_Loc_Chain_s { - Dwarf_Small lc_atom; - Dwarf_Unsigned lc_number; - Dwarf_Unsigned lc_number2; - Dwarf_Unsigned lc_offset; - Dwarf_Loc_Chain lc_next; -}; diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_macro.c b/usr/src/tools/ctf/dwarf/common/dwarf_macro.c deleted file mode 100644 index e1ff976d8c..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_macro.c +++ /dev/null @@ -1,467 +0,0 @@ -/* - - Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the Crittenden Lane address. -*/ - - - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include -#ifdef HAVE_STDLIB_H -#include -#endif /* HAVE_STDLIB_H */ -#include "dwarf_macro.h" - - -#define LEFTPAREN '(' -#define RIGHTPAREN ')' -#define SPACE ' ' - -/* - Given the dwarf macro string, return a pointer to - the value. Returns pointer to 0 byte at end of string - if no value found (meaning the value is the empty string). - - Only understands well-formed dwarf macinfo strings. -*/ -char * -dwarf_find_macro_value_start(char *str) -{ - char *lcp; - int funclike = 0; - - for (lcp = str; *lcp; ++lcp) { - switch (*lcp) { - case LEFTPAREN: - funclike = 1; - break; - case RIGHTPAREN: - /* lcp+1 must be a space, and following char is the value */ - return lcp + 2; - case SPACE: - /* we allow extraneous spaces inside macro parameter ** - list, just in case... This is not really needed. */ - if (!funclike) { - return lcp + 1; - } - break; - } - } - /* never found value: returns pointer to the 0 byte at end of - string */ - return lcp; - -} - - -/* - Try to keep fileindex correct in every Macro_Details - record by tracking file starts and ends. - Uses high water mark: space reused, not freed. - Presumption is that this makes sense for most uses. - STARTERMAX is set so that the array need not be expanded for - most files: it is the initial include file depth. -*/ -struct macro_stack_s { - Dwarf_Signed *st_base; - long max; - long next_to_use; - int was_fault; -}; - -static void _dwarf_reset_index_macro_stack(struct macro_stack_s *ms); -static void -free_macro_stack(Dwarf_Debug dbg, struct macro_stack_s *ms) -{ - dwarf_dealloc(dbg,ms->st_base,DW_DLA_STRING); - _dwarf_reset_index_macro_stack(ms); -} - -#define STARTERMAX 10 -static void -_dwarf_reset_index_macro_stack(struct macro_stack_s *ms) -{ - ms->st_base = 0; - ms->max = 0; - ms->next_to_use = 0; - ms->was_fault = 0; -} -static int -_dwarf_macro_stack_push_index(Dwarf_Debug dbg, Dwarf_Signed indx, - struct macro_stack_s *ms) -{ - Dwarf_Signed *newbase; - - if (ms->next_to_use >= ms->max) { - long new_size; - - if (ms->max == 0) { - ms->max = STARTERMAX; - } - new_size = ms->max * 2; - newbase = - _dwarf_get_alloc(dbg, DW_DLA_STRING, - new_size * sizeof(Dwarf_Signed)); - if (newbase == 0) { - /* just leave the old array in place */ - ms->was_fault = 1; - return DW_DLV_ERROR; - } - if(ms->st_base) { - memcpy(newbase, ms->st_base, - ms->next_to_use * sizeof(Dwarf_Signed)); - dwarf_dealloc(dbg, ms->st_base, DW_DLA_STRING); - } - ms->st_base = newbase; - ms->max = new_size; - } - ms->st_base[ms->next_to_use] = indx; - ++ms->next_to_use; - return DW_DLV_OK; -} - -static Dwarf_Signed -_dwarf_macro_stack_pop_index(struct macro_stack_s *ms) -{ - if (ms->was_fault) { - return -1; - } - if (ms->next_to_use > 0) { - ms->next_to_use--; - return (ms->st_base[ms->next_to_use]); - } else { - ms->was_fault = 1; - } - return -1; -} - -/* starting at macro_offset in .debug_macinfo, - if maximum_count is 0, treat as if it is infinite. - get macro data up thru - maximum_count entries or the end of a compilation - unit's entries (whichever comes first). -*/ - -int -dwarf_get_macro_details(Dwarf_Debug dbg, - Dwarf_Off macro_offset, - Dwarf_Unsigned maximum_count, - Dwarf_Signed * entry_count, - Dwarf_Macro_Details ** details, - Dwarf_Error * error) -{ - Dwarf_Small *macro_base = 0; - Dwarf_Small *pnext = 0; - Dwarf_Unsigned endloc = 0; - unsigned char uc = 0; - unsigned long depth = 0; - /* By section 6.3.2 Dwarf3 draft 8/9, - the base file should appear as - DW_MACINFO_start_file. See - http://gcc.gnu.org/ml/gcc-bugs/2005-02/msg03442.html - on "[Bug debug/20253] New: [3.4/4.0 regression]: - Macro debug info broken due to lexer change" for how - gcc is broken in some versions. We no longer use - depth as a stopping point, it's not needed as a - stopping point anyway. */ - int res = 0; - /* count space used by strings */ - unsigned long str_space = 0; - int done = 0; - unsigned long space_needed = 0; - unsigned long string_offset = 0; - Dwarf_Small *return_data = 0; - Dwarf_Small *pdata = 0; - unsigned long final_count = 0; - Dwarf_Signed fileindex = -1; - Dwarf_Small *latest_str_loc = 0; - struct macro_stack_s msdata; - - unsigned long count = 0; - unsigned long max_count = (unsigned long) maximum_count; - - _dwarf_reset_index_macro_stack(&msdata); - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_DBG_NULL); - free_macro_stack(dbg,&msdata); - return (DW_DLV_ERROR); - } - - res = _dwarf_load_section(dbg, &dbg->de_debug_macinfo,error); - if (res != DW_DLV_OK) { - free_macro_stack(dbg,&msdata); - return res; - } - - macro_base = dbg->de_debug_macinfo.dss_data; - if (macro_base == NULL) { - free_macro_stack(dbg,&msdata); - return (DW_DLV_NO_ENTRY); - } - if (macro_offset >= dbg->de_debug_macinfo.dss_size) { - free_macro_stack(dbg,&msdata); - return (DW_DLV_NO_ENTRY); - } - - pnext = macro_base + macro_offset; - if (maximum_count == 0) { - max_count = ULONG_MAX; - } - - - /* how many entries and how much space will they take? */ - - endloc = (pnext - macro_base); - if (endloc >= dbg->de_debug_macinfo.dss_size) { - if (endloc == dbg->de_debug_macinfo.dss_size) { - /* normal: found last entry */ - free_macro_stack(dbg,&msdata); - return DW_DLV_NO_ENTRY; - } - _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD); - free_macro_stack(dbg,&msdata); - return (DW_DLV_ERROR); - } - for (count = 0; !done && count < max_count; ++count) { - unsigned long slen; - Dwarf_Word len; - - uc = *pnext; - ++pnext; /* get past the type code */ - switch (uc) { - case DW_MACINFO_define: - case DW_MACINFO_undef: - /* line, string */ - case DW_MACINFO_vendor_ext: - /* number, string */ - (void) _dwarf_decode_u_leb128(pnext, &len); - - pnext += len; - if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { - free_macro_stack(dbg,&msdata); - _dwarf_error(dbg, error, - DW_DLE_DEBUG_MACRO_INCONSISTENT); - return (DW_DLV_ERROR); - } - slen = strlen((char *) pnext) + 1; - pnext += slen; - if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { - free_macro_stack(dbg,&msdata); - _dwarf_error(dbg, error, - DW_DLE_DEBUG_MACRO_INCONSISTENT); - return (DW_DLV_ERROR); - } - str_space += slen; - break; - case DW_MACINFO_start_file: - /* line, file index */ - (void) _dwarf_decode_u_leb128(pnext, &len); - pnext += len; - if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { - free_macro_stack(dbg,&msdata); - _dwarf_error(dbg, error, - DW_DLE_DEBUG_MACRO_INCONSISTENT); - return (DW_DLV_ERROR); - } - (void) _dwarf_decode_u_leb128(pnext, &len); - pnext += len; - if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { - free_macro_stack(dbg,&msdata); - _dwarf_error(dbg, error, - DW_DLE_DEBUG_MACRO_INCONSISTENT); - return (DW_DLV_ERROR); - } - ++depth; - break; - - case DW_MACINFO_end_file: - if (--depth == 0) { - /* done = 1; no, do not stop here, at least one gcc had - the wrong depth settings in the gcc 3.4 timeframe. */ - } - break; /* no string or number here */ - case 0: - /* end of cu's entries */ - done = 1; - break; - default: - free_macro_stack(dbg,&msdata); - _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT); - return (DW_DLV_ERROR); - /* bogus macinfo! */ - } - - endloc = (pnext - macro_base); - if (endloc == dbg->de_debug_macinfo.dss_size) { - done = 1; - } else if (endloc > dbg->de_debug_macinfo.dss_size) { - _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD); - free_macro_stack(dbg,&msdata); - return (DW_DLV_ERROR); - } - } - if (count == 0) { - free_macro_stack(dbg,&msdata); - _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INTERNAL_ERR); - return (DW_DLV_ERROR); - } - - /* we have 'count' array entries to allocate and str_space bytes of - string space to provide for. */ - - string_offset = count * sizeof(Dwarf_Macro_Details); - - /* extra 2 not really needed */ - space_needed = string_offset + str_space + 2; - return_data = pdata = - _dwarf_get_alloc(dbg, DW_DLA_STRING, space_needed); - latest_str_loc = pdata + string_offset; - if (pdata == 0) { - free_macro_stack(dbg,&msdata); - _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_MALLOC_SPACE); - return (DW_DLV_ERROR); - } - pnext = macro_base + macro_offset; - - done = 0; - - /* A series ends with a type code of 0. */ - - for (final_count = 0; !done && final_count < count; ++final_count) { - unsigned long slen; - Dwarf_Word len; - Dwarf_Unsigned v1; - Dwarf_Macro_Details *pdmd = (Dwarf_Macro_Details *) (pdata + - (final_count * sizeof (Dwarf_Macro_Details))); - - endloc = (pnext - macro_base); - if (endloc > dbg->de_debug_macinfo.dss_size) { - free_macro_stack(dbg,&msdata); - _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD); - return (DW_DLV_ERROR); - } - uc = *pnext; - pdmd->dmd_offset = (pnext - macro_base); - pdmd->dmd_type = uc; - pdmd->dmd_fileindex = fileindex; - pdmd->dmd_lineno = 0; - pdmd->dmd_macro = 0; - ++pnext; /* get past the type code */ - switch (uc) { - case DW_MACINFO_define: - case DW_MACINFO_undef: - /* line, string */ - case DW_MACINFO_vendor_ext: - /* number, string */ - v1 = _dwarf_decode_u_leb128(pnext, &len); - pdmd->dmd_lineno = v1; - - pnext += len; - if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { - free_macro_stack(dbg,&msdata); - dwarf_dealloc(dbg, return_data, DW_DLA_STRING); - _dwarf_error(dbg, error, - DW_DLE_DEBUG_MACRO_INCONSISTENT); - return (DW_DLV_ERROR); - } - slen = strlen((char *) pnext) + 1; - strcpy((char *) latest_str_loc, (char *) pnext); - pdmd->dmd_macro = (char *) latest_str_loc; - latest_str_loc += slen; - pnext += slen; - if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { - free_macro_stack(dbg,&msdata); - dwarf_dealloc(dbg, return_data, DW_DLA_STRING); - _dwarf_error(dbg, error, - DW_DLE_DEBUG_MACRO_INCONSISTENT); - return (DW_DLV_ERROR); - } - break; - case DW_MACINFO_start_file: - /* Line, file index */ - v1 = _dwarf_decode_u_leb128(pnext, &len); - pdmd->dmd_lineno = v1; - pnext += len; - if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { - free_macro_stack(dbg,&msdata); - dwarf_dealloc(dbg, return_data, DW_DLA_STRING); - _dwarf_error(dbg, error, - DW_DLE_DEBUG_MACRO_INCONSISTENT); - return (DW_DLV_ERROR); - } - v1 = _dwarf_decode_u_leb128(pnext, &len); - pdmd->dmd_fileindex = v1; - (void) _dwarf_macro_stack_push_index(dbg, fileindex, - &msdata); - /* We ignore the error, we just let fileindex ** be -1 when - we pop this one. */ - fileindex = v1; - pnext += len; - if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { - free_macro_stack(dbg,&msdata); - dwarf_dealloc(dbg, return_data, DW_DLA_STRING); - _dwarf_error(dbg, error, - DW_DLE_DEBUG_MACRO_INCONSISTENT); - return (DW_DLV_ERROR); - } - break; - - case DW_MACINFO_end_file: - fileindex = _dwarf_macro_stack_pop_index(&msdata); - break; /* no string or number here */ - case 0: - /* Type code of 0 means the end of cu's entries. */ - done = 1; - break; - default: - /* Bogus macinfo! */ - dwarf_dealloc(dbg, return_data, DW_DLA_STRING); - free_macro_stack(dbg,&msdata); - _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT); - return (DW_DLV_ERROR); - } - } - *entry_count = count; - *details = (Dwarf_Macro_Details *) return_data; - free_macro_stack(dbg,&msdata); - return DW_DLV_OK; -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_macro.h b/usr/src/tools/ctf/dwarf/common/dwarf_macro.h deleted file mode 100644 index 31ea2e6e67..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_macro.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - - Copyright (C) 2000, 2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - -/* - - - dwarf_macro.h - - $Revision: 1.4 $ $Date: 2004/10/28 22:19:14 $ - -*/ diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_names.c b/usr/src/tools/ctf/dwarf/common/dwarf_names.c deleted file mode 100644 index 417e025690..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_names.c +++ /dev/null @@ -1,2408 +0,0 @@ -/* Generated routines, do not edit. */ -/* Generated on May 22 2011 03:05:33 */ - -/* BEGIN FILE */ - -#include "dwarf.h" - -#include "libdwarf.h" - -/* ARGSUSED */ -int -dwarf_get_TAG_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_TAG_array_type: - *s_out = "DW_TAG_array_type"; - return DW_DLV_OK; - case DW_TAG_class_type: - *s_out = "DW_TAG_class_type"; - return DW_DLV_OK; - case DW_TAG_entry_point: - *s_out = "DW_TAG_entry_point"; - return DW_DLV_OK; - case DW_TAG_enumeration_type: - *s_out = "DW_TAG_enumeration_type"; - return DW_DLV_OK; - case DW_TAG_formal_parameter: - *s_out = "DW_TAG_formal_parameter"; - return DW_DLV_OK; - case DW_TAG_imported_declaration: - *s_out = "DW_TAG_imported_declaration"; - return DW_DLV_OK; - case DW_TAG_label: - *s_out = "DW_TAG_label"; - return DW_DLV_OK; - case DW_TAG_lexical_block: - *s_out = "DW_TAG_lexical_block"; - return DW_DLV_OK; - case DW_TAG_member: - *s_out = "DW_TAG_member"; - return DW_DLV_OK; - case DW_TAG_pointer_type: - *s_out = "DW_TAG_pointer_type"; - return DW_DLV_OK; - case DW_TAG_reference_type: - *s_out = "DW_TAG_reference_type"; - return DW_DLV_OK; - case DW_TAG_compile_unit: - *s_out = "DW_TAG_compile_unit"; - return DW_DLV_OK; - case DW_TAG_string_type: - *s_out = "DW_TAG_string_type"; - return DW_DLV_OK; - case DW_TAG_structure_type: - *s_out = "DW_TAG_structure_type"; - return DW_DLV_OK; - case DW_TAG_subroutine_type: - *s_out = "DW_TAG_subroutine_type"; - return DW_DLV_OK; - case DW_TAG_typedef: - *s_out = "DW_TAG_typedef"; - return DW_DLV_OK; - case DW_TAG_union_type: - *s_out = "DW_TAG_union_type"; - return DW_DLV_OK; - case DW_TAG_unspecified_parameters: - *s_out = "DW_TAG_unspecified_parameters"; - return DW_DLV_OK; - case DW_TAG_variant: - *s_out = "DW_TAG_variant"; - return DW_DLV_OK; - case DW_TAG_common_block: - *s_out = "DW_TAG_common_block"; - return DW_DLV_OK; - case DW_TAG_common_inclusion: - *s_out = "DW_TAG_common_inclusion"; - return DW_DLV_OK; - case DW_TAG_inheritance: - *s_out = "DW_TAG_inheritance"; - return DW_DLV_OK; - case DW_TAG_inlined_subroutine: - *s_out = "DW_TAG_inlined_subroutine"; - return DW_DLV_OK; - case DW_TAG_module: - *s_out = "DW_TAG_module"; - return DW_DLV_OK; - case DW_TAG_ptr_to_member_type: - *s_out = "DW_TAG_ptr_to_member_type"; - return DW_DLV_OK; - case DW_TAG_set_type: - *s_out = "DW_TAG_set_type"; - return DW_DLV_OK; - case DW_TAG_subrange_type: - *s_out = "DW_TAG_subrange_type"; - return DW_DLV_OK; - case DW_TAG_with_stmt: - *s_out = "DW_TAG_with_stmt"; - return DW_DLV_OK; - case DW_TAG_access_declaration: - *s_out = "DW_TAG_access_declaration"; - return DW_DLV_OK; - case DW_TAG_base_type: - *s_out = "DW_TAG_base_type"; - return DW_DLV_OK; - case DW_TAG_catch_block: - *s_out = "DW_TAG_catch_block"; - return DW_DLV_OK; - case DW_TAG_const_type: - *s_out = "DW_TAG_const_type"; - return DW_DLV_OK; - case DW_TAG_constant: - *s_out = "DW_TAG_constant"; - return DW_DLV_OK; - case DW_TAG_enumerator: - *s_out = "DW_TAG_enumerator"; - return DW_DLV_OK; - case DW_TAG_file_type: - *s_out = "DW_TAG_file_type"; - return DW_DLV_OK; - case DW_TAG_friend: - *s_out = "DW_TAG_friend"; - return DW_DLV_OK; - case DW_TAG_namelist: - *s_out = "DW_TAG_namelist"; - return DW_DLV_OK; - case DW_TAG_namelist_item: - *s_out = "DW_TAG_namelist_item"; - return DW_DLV_OK; - case DW_TAG_packed_type: - *s_out = "DW_TAG_packed_type"; - return DW_DLV_OK; - case DW_TAG_subprogram: - *s_out = "DW_TAG_subprogram"; - return DW_DLV_OK; - case DW_TAG_template_type_parameter: - *s_out = "DW_TAG_template_type_parameter"; - return DW_DLV_OK; - case DW_TAG_template_value_parameter: - *s_out = "DW_TAG_template_value_parameter"; - return DW_DLV_OK; - case DW_TAG_thrown_type: - *s_out = "DW_TAG_thrown_type"; - return DW_DLV_OK; - case DW_TAG_try_block: - *s_out = "DW_TAG_try_block"; - return DW_DLV_OK; - case DW_TAG_variant_part: - *s_out = "DW_TAG_variant_part"; - return DW_DLV_OK; - case DW_TAG_variable: - *s_out = "DW_TAG_variable"; - return DW_DLV_OK; - case DW_TAG_volatile_type: - *s_out = "DW_TAG_volatile_type"; - return DW_DLV_OK; - case DW_TAG_dwarf_procedure: - *s_out = "DW_TAG_dwarf_procedure"; - return DW_DLV_OK; - case DW_TAG_restrict_type: - *s_out = "DW_TAG_restrict_type"; - return DW_DLV_OK; - case DW_TAG_interface_type: - *s_out = "DW_TAG_interface_type"; - return DW_DLV_OK; - case DW_TAG_namespace: - *s_out = "DW_TAG_namespace"; - return DW_DLV_OK; - case DW_TAG_imported_module: - *s_out = "DW_TAG_imported_module"; - return DW_DLV_OK; - case DW_TAG_unspecified_type: - *s_out = "DW_TAG_unspecified_type"; - return DW_DLV_OK; - case DW_TAG_partial_unit: - *s_out = "DW_TAG_partial_unit"; - return DW_DLV_OK; - case DW_TAG_imported_unit: - *s_out = "DW_TAG_imported_unit"; - return DW_DLV_OK; - case DW_TAG_mutable_type: - *s_out = "DW_TAG_mutable_type"; - return DW_DLV_OK; - case DW_TAG_condition: - *s_out = "DW_TAG_condition"; - return DW_DLV_OK; - case DW_TAG_shared_type: - *s_out = "DW_TAG_shared_type"; - return DW_DLV_OK; - case DW_TAG_type_unit: - *s_out = "DW_TAG_type_unit"; - return DW_DLV_OK; - case DW_TAG_rvalue_reference_type: - *s_out = "DW_TAG_rvalue_reference_type"; - return DW_DLV_OK; - case DW_TAG_template_alias: - *s_out = "DW_TAG_template_alias"; - return DW_DLV_OK; - case DW_TAG_lo_user: - *s_out = "DW_TAG_lo_user"; - return DW_DLV_OK; - case DW_TAG_MIPS_loop: - *s_out = "DW_TAG_MIPS_loop"; - return DW_DLV_OK; - case DW_TAG_HP_array_descriptor: - *s_out = "DW_TAG_HP_array_descriptor"; - return DW_DLV_OK; - case DW_TAG_format_label: - *s_out = "DW_TAG_format_label"; - return DW_DLV_OK; - case DW_TAG_function_template: - *s_out = "DW_TAG_function_template"; - return DW_DLV_OK; - case DW_TAG_class_template: - *s_out = "DW_TAG_class_template"; - return DW_DLV_OK; - case DW_TAG_GNU_BINCL: - *s_out = "DW_TAG_GNU_BINCL"; - return DW_DLV_OK; - case DW_TAG_GNU_EINCL: - *s_out = "DW_TAG_GNU_EINCL"; - return DW_DLV_OK; - case DW_TAG_GNU_template_template_parameter: - *s_out = "DW_TAG_GNU_template_template_parameter"; - return DW_DLV_OK; - case DW_TAG_GNU_template_parameter_pack: - *s_out = "DW_TAG_GNU_template_parameter_pack"; - return DW_DLV_OK; - case DW_TAG_GNU_formal_parameter_pack: - *s_out = "DW_TAG_GNU_formal_parameter_pack"; - return DW_DLV_OK; - case DW_TAG_SUN_function_template: - *s_out = "DW_TAG_SUN_function_template"; - return DW_DLV_OK; - case DW_TAG_SUN_class_template: - *s_out = "DW_TAG_SUN_class_template"; - return DW_DLV_OK; - case DW_TAG_SUN_struct_template: - *s_out = "DW_TAG_SUN_struct_template"; - return DW_DLV_OK; - case DW_TAG_SUN_union_template: - *s_out = "DW_TAG_SUN_union_template"; - return DW_DLV_OK; - case DW_TAG_SUN_indirect_inheritance: - *s_out = "DW_TAG_SUN_indirect_inheritance"; - return DW_DLV_OK; - case DW_TAG_SUN_codeflags: - *s_out = "DW_TAG_SUN_codeflags"; - return DW_DLV_OK; - case DW_TAG_SUN_memop_info: - *s_out = "DW_TAG_SUN_memop_info"; - return DW_DLV_OK; - case DW_TAG_SUN_omp_child_func: - *s_out = "DW_TAG_SUN_omp_child_func"; - return DW_DLV_OK; - case DW_TAG_SUN_rtti_descriptor: - *s_out = "DW_TAG_SUN_rtti_descriptor"; - return DW_DLV_OK; - case DW_TAG_SUN_dtor_info: - *s_out = "DW_TAG_SUN_dtor_info"; - return DW_DLV_OK; - case DW_TAG_SUN_dtor: - *s_out = "DW_TAG_SUN_dtor"; - return DW_DLV_OK; - case DW_TAG_SUN_f90_interface: - *s_out = "DW_TAG_SUN_f90_interface"; - return DW_DLV_OK; - case DW_TAG_SUN_fortran_vax_structure: - *s_out = "DW_TAG_SUN_fortran_vax_structure"; - return DW_DLV_OK; - case DW_TAG_SUN_hi: - *s_out = "DW_TAG_SUN_hi"; - return DW_DLV_OK; - case DW_TAG_ALTIUM_circ_type: - *s_out = "DW_TAG_ALTIUM_circ_type"; - return DW_DLV_OK; - case DW_TAG_ALTIUM_mwa_circ_type: - *s_out = "DW_TAG_ALTIUM_mwa_circ_type"; - return DW_DLV_OK; - case DW_TAG_ALTIUM_rev_carry_type: - *s_out = "DW_TAG_ALTIUM_rev_carry_type"; - return DW_DLV_OK; - case DW_TAG_ALTIUM_rom: - *s_out = "DW_TAG_ALTIUM_rom"; - return DW_DLV_OK; - case DW_TAG_upc_shared_type: - *s_out = "DW_TAG_upc_shared_type"; - return DW_DLV_OK; - case DW_TAG_upc_strict_type: - *s_out = "DW_TAG_upc_strict_type"; - return DW_DLV_OK; - case DW_TAG_upc_relaxed_type: - *s_out = "DW_TAG_upc_relaxed_type"; - return DW_DLV_OK; - case DW_TAG_PGI_kanji_type: - *s_out = "DW_TAG_PGI_kanji_type"; - return DW_DLV_OK; - case DW_TAG_PGI_interface_block: - *s_out = "DW_TAG_PGI_interface_block"; - return DW_DLV_OK; - case DW_TAG_hi_user: - *s_out = "DW_TAG_hi_user"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_children_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_children_no: - *s_out = "DW_children_no"; - return DW_DLV_OK; - case DW_children_yes: - *s_out = "DW_children_yes"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_FORM_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_FORM_addr: - *s_out = "DW_FORM_addr"; - return DW_DLV_OK; - case DW_FORM_block2: - *s_out = "DW_FORM_block2"; - return DW_DLV_OK; - case DW_FORM_block4: - *s_out = "DW_FORM_block4"; - return DW_DLV_OK; - case DW_FORM_data2: - *s_out = "DW_FORM_data2"; - return DW_DLV_OK; - case DW_FORM_data4: - *s_out = "DW_FORM_data4"; - return DW_DLV_OK; - case DW_FORM_data8: - *s_out = "DW_FORM_data8"; - return DW_DLV_OK; - case DW_FORM_string: - *s_out = "DW_FORM_string"; - return DW_DLV_OK; - case DW_FORM_block: - *s_out = "DW_FORM_block"; - return DW_DLV_OK; - case DW_FORM_block1: - *s_out = "DW_FORM_block1"; - return DW_DLV_OK; - case DW_FORM_data1: - *s_out = "DW_FORM_data1"; - return DW_DLV_OK; - case DW_FORM_flag: - *s_out = "DW_FORM_flag"; - return DW_DLV_OK; - case DW_FORM_sdata: - *s_out = "DW_FORM_sdata"; - return DW_DLV_OK; - case DW_FORM_strp: - *s_out = "DW_FORM_strp"; - return DW_DLV_OK; - case DW_FORM_udata: - *s_out = "DW_FORM_udata"; - return DW_DLV_OK; - case DW_FORM_ref_addr: - *s_out = "DW_FORM_ref_addr"; - return DW_DLV_OK; - case DW_FORM_ref1: - *s_out = "DW_FORM_ref1"; - return DW_DLV_OK; - case DW_FORM_ref2: - *s_out = "DW_FORM_ref2"; - return DW_DLV_OK; - case DW_FORM_ref4: - *s_out = "DW_FORM_ref4"; - return DW_DLV_OK; - case DW_FORM_ref8: - *s_out = "DW_FORM_ref8"; - return DW_DLV_OK; - case DW_FORM_ref_udata: - *s_out = "DW_FORM_ref_udata"; - return DW_DLV_OK; - case DW_FORM_indirect: - *s_out = "DW_FORM_indirect"; - return DW_DLV_OK; - case DW_FORM_sec_offset: - *s_out = "DW_FORM_sec_offset"; - return DW_DLV_OK; - case DW_FORM_exprloc: - *s_out = "DW_FORM_exprloc"; - return DW_DLV_OK; - case DW_FORM_flag_present: - *s_out = "DW_FORM_flag_present"; - return DW_DLV_OK; - case DW_FORM_ref_sig8: - *s_out = "DW_FORM_ref_sig8"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_AT_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_AT_sibling: - *s_out = "DW_AT_sibling"; - return DW_DLV_OK; - case DW_AT_location: - *s_out = "DW_AT_location"; - return DW_DLV_OK; - case DW_AT_name: - *s_out = "DW_AT_name"; - return DW_DLV_OK; - case DW_AT_ordering: - *s_out = "DW_AT_ordering"; - return DW_DLV_OK; - case DW_AT_subscr_data: - *s_out = "DW_AT_subscr_data"; - return DW_DLV_OK; - case DW_AT_byte_size: - *s_out = "DW_AT_byte_size"; - return DW_DLV_OK; - case DW_AT_bit_offset: - *s_out = "DW_AT_bit_offset"; - return DW_DLV_OK; - case DW_AT_bit_size: - *s_out = "DW_AT_bit_size"; - return DW_DLV_OK; - case DW_AT_element_list: - *s_out = "DW_AT_element_list"; - return DW_DLV_OK; - case DW_AT_stmt_list: - *s_out = "DW_AT_stmt_list"; - return DW_DLV_OK; - case DW_AT_low_pc: - *s_out = "DW_AT_low_pc"; - return DW_DLV_OK; - case DW_AT_high_pc: - *s_out = "DW_AT_high_pc"; - return DW_DLV_OK; - case DW_AT_language: - *s_out = "DW_AT_language"; - return DW_DLV_OK; - case DW_AT_member: - *s_out = "DW_AT_member"; - return DW_DLV_OK; - case DW_AT_discr: - *s_out = "DW_AT_discr"; - return DW_DLV_OK; - case DW_AT_discr_value: - *s_out = "DW_AT_discr_value"; - return DW_DLV_OK; - case DW_AT_visibility: - *s_out = "DW_AT_visibility"; - return DW_DLV_OK; - case DW_AT_import: - *s_out = "DW_AT_import"; - return DW_DLV_OK; - case DW_AT_string_length: - *s_out = "DW_AT_string_length"; - return DW_DLV_OK; - case DW_AT_common_reference: - *s_out = "DW_AT_common_reference"; - return DW_DLV_OK; - case DW_AT_comp_dir: - *s_out = "DW_AT_comp_dir"; - return DW_DLV_OK; - case DW_AT_const_value: - *s_out = "DW_AT_const_value"; - return DW_DLV_OK; - case DW_AT_containing_type: - *s_out = "DW_AT_containing_type"; - return DW_DLV_OK; - case DW_AT_default_value: - *s_out = "DW_AT_default_value"; - return DW_DLV_OK; - case DW_AT_inline: - *s_out = "DW_AT_inline"; - return DW_DLV_OK; - case DW_AT_is_optional: - *s_out = "DW_AT_is_optional"; - return DW_DLV_OK; - case DW_AT_lower_bound: - *s_out = "DW_AT_lower_bound"; - return DW_DLV_OK; - case DW_AT_producer: - *s_out = "DW_AT_producer"; - return DW_DLV_OK; - case DW_AT_prototyped: - *s_out = "DW_AT_prototyped"; - return DW_DLV_OK; - case DW_AT_return_addr: - *s_out = "DW_AT_return_addr"; - return DW_DLV_OK; - case DW_AT_start_scope: - *s_out = "DW_AT_start_scope"; - return DW_DLV_OK; - case DW_AT_bit_stride: - *s_out = "DW_AT_bit_stride"; - return DW_DLV_OK; - case DW_AT_upper_bound: - *s_out = "DW_AT_upper_bound"; - return DW_DLV_OK; - case DW_AT_abstract_origin: - *s_out = "DW_AT_abstract_origin"; - return DW_DLV_OK; - case DW_AT_accessibility: - *s_out = "DW_AT_accessibility"; - return DW_DLV_OK; - case DW_AT_address_class: - *s_out = "DW_AT_address_class"; - return DW_DLV_OK; - case DW_AT_artificial: - *s_out = "DW_AT_artificial"; - return DW_DLV_OK; - case DW_AT_base_types: - *s_out = "DW_AT_base_types"; - return DW_DLV_OK; - case DW_AT_calling_convention: - *s_out = "DW_AT_calling_convention"; - return DW_DLV_OK; - case DW_AT_count: - *s_out = "DW_AT_count"; - return DW_DLV_OK; - case DW_AT_data_member_location: - *s_out = "DW_AT_data_member_location"; - return DW_DLV_OK; - case DW_AT_decl_column: - *s_out = "DW_AT_decl_column"; - return DW_DLV_OK; - case DW_AT_decl_file: - *s_out = "DW_AT_decl_file"; - return DW_DLV_OK; - case DW_AT_decl_line: - *s_out = "DW_AT_decl_line"; - return DW_DLV_OK; - case DW_AT_declaration: - *s_out = "DW_AT_declaration"; - return DW_DLV_OK; - case DW_AT_discr_list: - *s_out = "DW_AT_discr_list"; - return DW_DLV_OK; - case DW_AT_encoding: - *s_out = "DW_AT_encoding"; - return DW_DLV_OK; - case DW_AT_external: - *s_out = "DW_AT_external"; - return DW_DLV_OK; - case DW_AT_frame_base: - *s_out = "DW_AT_frame_base"; - return DW_DLV_OK; - case DW_AT_friend: - *s_out = "DW_AT_friend"; - return DW_DLV_OK; - case DW_AT_identifier_case: - *s_out = "DW_AT_identifier_case"; - return DW_DLV_OK; - case DW_AT_macro_info: - *s_out = "DW_AT_macro_info"; - return DW_DLV_OK; - case DW_AT_namelist_item: - *s_out = "DW_AT_namelist_item"; - return DW_DLV_OK; - case DW_AT_priority: - *s_out = "DW_AT_priority"; - return DW_DLV_OK; - case DW_AT_segment: - *s_out = "DW_AT_segment"; - return DW_DLV_OK; - case DW_AT_specification: - *s_out = "DW_AT_specification"; - return DW_DLV_OK; - case DW_AT_static_link: - *s_out = "DW_AT_static_link"; - return DW_DLV_OK; - case DW_AT_type: - *s_out = "DW_AT_type"; - return DW_DLV_OK; - case DW_AT_use_location: - *s_out = "DW_AT_use_location"; - return DW_DLV_OK; - case DW_AT_variable_parameter: - *s_out = "DW_AT_variable_parameter"; - return DW_DLV_OK; - case DW_AT_virtuality: - *s_out = "DW_AT_virtuality"; - return DW_DLV_OK; - case DW_AT_vtable_elem_location: - *s_out = "DW_AT_vtable_elem_location"; - return DW_DLV_OK; - case DW_AT_allocated: - *s_out = "DW_AT_allocated"; - return DW_DLV_OK; - case DW_AT_associated: - *s_out = "DW_AT_associated"; - return DW_DLV_OK; - case DW_AT_data_location: - *s_out = "DW_AT_data_location"; - return DW_DLV_OK; - case DW_AT_stride: - *s_out = "DW_AT_stride"; - return DW_DLV_OK; - case DW_AT_entry_pc: - *s_out = "DW_AT_entry_pc"; - return DW_DLV_OK; - case DW_AT_use_UTF8: - *s_out = "DW_AT_use_UTF8"; - return DW_DLV_OK; - case DW_AT_extension: - *s_out = "DW_AT_extension"; - return DW_DLV_OK; - case DW_AT_ranges: - *s_out = "DW_AT_ranges"; - return DW_DLV_OK; - case DW_AT_trampoline: - *s_out = "DW_AT_trampoline"; - return DW_DLV_OK; - case DW_AT_call_column: - *s_out = "DW_AT_call_column"; - return DW_DLV_OK; - case DW_AT_call_file: - *s_out = "DW_AT_call_file"; - return DW_DLV_OK; - case DW_AT_call_line: - *s_out = "DW_AT_call_line"; - return DW_DLV_OK; - case DW_AT_description: - *s_out = "DW_AT_description"; - return DW_DLV_OK; - case DW_AT_binary_scale: - *s_out = "DW_AT_binary_scale"; - return DW_DLV_OK; - case DW_AT_decimal_scale: - *s_out = "DW_AT_decimal_scale"; - return DW_DLV_OK; - case DW_AT_small: - *s_out = "DW_AT_small"; - return DW_DLV_OK; - case DW_AT_decimal_sign: - *s_out = "DW_AT_decimal_sign"; - return DW_DLV_OK; - case DW_AT_digit_count: - *s_out = "DW_AT_digit_count"; - return DW_DLV_OK; - case DW_AT_picture_string: - *s_out = "DW_AT_picture_string"; - return DW_DLV_OK; - case DW_AT_mutable: - *s_out = "DW_AT_mutable"; - return DW_DLV_OK; - case DW_AT_threads_scaled: - *s_out = "DW_AT_threads_scaled"; - return DW_DLV_OK; - case DW_AT_explicit: - *s_out = "DW_AT_explicit"; - return DW_DLV_OK; - case DW_AT_object_pointer: - *s_out = "DW_AT_object_pointer"; - return DW_DLV_OK; - case DW_AT_endianity: - *s_out = "DW_AT_endianity"; - return DW_DLV_OK; - case DW_AT_elemental: - *s_out = "DW_AT_elemental"; - return DW_DLV_OK; - case DW_AT_pure: - *s_out = "DW_AT_pure"; - return DW_DLV_OK; - case DW_AT_recursive: - *s_out = "DW_AT_recursive"; - return DW_DLV_OK; - case DW_AT_signature: - *s_out = "DW_AT_signature"; - return DW_DLV_OK; - case DW_AT_main_subprogram: - *s_out = "DW_AT_main_subprogram"; - return DW_DLV_OK; - case DW_AT_data_bit_offset: - *s_out = "DW_AT_data_bit_offset"; - return DW_DLV_OK; - case DW_AT_const_expr: - *s_out = "DW_AT_const_expr"; - return DW_DLV_OK; - case DW_AT_enum_class: - *s_out = "DW_AT_enum_class"; - return DW_DLV_OK; - case DW_AT_linkage_name: - *s_out = "DW_AT_linkage_name"; - return DW_DLV_OK; - case DW_AT_lo_user: - *s_out = "DW_AT_lo_user"; - return DW_DLV_OK; - case DW_AT_HP_unmodifiable: - *s_out = "DW_AT_HP_unmodifiable"; - return DW_DLV_OK; - case DW_AT_MIPS_loop_begin: - *s_out = "DW_AT_MIPS_loop_begin"; - return DW_DLV_OK; - case DW_AT_CPQ_split_lifetimes_var: - *s_out = "DW_AT_CPQ_split_lifetimes_var"; - return DW_DLV_OK; - case DW_AT_MIPS_epilog_begin: - *s_out = "DW_AT_MIPS_epilog_begin"; - return DW_DLV_OK; - case DW_AT_CPQ_prologue_length: - *s_out = "DW_AT_CPQ_prologue_length"; - return DW_DLV_OK; - case DW_AT_MIPS_software_pipeline_depth: - *s_out = "DW_AT_MIPS_software_pipeline_depth"; - return DW_DLV_OK; - case DW_AT_MIPS_linkage_name: - *s_out = "DW_AT_MIPS_linkage_name"; - return DW_DLV_OK; - case DW_AT_MIPS_stride: - *s_out = "DW_AT_MIPS_stride"; - return DW_DLV_OK; - case DW_AT_MIPS_abstract_name: - *s_out = "DW_AT_MIPS_abstract_name"; - return DW_DLV_OK; - case DW_AT_MIPS_clone_origin: - *s_out = "DW_AT_MIPS_clone_origin"; - return DW_DLV_OK; - case DW_AT_MIPS_has_inlines: - *s_out = "DW_AT_MIPS_has_inlines"; - return DW_DLV_OK; - case DW_AT_MIPS_stride_byte: - *s_out = "DW_AT_MIPS_stride_byte"; - return DW_DLV_OK; - case DW_AT_MIPS_stride_elem: - *s_out = "DW_AT_MIPS_stride_elem"; - return DW_DLV_OK; - case DW_AT_MIPS_ptr_dopetype: - *s_out = "DW_AT_MIPS_ptr_dopetype"; - return DW_DLV_OK; - case DW_AT_MIPS_allocatable_dopetype: - *s_out = "DW_AT_MIPS_allocatable_dopetype"; - return DW_DLV_OK; - case DW_AT_MIPS_assumed_shape_dopetype: - *s_out = "DW_AT_MIPS_assumed_shape_dopetype"; - return DW_DLV_OK; - case DW_AT_HP_proc_per_section: - *s_out = "DW_AT_HP_proc_per_section"; - return DW_DLV_OK; - case DW_AT_HP_raw_data_ptr: - *s_out = "DW_AT_HP_raw_data_ptr"; - return DW_DLV_OK; - case DW_AT_HP_pass_by_reference: - *s_out = "DW_AT_HP_pass_by_reference"; - return DW_DLV_OK; - case DW_AT_HP_opt_level: - *s_out = "DW_AT_HP_opt_level"; - return DW_DLV_OK; - case DW_AT_HP_prof_version_id: - *s_out = "DW_AT_HP_prof_version_id"; - return DW_DLV_OK; - case DW_AT_HP_opt_flags: - *s_out = "DW_AT_HP_opt_flags"; - return DW_DLV_OK; - case DW_AT_HP_cold_region_low_pc: - *s_out = "DW_AT_HP_cold_region_low_pc"; - return DW_DLV_OK; - case DW_AT_HP_cold_region_high_pc: - *s_out = "DW_AT_HP_cold_region_high_pc"; - return DW_DLV_OK; - case DW_AT_HP_all_variables_modifiable: - *s_out = "DW_AT_HP_all_variables_modifiable"; - return DW_DLV_OK; - case DW_AT_HP_linkage_name: - *s_out = "DW_AT_HP_linkage_name"; - return DW_DLV_OK; - case DW_AT_HP_prof_flags: - *s_out = "DW_AT_HP_prof_flags"; - return DW_DLV_OK; - case DW_AT_INTEL_other_endian: - *s_out = "DW_AT_INTEL_other_endian"; - return DW_DLV_OK; - case DW_AT_sf_names: - *s_out = "DW_AT_sf_names"; - return DW_DLV_OK; - case DW_AT_src_info: - *s_out = "DW_AT_src_info"; - return DW_DLV_OK; - case DW_AT_mac_info: - *s_out = "DW_AT_mac_info"; - return DW_DLV_OK; - case DW_AT_src_coords: - *s_out = "DW_AT_src_coords"; - return DW_DLV_OK; - case DW_AT_body_begin: - *s_out = "DW_AT_body_begin"; - return DW_DLV_OK; - case DW_AT_body_end: - *s_out = "DW_AT_body_end"; - return DW_DLV_OK; - case DW_AT_GNU_vector: - *s_out = "DW_AT_GNU_vector"; - return DW_DLV_OK; - case DW_AT_GNU_template_name: - *s_out = "DW_AT_GNU_template_name"; - return DW_DLV_OK; - case DW_AT_VMS_rtnbeg_pd_address: - *s_out = "DW_AT_VMS_rtnbeg_pd_address"; - return DW_DLV_OK; - case DW_AT_SUN_alignment: - *s_out = "DW_AT_SUN_alignment"; - return DW_DLV_OK; - case DW_AT_SUN_vtable: - *s_out = "DW_AT_SUN_vtable"; - return DW_DLV_OK; - case DW_AT_SUN_count_guarantee: - *s_out = "DW_AT_SUN_count_guarantee"; - return DW_DLV_OK; - case DW_AT_SUN_command_line: - *s_out = "DW_AT_SUN_command_line"; - return DW_DLV_OK; - case DW_AT_SUN_vbase: - *s_out = "DW_AT_SUN_vbase"; - return DW_DLV_OK; - case DW_AT_SUN_compile_options: - *s_out = "DW_AT_SUN_compile_options"; - return DW_DLV_OK; - case DW_AT_SUN_language: - *s_out = "DW_AT_SUN_language"; - return DW_DLV_OK; - case DW_AT_SUN_browser_file: - *s_out = "DW_AT_SUN_browser_file"; - return DW_DLV_OK; - case DW_AT_SUN_vtable_abi: - *s_out = "DW_AT_SUN_vtable_abi"; - return DW_DLV_OK; - case DW_AT_SUN_func_offsets: - *s_out = "DW_AT_SUN_func_offsets"; - return DW_DLV_OK; - case DW_AT_SUN_cf_kind: - *s_out = "DW_AT_SUN_cf_kind"; - return DW_DLV_OK; - case DW_AT_SUN_vtable_index: - *s_out = "DW_AT_SUN_vtable_index"; - return DW_DLV_OK; - case DW_AT_SUN_omp_tpriv_addr: - *s_out = "DW_AT_SUN_omp_tpriv_addr"; - return DW_DLV_OK; - case DW_AT_SUN_omp_child_func: - *s_out = "DW_AT_SUN_omp_child_func"; - return DW_DLV_OK; - case DW_AT_SUN_func_offset: - *s_out = "DW_AT_SUN_func_offset"; - return DW_DLV_OK; - case DW_AT_SUN_memop_type_ref: - *s_out = "DW_AT_SUN_memop_type_ref"; - return DW_DLV_OK; - case DW_AT_SUN_profile_id: - *s_out = "DW_AT_SUN_profile_id"; - return DW_DLV_OK; - case DW_AT_SUN_memop_signature: - *s_out = "DW_AT_SUN_memop_signature"; - return DW_DLV_OK; - case DW_AT_SUN_obj_dir: - *s_out = "DW_AT_SUN_obj_dir"; - return DW_DLV_OK; - case DW_AT_SUN_obj_file: - *s_out = "DW_AT_SUN_obj_file"; - return DW_DLV_OK; - case DW_AT_SUN_original_name: - *s_out = "DW_AT_SUN_original_name"; - return DW_DLV_OK; - case DW_AT_SUN_hwcprof_signature: - *s_out = "DW_AT_SUN_hwcprof_signature"; - return DW_DLV_OK; - case DW_AT_SUN_amd64_parmdump: - *s_out = "DW_AT_SUN_amd64_parmdump"; - return DW_DLV_OK; - case DW_AT_SUN_part_link_name: - *s_out = "DW_AT_SUN_part_link_name"; - return DW_DLV_OK; - case DW_AT_SUN_link_name: - *s_out = "DW_AT_SUN_link_name"; - return DW_DLV_OK; - case DW_AT_SUN_pass_with_const: - *s_out = "DW_AT_SUN_pass_with_const"; - return DW_DLV_OK; - case DW_AT_SUN_return_with_const: - *s_out = "DW_AT_SUN_return_with_const"; - return DW_DLV_OK; - case DW_AT_SUN_import_by_name: - *s_out = "DW_AT_SUN_import_by_name"; - return DW_DLV_OK; - case DW_AT_SUN_f90_pointer: - *s_out = "DW_AT_SUN_f90_pointer"; - return DW_DLV_OK; - case DW_AT_SUN_pass_by_ref: - *s_out = "DW_AT_SUN_pass_by_ref"; - return DW_DLV_OK; - case DW_AT_SUN_f90_allocatable: - *s_out = "DW_AT_SUN_f90_allocatable"; - return DW_DLV_OK; - case DW_AT_SUN_f90_assumed_shape_array: - *s_out = "DW_AT_SUN_f90_assumed_shape_array"; - return DW_DLV_OK; - case DW_AT_SUN_c_vla: - *s_out = "DW_AT_SUN_c_vla"; - return DW_DLV_OK; - case DW_AT_SUN_return_value_ptr: - *s_out = "DW_AT_SUN_return_value_ptr"; - return DW_DLV_OK; - case DW_AT_SUN_dtor_start: - *s_out = "DW_AT_SUN_dtor_start"; - return DW_DLV_OK; - case DW_AT_SUN_dtor_length: - *s_out = "DW_AT_SUN_dtor_length"; - return DW_DLV_OK; - case DW_AT_SUN_dtor_state_initial: - *s_out = "DW_AT_SUN_dtor_state_initial"; - return DW_DLV_OK; - case DW_AT_SUN_dtor_state_final: - *s_out = "DW_AT_SUN_dtor_state_final"; - return DW_DLV_OK; - case DW_AT_SUN_dtor_state_deltas: - *s_out = "DW_AT_SUN_dtor_state_deltas"; - return DW_DLV_OK; - case DW_AT_SUN_import_by_lname: - *s_out = "DW_AT_SUN_import_by_lname"; - return DW_DLV_OK; - case DW_AT_SUN_f90_use_only: - *s_out = "DW_AT_SUN_f90_use_only"; - return DW_DLV_OK; - case DW_AT_SUN_namelist_spec: - *s_out = "DW_AT_SUN_namelist_spec"; - return DW_DLV_OK; - case DW_AT_SUN_is_omp_child_func: - *s_out = "DW_AT_SUN_is_omp_child_func"; - return DW_DLV_OK; - case DW_AT_SUN_fortran_main_alias: - *s_out = "DW_AT_SUN_fortran_main_alias"; - return DW_DLV_OK; - case DW_AT_SUN_fortran_based: - *s_out = "DW_AT_SUN_fortran_based"; - return DW_DLV_OK; - case DW_AT_ALTIUM_loclist: - *s_out = "DW_AT_ALTIUM_loclist"; - return DW_DLV_OK; - case DW_AT_upc_threads_scaled: - *s_out = "DW_AT_upc_threads_scaled"; - return DW_DLV_OK; - case DW_AT_PGI_lbase: - *s_out = "DW_AT_PGI_lbase"; - return DW_DLV_OK; - case DW_AT_PGI_soffset: - *s_out = "DW_AT_PGI_soffset"; - return DW_DLV_OK; - case DW_AT_PGI_lstride: - *s_out = "DW_AT_PGI_lstride"; - return DW_DLV_OK; - case DW_AT_APPLE_closure: - *s_out = "DW_AT_APPLE_closure"; - return DW_DLV_OK; - case DW_AT_APPLE_major_runtime_vers: - *s_out = "DW_AT_APPLE_major_runtime_vers"; - return DW_DLV_OK; - case DW_AT_APPLE_runtime_class: - *s_out = "DW_AT_APPLE_runtime_class"; - return DW_DLV_OK; - case DW_AT_hi_user: - *s_out = "DW_AT_hi_user"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_OP_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_OP_addr: - *s_out = "DW_OP_addr"; - return DW_DLV_OK; - case DW_OP_deref: - *s_out = "DW_OP_deref"; - return DW_DLV_OK; - case DW_OP_const1u: - *s_out = "DW_OP_const1u"; - return DW_DLV_OK; - case DW_OP_const1s: - *s_out = "DW_OP_const1s"; - return DW_DLV_OK; - case DW_OP_const2u: - *s_out = "DW_OP_const2u"; - return DW_DLV_OK; - case DW_OP_const2s: - *s_out = "DW_OP_const2s"; - return DW_DLV_OK; - case DW_OP_const4u: - *s_out = "DW_OP_const4u"; - return DW_DLV_OK; - case DW_OP_const4s: - *s_out = "DW_OP_const4s"; - return DW_DLV_OK; - case DW_OP_const8u: - *s_out = "DW_OP_const8u"; - return DW_DLV_OK; - case DW_OP_const8s: - *s_out = "DW_OP_const8s"; - return DW_DLV_OK; - case DW_OP_constu: - *s_out = "DW_OP_constu"; - return DW_DLV_OK; - case DW_OP_consts: - *s_out = "DW_OP_consts"; - return DW_DLV_OK; - case DW_OP_dup: - *s_out = "DW_OP_dup"; - return DW_DLV_OK; - case DW_OP_drop: - *s_out = "DW_OP_drop"; - return DW_DLV_OK; - case DW_OP_over: - *s_out = "DW_OP_over"; - return DW_DLV_OK; - case DW_OP_pick: - *s_out = "DW_OP_pick"; - return DW_DLV_OK; - case DW_OP_swap: - *s_out = "DW_OP_swap"; - return DW_DLV_OK; - case DW_OP_rot: - *s_out = "DW_OP_rot"; - return DW_DLV_OK; - case DW_OP_xderef: - *s_out = "DW_OP_xderef"; - return DW_DLV_OK; - case DW_OP_abs: - *s_out = "DW_OP_abs"; - return DW_DLV_OK; - case DW_OP_and: - *s_out = "DW_OP_and"; - return DW_DLV_OK; - case DW_OP_div: - *s_out = "DW_OP_div"; - return DW_DLV_OK; - case DW_OP_minus: - *s_out = "DW_OP_minus"; - return DW_DLV_OK; - case DW_OP_mod: - *s_out = "DW_OP_mod"; - return DW_DLV_OK; - case DW_OP_mul: - *s_out = "DW_OP_mul"; - return DW_DLV_OK; - case DW_OP_neg: - *s_out = "DW_OP_neg"; - return DW_DLV_OK; - case DW_OP_not: - *s_out = "DW_OP_not"; - return DW_DLV_OK; - case DW_OP_or: - *s_out = "DW_OP_or"; - return DW_DLV_OK; - case DW_OP_plus: - *s_out = "DW_OP_plus"; - return DW_DLV_OK; - case DW_OP_plus_uconst: - *s_out = "DW_OP_plus_uconst"; - return DW_DLV_OK; - case DW_OP_shl: - *s_out = "DW_OP_shl"; - return DW_DLV_OK; - case DW_OP_shr: - *s_out = "DW_OP_shr"; - return DW_DLV_OK; - case DW_OP_shra: - *s_out = "DW_OP_shra"; - return DW_DLV_OK; - case DW_OP_xor: - *s_out = "DW_OP_xor"; - return DW_DLV_OK; - case DW_OP_bra: - *s_out = "DW_OP_bra"; - return DW_DLV_OK; - case DW_OP_eq: - *s_out = "DW_OP_eq"; - return DW_DLV_OK; - case DW_OP_ge: - *s_out = "DW_OP_ge"; - return DW_DLV_OK; - case DW_OP_gt: - *s_out = "DW_OP_gt"; - return DW_DLV_OK; - case DW_OP_le: - *s_out = "DW_OP_le"; - return DW_DLV_OK; - case DW_OP_lt: - *s_out = "DW_OP_lt"; - return DW_DLV_OK; - case DW_OP_ne: - *s_out = "DW_OP_ne"; - return DW_DLV_OK; - case DW_OP_skip: - *s_out = "DW_OP_skip"; - return DW_DLV_OK; - case DW_OP_lit0: - *s_out = "DW_OP_lit0"; - return DW_DLV_OK; - case DW_OP_lit1: - *s_out = "DW_OP_lit1"; - return DW_DLV_OK; - case DW_OP_lit2: - *s_out = "DW_OP_lit2"; - return DW_DLV_OK; - case DW_OP_lit3: - *s_out = "DW_OP_lit3"; - return DW_DLV_OK; - case DW_OP_lit4: - *s_out = "DW_OP_lit4"; - return DW_DLV_OK; - case DW_OP_lit5: - *s_out = "DW_OP_lit5"; - return DW_DLV_OK; - case DW_OP_lit6: - *s_out = "DW_OP_lit6"; - return DW_DLV_OK; - case DW_OP_lit7: - *s_out = "DW_OP_lit7"; - return DW_DLV_OK; - case DW_OP_lit8: - *s_out = "DW_OP_lit8"; - return DW_DLV_OK; - case DW_OP_lit9: - *s_out = "DW_OP_lit9"; - return DW_DLV_OK; - case DW_OP_lit10: - *s_out = "DW_OP_lit10"; - return DW_DLV_OK; - case DW_OP_lit11: - *s_out = "DW_OP_lit11"; - return DW_DLV_OK; - case DW_OP_lit12: - *s_out = "DW_OP_lit12"; - return DW_DLV_OK; - case DW_OP_lit13: - *s_out = "DW_OP_lit13"; - return DW_DLV_OK; - case DW_OP_lit14: - *s_out = "DW_OP_lit14"; - return DW_DLV_OK; - case DW_OP_lit15: - *s_out = "DW_OP_lit15"; - return DW_DLV_OK; - case DW_OP_lit16: - *s_out = "DW_OP_lit16"; - return DW_DLV_OK; - case DW_OP_lit17: - *s_out = "DW_OP_lit17"; - return DW_DLV_OK; - case DW_OP_lit18: - *s_out = "DW_OP_lit18"; - return DW_DLV_OK; - case DW_OP_lit19: - *s_out = "DW_OP_lit19"; - return DW_DLV_OK; - case DW_OP_lit20: - *s_out = "DW_OP_lit20"; - return DW_DLV_OK; - case DW_OP_lit21: - *s_out = "DW_OP_lit21"; - return DW_DLV_OK; - case DW_OP_lit22: - *s_out = "DW_OP_lit22"; - return DW_DLV_OK; - case DW_OP_lit23: - *s_out = "DW_OP_lit23"; - return DW_DLV_OK; - case DW_OP_lit24: - *s_out = "DW_OP_lit24"; - return DW_DLV_OK; - case DW_OP_lit25: - *s_out = "DW_OP_lit25"; - return DW_DLV_OK; - case DW_OP_lit26: - *s_out = "DW_OP_lit26"; - return DW_DLV_OK; - case DW_OP_lit27: - *s_out = "DW_OP_lit27"; - return DW_DLV_OK; - case DW_OP_lit28: - *s_out = "DW_OP_lit28"; - return DW_DLV_OK; - case DW_OP_lit29: - *s_out = "DW_OP_lit29"; - return DW_DLV_OK; - case DW_OP_lit30: - *s_out = "DW_OP_lit30"; - return DW_DLV_OK; - case DW_OP_lit31: - *s_out = "DW_OP_lit31"; - return DW_DLV_OK; - case DW_OP_reg0: - *s_out = "DW_OP_reg0"; - return DW_DLV_OK; - case DW_OP_reg1: - *s_out = "DW_OP_reg1"; - return DW_DLV_OK; - case DW_OP_reg2: - *s_out = "DW_OP_reg2"; - return DW_DLV_OK; - case DW_OP_reg3: - *s_out = "DW_OP_reg3"; - return DW_DLV_OK; - case DW_OP_reg4: - *s_out = "DW_OP_reg4"; - return DW_DLV_OK; - case DW_OP_reg5: - *s_out = "DW_OP_reg5"; - return DW_DLV_OK; - case DW_OP_reg6: - *s_out = "DW_OP_reg6"; - return DW_DLV_OK; - case DW_OP_reg7: - *s_out = "DW_OP_reg7"; - return DW_DLV_OK; - case DW_OP_reg8: - *s_out = "DW_OP_reg8"; - return DW_DLV_OK; - case DW_OP_reg9: - *s_out = "DW_OP_reg9"; - return DW_DLV_OK; - case DW_OP_reg10: - *s_out = "DW_OP_reg10"; - return DW_DLV_OK; - case DW_OP_reg11: - *s_out = "DW_OP_reg11"; - return DW_DLV_OK; - case DW_OP_reg12: - *s_out = "DW_OP_reg12"; - return DW_DLV_OK; - case DW_OP_reg13: - *s_out = "DW_OP_reg13"; - return DW_DLV_OK; - case DW_OP_reg14: - *s_out = "DW_OP_reg14"; - return DW_DLV_OK; - case DW_OP_reg15: - *s_out = "DW_OP_reg15"; - return DW_DLV_OK; - case DW_OP_reg16: - *s_out = "DW_OP_reg16"; - return DW_DLV_OK; - case DW_OP_reg17: - *s_out = "DW_OP_reg17"; - return DW_DLV_OK; - case DW_OP_reg18: - *s_out = "DW_OP_reg18"; - return DW_DLV_OK; - case DW_OP_reg19: - *s_out = "DW_OP_reg19"; - return DW_DLV_OK; - case DW_OP_reg20: - *s_out = "DW_OP_reg20"; - return DW_DLV_OK; - case DW_OP_reg21: - *s_out = "DW_OP_reg21"; - return DW_DLV_OK; - case DW_OP_reg22: - *s_out = "DW_OP_reg22"; - return DW_DLV_OK; - case DW_OP_reg23: - *s_out = "DW_OP_reg23"; - return DW_DLV_OK; - case DW_OP_reg24: - *s_out = "DW_OP_reg24"; - return DW_DLV_OK; - case DW_OP_reg25: - *s_out = "DW_OP_reg25"; - return DW_DLV_OK; - case DW_OP_reg26: - *s_out = "DW_OP_reg26"; - return DW_DLV_OK; - case DW_OP_reg27: - *s_out = "DW_OP_reg27"; - return DW_DLV_OK; - case DW_OP_reg28: - *s_out = "DW_OP_reg28"; - return DW_DLV_OK; - case DW_OP_reg29: - *s_out = "DW_OP_reg29"; - return DW_DLV_OK; - case DW_OP_reg30: - *s_out = "DW_OP_reg30"; - return DW_DLV_OK; - case DW_OP_reg31: - *s_out = "DW_OP_reg31"; - return DW_DLV_OK; - case DW_OP_breg0: - *s_out = "DW_OP_breg0"; - return DW_DLV_OK; - case DW_OP_breg1: - *s_out = "DW_OP_breg1"; - return DW_DLV_OK; - case DW_OP_breg2: - *s_out = "DW_OP_breg2"; - return DW_DLV_OK; - case DW_OP_breg3: - *s_out = "DW_OP_breg3"; - return DW_DLV_OK; - case DW_OP_breg4: - *s_out = "DW_OP_breg4"; - return DW_DLV_OK; - case DW_OP_breg5: - *s_out = "DW_OP_breg5"; - return DW_DLV_OK; - case DW_OP_breg6: - *s_out = "DW_OP_breg6"; - return DW_DLV_OK; - case DW_OP_breg7: - *s_out = "DW_OP_breg7"; - return DW_DLV_OK; - case DW_OP_breg8: - *s_out = "DW_OP_breg8"; - return DW_DLV_OK; - case DW_OP_breg9: - *s_out = "DW_OP_breg9"; - return DW_DLV_OK; - case DW_OP_breg10: - *s_out = "DW_OP_breg10"; - return DW_DLV_OK; - case DW_OP_breg11: - *s_out = "DW_OP_breg11"; - return DW_DLV_OK; - case DW_OP_breg12: - *s_out = "DW_OP_breg12"; - return DW_DLV_OK; - case DW_OP_breg13: - *s_out = "DW_OP_breg13"; - return DW_DLV_OK; - case DW_OP_breg14: - *s_out = "DW_OP_breg14"; - return DW_DLV_OK; - case DW_OP_breg15: - *s_out = "DW_OP_breg15"; - return DW_DLV_OK; - case DW_OP_breg16: - *s_out = "DW_OP_breg16"; - return DW_DLV_OK; - case DW_OP_breg17: - *s_out = "DW_OP_breg17"; - return DW_DLV_OK; - case DW_OP_breg18: - *s_out = "DW_OP_breg18"; - return DW_DLV_OK; - case DW_OP_breg19: - *s_out = "DW_OP_breg19"; - return DW_DLV_OK; - case DW_OP_breg20: - *s_out = "DW_OP_breg20"; - return DW_DLV_OK; - case DW_OP_breg21: - *s_out = "DW_OP_breg21"; - return DW_DLV_OK; - case DW_OP_breg22: - *s_out = "DW_OP_breg22"; - return DW_DLV_OK; - case DW_OP_breg23: - *s_out = "DW_OP_breg23"; - return DW_DLV_OK; - case DW_OP_breg24: - *s_out = "DW_OP_breg24"; - return DW_DLV_OK; - case DW_OP_breg25: - *s_out = "DW_OP_breg25"; - return DW_DLV_OK; - case DW_OP_breg26: - *s_out = "DW_OP_breg26"; - return DW_DLV_OK; - case DW_OP_breg27: - *s_out = "DW_OP_breg27"; - return DW_DLV_OK; - case DW_OP_breg28: - *s_out = "DW_OP_breg28"; - return DW_DLV_OK; - case DW_OP_breg29: - *s_out = "DW_OP_breg29"; - return DW_DLV_OK; - case DW_OP_breg30: - *s_out = "DW_OP_breg30"; - return DW_DLV_OK; - case DW_OP_breg31: - *s_out = "DW_OP_breg31"; - return DW_DLV_OK; - case DW_OP_regx: - *s_out = "DW_OP_regx"; - return DW_DLV_OK; - case DW_OP_fbreg: - *s_out = "DW_OP_fbreg"; - return DW_DLV_OK; - case DW_OP_bregx: - *s_out = "DW_OP_bregx"; - return DW_DLV_OK; - case DW_OP_piece: - *s_out = "DW_OP_piece"; - return DW_DLV_OK; - case DW_OP_deref_size: - *s_out = "DW_OP_deref_size"; - return DW_DLV_OK; - case DW_OP_xderef_size: - *s_out = "DW_OP_xderef_size"; - return DW_DLV_OK; - case DW_OP_nop: - *s_out = "DW_OP_nop"; - return DW_DLV_OK; - case DW_OP_push_object_address: - *s_out = "DW_OP_push_object_address"; - return DW_DLV_OK; - case DW_OP_call2: - *s_out = "DW_OP_call2"; - return DW_DLV_OK; - case DW_OP_call4: - *s_out = "DW_OP_call4"; - return DW_DLV_OK; - case DW_OP_call_ref: - *s_out = "DW_OP_call_ref"; - return DW_DLV_OK; - case DW_OP_form_tls_address: - *s_out = "DW_OP_form_tls_address"; - return DW_DLV_OK; - case DW_OP_call_frame_cfa: - *s_out = "DW_OP_call_frame_cfa"; - return DW_DLV_OK; - case DW_OP_bit_piece: - *s_out = "DW_OP_bit_piece"; - return DW_DLV_OK; - case DW_OP_implicit_value: - *s_out = "DW_OP_implicit_value"; - return DW_DLV_OK; - case DW_OP_stack_value: - *s_out = "DW_OP_stack_value"; - return DW_DLV_OK; - case DW_OP_lo_user: - *s_out = "DW_OP_lo_user"; - return DW_DLV_OK; - case DW_OP_HP_is_value: - *s_out = "DW_OP_HP_is_value"; - return DW_DLV_OK; - case DW_OP_HP_fltconst4: - *s_out = "DW_OP_HP_fltconst4"; - return DW_DLV_OK; - case DW_OP_HP_fltconst8: - *s_out = "DW_OP_HP_fltconst8"; - return DW_DLV_OK; - case DW_OP_HP_mod_range: - *s_out = "DW_OP_HP_mod_range"; - return DW_DLV_OK; - case DW_OP_HP_unmod_range: - *s_out = "DW_OP_HP_unmod_range"; - return DW_DLV_OK; - case DW_OP_HP_tls: - *s_out = "DW_OP_HP_tls"; - return DW_DLV_OK; - case DW_OP_INTEL_bit_piece: - *s_out = "DW_OP_INTEL_bit_piece"; - return DW_DLV_OK; - case DW_OP_APPLE_uninit: - *s_out = "DW_OP_APPLE_uninit"; - return DW_DLV_OK; - case DW_OP_hi_user: - *s_out = "DW_OP_hi_user"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_ATE_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_ATE_address: - *s_out = "DW_ATE_address"; - return DW_DLV_OK; - case DW_ATE_boolean: - *s_out = "DW_ATE_boolean"; - return DW_DLV_OK; - case DW_ATE_complex_float: - *s_out = "DW_ATE_complex_float"; - return DW_DLV_OK; - case DW_ATE_float: - *s_out = "DW_ATE_float"; - return DW_DLV_OK; - case DW_ATE_signed: - *s_out = "DW_ATE_signed"; - return DW_DLV_OK; - case DW_ATE_signed_char: - *s_out = "DW_ATE_signed_char"; - return DW_DLV_OK; - case DW_ATE_unsigned: - *s_out = "DW_ATE_unsigned"; - return DW_DLV_OK; - case DW_ATE_unsigned_char: - *s_out = "DW_ATE_unsigned_char"; - return DW_DLV_OK; - case DW_ATE_imaginary_float: - *s_out = "DW_ATE_imaginary_float"; - return DW_DLV_OK; - case DW_ATE_packed_decimal: - *s_out = "DW_ATE_packed_decimal"; - return DW_DLV_OK; - case DW_ATE_numeric_string: - *s_out = "DW_ATE_numeric_string"; - return DW_DLV_OK; - case DW_ATE_edited: - *s_out = "DW_ATE_edited"; - return DW_DLV_OK; - case DW_ATE_signed_fixed: - *s_out = "DW_ATE_signed_fixed"; - return DW_DLV_OK; - case DW_ATE_unsigned_fixed: - *s_out = "DW_ATE_unsigned_fixed"; - return DW_DLV_OK; - case DW_ATE_decimal_float: - *s_out = "DW_ATE_decimal_float"; - return DW_DLV_OK; - case DW_ATE_HP_float80: - *s_out = "DW_ATE_HP_float80"; - return DW_DLV_OK; - case DW_ATE_HP_complex_float80: - *s_out = "DW_ATE_HP_complex_float80"; - return DW_DLV_OK; - case DW_ATE_HP_float128: - *s_out = "DW_ATE_HP_float128"; - return DW_DLV_OK; - case DW_ATE_HP_complex_float128: - *s_out = "DW_ATE_HP_complex_float128"; - return DW_DLV_OK; - case DW_ATE_HP_floathpintel: - *s_out = "DW_ATE_HP_floathpintel"; - return DW_DLV_OK; - case DW_ATE_HP_imaginary_float80: - *s_out = "DW_ATE_HP_imaginary_float80"; - return DW_DLV_OK; - case DW_ATE_HP_imaginary_float128: - *s_out = "DW_ATE_HP_imaginary_float128"; - return DW_DLV_OK; - case DW_ATE_SUN_interval_float: - *s_out = "DW_ATE_SUN_interval_float"; - return DW_DLV_OK; - case DW_ATE_SUN_imaginary_float: - *s_out = "DW_ATE_SUN_imaginary_float"; - return DW_DLV_OK; - case DW_ATE_hi_user: - *s_out = "DW_ATE_hi_user"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_DS_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_DS_unsigned: - *s_out = "DW_DS_unsigned"; - return DW_DLV_OK; - case DW_DS_leading_overpunch: - *s_out = "DW_DS_leading_overpunch"; - return DW_DLV_OK; - case DW_DS_trailing_overpunch: - *s_out = "DW_DS_trailing_overpunch"; - return DW_DLV_OK; - case DW_DS_leading_separate: - *s_out = "DW_DS_leading_separate"; - return DW_DLV_OK; - case DW_DS_trailing_separate: - *s_out = "DW_DS_trailing_separate"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_END_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_END_default: - *s_out = "DW_END_default"; - return DW_DLV_OK; - case DW_END_big: - *s_out = "DW_END_big"; - return DW_DLV_OK; - case DW_END_little: - *s_out = "DW_END_little"; - return DW_DLV_OK; - case DW_END_lo_user: - *s_out = "DW_END_lo_user"; - return DW_DLV_OK; - case DW_END_hi_user: - *s_out = "DW_END_hi_user"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_ATCF_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_ATCF_lo_user: - *s_out = "DW_ATCF_lo_user"; - return DW_DLV_OK; - case DW_ATCF_SUN_mop_bitfield: - *s_out = "DW_ATCF_SUN_mop_bitfield"; - return DW_DLV_OK; - case DW_ATCF_SUN_mop_spill: - *s_out = "DW_ATCF_SUN_mop_spill"; - return DW_DLV_OK; - case DW_ATCF_SUN_mop_scopy: - *s_out = "DW_ATCF_SUN_mop_scopy"; - return DW_DLV_OK; - case DW_ATCF_SUN_func_start: - *s_out = "DW_ATCF_SUN_func_start"; - return DW_DLV_OK; - case DW_ATCF_SUN_end_ctors: - *s_out = "DW_ATCF_SUN_end_ctors"; - return DW_DLV_OK; - case DW_ATCF_SUN_branch_target: - *s_out = "DW_ATCF_SUN_branch_target"; - return DW_DLV_OK; - case DW_ATCF_SUN_mop_stack_probe: - *s_out = "DW_ATCF_SUN_mop_stack_probe"; - return DW_DLV_OK; - case DW_ATCF_SUN_func_epilog: - *s_out = "DW_ATCF_SUN_func_epilog"; - return DW_DLV_OK; - case DW_ATCF_hi_user: - *s_out = "DW_ATCF_hi_user"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_ACCESS_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_ACCESS_public: - *s_out = "DW_ACCESS_public"; - return DW_DLV_OK; - case DW_ACCESS_protected: - *s_out = "DW_ACCESS_protected"; - return DW_DLV_OK; - case DW_ACCESS_private: - *s_out = "DW_ACCESS_private"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_VIS_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_VIS_local: - *s_out = "DW_VIS_local"; - return DW_DLV_OK; - case DW_VIS_exported: - *s_out = "DW_VIS_exported"; - return DW_DLV_OK; - case DW_VIS_qualified: - *s_out = "DW_VIS_qualified"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_VIRTUALITY_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_VIRTUALITY_none: - *s_out = "DW_VIRTUALITY_none"; - return DW_DLV_OK; - case DW_VIRTUALITY_virtual: - *s_out = "DW_VIRTUALITY_virtual"; - return DW_DLV_OK; - case DW_VIRTUALITY_pure_virtual: - *s_out = "DW_VIRTUALITY_pure_virtual"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_LANG_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_LANG_C89: - *s_out = "DW_LANG_C89"; - return DW_DLV_OK; - case DW_LANG_C: - *s_out = "DW_LANG_C"; - return DW_DLV_OK; - case DW_LANG_Ada83: - *s_out = "DW_LANG_Ada83"; - return DW_DLV_OK; - case DW_LANG_C_plus_plus: - *s_out = "DW_LANG_C_plus_plus"; - return DW_DLV_OK; - case DW_LANG_Cobol74: - *s_out = "DW_LANG_Cobol74"; - return DW_DLV_OK; - case DW_LANG_Cobol85: - *s_out = "DW_LANG_Cobol85"; - return DW_DLV_OK; - case DW_LANG_Fortran77: - *s_out = "DW_LANG_Fortran77"; - return DW_DLV_OK; - case DW_LANG_Fortran90: - *s_out = "DW_LANG_Fortran90"; - return DW_DLV_OK; - case DW_LANG_Pascal83: - *s_out = "DW_LANG_Pascal83"; - return DW_DLV_OK; - case DW_LANG_Modula2: - *s_out = "DW_LANG_Modula2"; - return DW_DLV_OK; - case DW_LANG_Java: - *s_out = "DW_LANG_Java"; - return DW_DLV_OK; - case DW_LANG_C99: - *s_out = "DW_LANG_C99"; - return DW_DLV_OK; - case DW_LANG_Ada95: - *s_out = "DW_LANG_Ada95"; - return DW_DLV_OK; - case DW_LANG_Fortran95: - *s_out = "DW_LANG_Fortran95"; - return DW_DLV_OK; - case DW_LANG_PLI: - *s_out = "DW_LANG_PLI"; - return DW_DLV_OK; - case DW_LANG_ObjC: - *s_out = "DW_LANG_ObjC"; - return DW_DLV_OK; - case DW_LANG_ObjC_plus_plus: - *s_out = "DW_LANG_ObjC_plus_plus"; - return DW_DLV_OK; - case DW_LANG_UPC: - *s_out = "DW_LANG_UPC"; - return DW_DLV_OK; - case DW_LANG_D: - *s_out = "DW_LANG_D"; - return DW_DLV_OK; - case DW_LANG_Python: - *s_out = "DW_LANG_Python"; - return DW_DLV_OK; - case DW_LANG_OpenCL: - *s_out = "DW_LANG_OpenCL"; - return DW_DLV_OK; - case DW_LANG_Go: - *s_out = "DW_LANG_Go"; - return DW_DLV_OK; - case DW_LANG_lo_user: - *s_out = "DW_LANG_lo_user"; - return DW_DLV_OK; - case DW_LANG_Mips_Assembler: - *s_out = "DW_LANG_Mips_Assembler"; - return DW_DLV_OK; - case DW_LANG_Upc: - *s_out = "DW_LANG_Upc"; - return DW_DLV_OK; - case DW_LANG_SUN_Assembler: - *s_out = "DW_LANG_SUN_Assembler"; - return DW_DLV_OK; - case DW_LANG_ALTIUM_Assembler: - *s_out = "DW_LANG_ALTIUM_Assembler"; - return DW_DLV_OK; - case DW_LANG_hi_user: - *s_out = "DW_LANG_hi_user"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_ID_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_ID_case_sensitive: - *s_out = "DW_ID_case_sensitive"; - return DW_DLV_OK; - case DW_ID_up_case: - *s_out = "DW_ID_up_case"; - return DW_DLV_OK; - case DW_ID_down_case: - *s_out = "DW_ID_down_case"; - return DW_DLV_OK; - case DW_ID_case_insensitive: - *s_out = "DW_ID_case_insensitive"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_CC_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_CC_normal: - *s_out = "DW_CC_normal"; - return DW_DLV_OK; - case DW_CC_program: - *s_out = "DW_CC_program"; - return DW_DLV_OK; - case DW_CC_nocall: - *s_out = "DW_CC_nocall"; - return DW_DLV_OK; - case DW_CC_lo_user: - *s_out = "DW_CC_lo_user"; - return DW_DLV_OK; - case DW_CC_ALTIUM_interrupt: - *s_out = "DW_CC_ALTIUM_interrupt"; - return DW_DLV_OK; - case DW_CC_ALTIUM_near_system_stack: - *s_out = "DW_CC_ALTIUM_near_system_stack"; - return DW_DLV_OK; - case DW_CC_ALTIUM_near_user_stack: - *s_out = "DW_CC_ALTIUM_near_user_stack"; - return DW_DLV_OK; - case DW_CC_ALTIUM_huge_user_stack: - *s_out = "DW_CC_ALTIUM_huge_user_stack"; - return DW_DLV_OK; - case DW_CC_hi_user: - *s_out = "DW_CC_hi_user"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_INL_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_INL_not_inlined: - *s_out = "DW_INL_not_inlined"; - return DW_DLV_OK; - case DW_INL_inlined: - *s_out = "DW_INL_inlined"; - return DW_DLV_OK; - case DW_INL_declared_not_inlined: - *s_out = "DW_INL_declared_not_inlined"; - return DW_DLV_OK; - case DW_INL_declared_inlined: - *s_out = "DW_INL_declared_inlined"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_ORD_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_ORD_row_major: - *s_out = "DW_ORD_row_major"; - return DW_DLV_OK; - case DW_ORD_col_major: - *s_out = "DW_ORD_col_major"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_DSC_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_DSC_label: - *s_out = "DW_DSC_label"; - return DW_DLV_OK; - case DW_DSC_range: - *s_out = "DW_DSC_range"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_LNS_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_LNS_copy: - *s_out = "DW_LNS_copy"; - return DW_DLV_OK; - case DW_LNS_advance_pc: - *s_out = "DW_LNS_advance_pc"; - return DW_DLV_OK; - case DW_LNS_advance_line: - *s_out = "DW_LNS_advance_line"; - return DW_DLV_OK; - case DW_LNS_set_file: - *s_out = "DW_LNS_set_file"; - return DW_DLV_OK; - case DW_LNS_set_column: - *s_out = "DW_LNS_set_column"; - return DW_DLV_OK; - case DW_LNS_negate_stmt: - *s_out = "DW_LNS_negate_stmt"; - return DW_DLV_OK; - case DW_LNS_set_basic_block: - *s_out = "DW_LNS_set_basic_block"; - return DW_DLV_OK; - case DW_LNS_const_add_pc: - *s_out = "DW_LNS_const_add_pc"; - return DW_DLV_OK; - case DW_LNS_fixed_advance_pc: - *s_out = "DW_LNS_fixed_advance_pc"; - return DW_DLV_OK; - case DW_LNS_set_prologue_end: - *s_out = "DW_LNS_set_prologue_end"; - return DW_DLV_OK; - case DW_LNS_set_epilogue_begin: - *s_out = "DW_LNS_set_epilogue_begin"; - return DW_DLV_OK; - case DW_LNS_set_isa: - *s_out = "DW_LNS_set_isa"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_LNE_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_LNE_end_sequence: - *s_out = "DW_LNE_end_sequence"; - return DW_DLV_OK; - case DW_LNE_set_address: - *s_out = "DW_LNE_set_address"; - return DW_DLV_OK; - case DW_LNE_define_file: - *s_out = "DW_LNE_define_file"; - return DW_DLV_OK; - case DW_LNE_set_discriminator: - *s_out = "DW_LNE_set_discriminator"; - return DW_DLV_OK; - case DW_LNE_HP_negate_is_UV_update: - *s_out = "DW_LNE_HP_negate_is_UV_update"; - return DW_DLV_OK; - case DW_LNE_HP_push_context: - *s_out = "DW_LNE_HP_push_context"; - return DW_DLV_OK; - case DW_LNE_HP_pop_context: - *s_out = "DW_LNE_HP_pop_context"; - return DW_DLV_OK; - case DW_LNE_HP_set_file_line_column: - *s_out = "DW_LNE_HP_set_file_line_column"; - return DW_DLV_OK; - case DW_LNE_HP_set_routine_name: - *s_out = "DW_LNE_HP_set_routine_name"; - return DW_DLV_OK; - case DW_LNE_HP_set_sequence: - *s_out = "DW_LNE_HP_set_sequence"; - return DW_DLV_OK; - case DW_LNE_HP_negate_post_semantics: - *s_out = "DW_LNE_HP_negate_post_semantics"; - return DW_DLV_OK; - case DW_LNE_HP_negate_function_exit: - *s_out = "DW_LNE_HP_negate_function_exit"; - return DW_DLV_OK; - case DW_LNE_HP_negate_front_end_logical: - *s_out = "DW_LNE_HP_negate_front_end_logical"; - return DW_DLV_OK; - case DW_LNE_HP_define_proc: - *s_out = "DW_LNE_HP_define_proc"; - return DW_DLV_OK; - case DW_LNE_lo_user: - *s_out = "DW_LNE_lo_user"; - return DW_DLV_OK; - case DW_LNE_hi_user: - *s_out = "DW_LNE_hi_user"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_ISA_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_ISA_UNKNOWN: - *s_out = "DW_ISA_UNKNOWN"; - return DW_DLV_OK; - case DW_ISA_ARM_thumb: - *s_out = "DW_ISA_ARM_thumb"; - return DW_DLV_OK; - case DW_ISA_ARM_arm: - *s_out = "DW_ISA_ARM_arm"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_MACINFO_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_MACINFO_define: - *s_out = "DW_MACINFO_define"; - return DW_DLV_OK; - case DW_MACINFO_undef: - *s_out = "DW_MACINFO_undef"; - return DW_DLV_OK; - case DW_MACINFO_start_file: - *s_out = "DW_MACINFO_start_file"; - return DW_DLV_OK; - case DW_MACINFO_end_file: - *s_out = "DW_MACINFO_end_file"; - return DW_DLV_OK; - case DW_MACINFO_vendor_ext: - *s_out = "DW_MACINFO_vendor_ext"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_CFA_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_CFA_extended: - *s_out = "DW_CFA_extended"; - return DW_DLV_OK; - case DW_CFA_set_loc: - *s_out = "DW_CFA_set_loc"; - return DW_DLV_OK; - case DW_CFA_advance_loc1: - *s_out = "DW_CFA_advance_loc1"; - return DW_DLV_OK; - case DW_CFA_advance_loc2: - *s_out = "DW_CFA_advance_loc2"; - return DW_DLV_OK; - case DW_CFA_advance_loc4: - *s_out = "DW_CFA_advance_loc4"; - return DW_DLV_OK; - case DW_CFA_offset_extended: - *s_out = "DW_CFA_offset_extended"; - return DW_DLV_OK; - case DW_CFA_restore_extended: - *s_out = "DW_CFA_restore_extended"; - return DW_DLV_OK; - case DW_CFA_undefined: - *s_out = "DW_CFA_undefined"; - return DW_DLV_OK; - case DW_CFA_same_value: - *s_out = "DW_CFA_same_value"; - return DW_DLV_OK; - case DW_CFA_register: - *s_out = "DW_CFA_register"; - return DW_DLV_OK; - case DW_CFA_remember_state: - *s_out = "DW_CFA_remember_state"; - return DW_DLV_OK; - case DW_CFA_restore_state: - *s_out = "DW_CFA_restore_state"; - return DW_DLV_OK; - case DW_CFA_def_cfa: - *s_out = "DW_CFA_def_cfa"; - return DW_DLV_OK; - case DW_CFA_def_cfa_register: - *s_out = "DW_CFA_def_cfa_register"; - return DW_DLV_OK; - case DW_CFA_def_cfa_offset: - *s_out = "DW_CFA_def_cfa_offset"; - return DW_DLV_OK; - case DW_CFA_def_cfa_expression: - *s_out = "DW_CFA_def_cfa_expression"; - return DW_DLV_OK; - case DW_CFA_expression: - *s_out = "DW_CFA_expression"; - return DW_DLV_OK; - case DW_CFA_offset_extended_sf: - *s_out = "DW_CFA_offset_extended_sf"; - return DW_DLV_OK; - case DW_CFA_def_cfa_sf: - *s_out = "DW_CFA_def_cfa_sf"; - return DW_DLV_OK; - case DW_CFA_def_cfa_offset_sf: - *s_out = "DW_CFA_def_cfa_offset_sf"; - return DW_DLV_OK; - case DW_CFA_val_offset: - *s_out = "DW_CFA_val_offset"; - return DW_DLV_OK; - case DW_CFA_val_offset_sf: - *s_out = "DW_CFA_val_offset_sf"; - return DW_DLV_OK; - case DW_CFA_val_expression: - *s_out = "DW_CFA_val_expression"; - return DW_DLV_OK; - case DW_CFA_lo_user: - *s_out = "DW_CFA_lo_user"; - return DW_DLV_OK; - case DW_CFA_MIPS_advance_loc8: - *s_out = "DW_CFA_MIPS_advance_loc8"; - return DW_DLV_OK; - case DW_CFA_GNU_window_save: - *s_out = "DW_CFA_GNU_window_save"; - return DW_DLV_OK; - case DW_CFA_GNU_args_size: - *s_out = "DW_CFA_GNU_args_size"; - return DW_DLV_OK; - case DW_CFA_GNU_negative_offset_extended: - *s_out = "DW_CFA_GNU_negative_offset_extended"; - return DW_DLV_OK; - case DW_CFA_high_user: - *s_out = "DW_CFA_high_user"; - return DW_DLV_OK; - case DW_CFA_advance_loc: - *s_out = "DW_CFA_advance_loc"; - return DW_DLV_OK; - case DW_CFA_offset: - *s_out = "DW_CFA_offset"; - return DW_DLV_OK; - case DW_CFA_restore: - *s_out = "DW_CFA_restore"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_EH_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_EH_PE_absptr: - *s_out = "DW_EH_PE_absptr"; - return DW_DLV_OK; - case DW_EH_PE_uleb128: - *s_out = "DW_EH_PE_uleb128"; - return DW_DLV_OK; - case DW_EH_PE_udata2: - *s_out = "DW_EH_PE_udata2"; - return DW_DLV_OK; - case DW_EH_PE_udata4: - *s_out = "DW_EH_PE_udata4"; - return DW_DLV_OK; - case DW_EH_PE_udata8: - *s_out = "DW_EH_PE_udata8"; - return DW_DLV_OK; - case DW_EH_PE_sleb128: - *s_out = "DW_EH_PE_sleb128"; - return DW_DLV_OK; - case DW_EH_PE_sdata2: - *s_out = "DW_EH_PE_sdata2"; - return DW_DLV_OK; - case DW_EH_PE_sdata4: - *s_out = "DW_EH_PE_sdata4"; - return DW_DLV_OK; - case DW_EH_PE_sdata8: - *s_out = "DW_EH_PE_sdata8"; - return DW_DLV_OK; - case DW_EH_PE_pcrel: - *s_out = "DW_EH_PE_pcrel"; - return DW_DLV_OK; - case DW_EH_PE_textrel: - *s_out = "DW_EH_PE_textrel"; - return DW_DLV_OK; - case DW_EH_PE_datarel: - *s_out = "DW_EH_PE_datarel"; - return DW_DLV_OK; - case DW_EH_PE_funcrel: - *s_out = "DW_EH_PE_funcrel"; - return DW_DLV_OK; - case DW_EH_PE_aligned: - *s_out = "DW_EH_PE_aligned"; - return DW_DLV_OK; - case DW_EH_PE_omit: - *s_out = "DW_EH_PE_omit"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_FRAME_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_FRAME_CFA_COL: - *s_out = "DW_FRAME_CFA_COL"; - return DW_DLV_OK; - case DW_FRAME_REG1: - *s_out = "DW_FRAME_REG1"; - return DW_DLV_OK; - case DW_FRAME_REG2: - *s_out = "DW_FRAME_REG2"; - return DW_DLV_OK; - case DW_FRAME_REG3: - *s_out = "DW_FRAME_REG3"; - return DW_DLV_OK; - case DW_FRAME_REG4: - *s_out = "DW_FRAME_REG4"; - return DW_DLV_OK; - case DW_FRAME_REG5: - *s_out = "DW_FRAME_REG5"; - return DW_DLV_OK; - case DW_FRAME_REG6: - *s_out = "DW_FRAME_REG6"; - return DW_DLV_OK; - case DW_FRAME_REG7: - *s_out = "DW_FRAME_REG7"; - return DW_DLV_OK; - case DW_FRAME_REG8: - *s_out = "DW_FRAME_REG8"; - return DW_DLV_OK; - case DW_FRAME_REG9: - *s_out = "DW_FRAME_REG9"; - return DW_DLV_OK; - case DW_FRAME_REG10: - *s_out = "DW_FRAME_REG10"; - return DW_DLV_OK; - case DW_FRAME_REG11: - *s_out = "DW_FRAME_REG11"; - return DW_DLV_OK; - case DW_FRAME_REG12: - *s_out = "DW_FRAME_REG12"; - return DW_DLV_OK; - case DW_FRAME_REG13: - *s_out = "DW_FRAME_REG13"; - return DW_DLV_OK; - case DW_FRAME_REG14: - *s_out = "DW_FRAME_REG14"; - return DW_DLV_OK; - case DW_FRAME_REG15: - *s_out = "DW_FRAME_REG15"; - return DW_DLV_OK; - case DW_FRAME_REG16: - *s_out = "DW_FRAME_REG16"; - return DW_DLV_OK; - case DW_FRAME_REG17: - *s_out = "DW_FRAME_REG17"; - return DW_DLV_OK; - case DW_FRAME_REG18: - *s_out = "DW_FRAME_REG18"; - return DW_DLV_OK; - case DW_FRAME_REG19: - *s_out = "DW_FRAME_REG19"; - return DW_DLV_OK; - case DW_FRAME_REG20: - *s_out = "DW_FRAME_REG20"; - return DW_DLV_OK; - case DW_FRAME_REG21: - *s_out = "DW_FRAME_REG21"; - return DW_DLV_OK; - case DW_FRAME_REG22: - *s_out = "DW_FRAME_REG22"; - return DW_DLV_OK; - case DW_FRAME_REG23: - *s_out = "DW_FRAME_REG23"; - return DW_DLV_OK; - case DW_FRAME_REG24: - *s_out = "DW_FRAME_REG24"; - return DW_DLV_OK; - case DW_FRAME_REG25: - *s_out = "DW_FRAME_REG25"; - return DW_DLV_OK; - case DW_FRAME_REG26: - *s_out = "DW_FRAME_REG26"; - return DW_DLV_OK; - case DW_FRAME_REG27: - *s_out = "DW_FRAME_REG27"; - return DW_DLV_OK; - case DW_FRAME_REG28: - *s_out = "DW_FRAME_REG28"; - return DW_DLV_OK; - case DW_FRAME_REG29: - *s_out = "DW_FRAME_REG29"; - return DW_DLV_OK; - case DW_FRAME_REG30: - *s_out = "DW_FRAME_REG30"; - return DW_DLV_OK; - case DW_FRAME_REG31: - *s_out = "DW_FRAME_REG31"; - return DW_DLV_OK; - case DW_FRAME_FREG0: - *s_out = "DW_FRAME_FREG0"; - return DW_DLV_OK; - case DW_FRAME_FREG1: - *s_out = "DW_FRAME_FREG1"; - return DW_DLV_OK; - case DW_FRAME_FREG2: - *s_out = "DW_FRAME_FREG2"; - return DW_DLV_OK; - case DW_FRAME_FREG3: - *s_out = "DW_FRAME_FREG3"; - return DW_DLV_OK; - case DW_FRAME_FREG4: - *s_out = "DW_FRAME_FREG4"; - return DW_DLV_OK; - case DW_FRAME_FREG5: - *s_out = "DW_FRAME_FREG5"; - return DW_DLV_OK; - case DW_FRAME_FREG6: - *s_out = "DW_FRAME_FREG6"; - return DW_DLV_OK; - case DW_FRAME_FREG7: - *s_out = "DW_FRAME_FREG7"; - return DW_DLV_OK; - case DW_FRAME_FREG8: - *s_out = "DW_FRAME_FREG8"; - return DW_DLV_OK; - case DW_FRAME_FREG9: - *s_out = "DW_FRAME_FREG9"; - return DW_DLV_OK; - case DW_FRAME_FREG10: - *s_out = "DW_FRAME_FREG10"; - return DW_DLV_OK; - case DW_FRAME_FREG11: - *s_out = "DW_FRAME_FREG11"; - return DW_DLV_OK; - case DW_FRAME_FREG12: - *s_out = "DW_FRAME_FREG12"; - return DW_DLV_OK; - case DW_FRAME_FREG13: - *s_out = "DW_FRAME_FREG13"; - return DW_DLV_OK; - case DW_FRAME_FREG14: - *s_out = "DW_FRAME_FREG14"; - return DW_DLV_OK; - case DW_FRAME_FREG15: - *s_out = "DW_FRAME_FREG15"; - return DW_DLV_OK; - case DW_FRAME_FREG16: - *s_out = "DW_FRAME_FREG16"; - return DW_DLV_OK; - case DW_FRAME_FREG17: - *s_out = "DW_FRAME_FREG17"; - return DW_DLV_OK; - case DW_FRAME_FREG18: - *s_out = "DW_FRAME_FREG18"; - return DW_DLV_OK; - case DW_FRAME_FREG19: - *s_out = "DW_FRAME_FREG19"; - return DW_DLV_OK; - case DW_FRAME_FREG20: - *s_out = "DW_FRAME_FREG20"; - return DW_DLV_OK; - case DW_FRAME_FREG21: - *s_out = "DW_FRAME_FREG21"; - return DW_DLV_OK; - case DW_FRAME_FREG22: - *s_out = "DW_FRAME_FREG22"; - return DW_DLV_OK; - case DW_FRAME_FREG23: - *s_out = "DW_FRAME_FREG23"; - return DW_DLV_OK; - case DW_FRAME_FREG24: - *s_out = "DW_FRAME_FREG24"; - return DW_DLV_OK; - case DW_FRAME_FREG25: - *s_out = "DW_FRAME_FREG25"; - return DW_DLV_OK; - case DW_FRAME_FREG26: - *s_out = "DW_FRAME_FREG26"; - return DW_DLV_OK; - case DW_FRAME_FREG27: - *s_out = "DW_FRAME_FREG27"; - return DW_DLV_OK; - case DW_FRAME_FREG28: - *s_out = "DW_FRAME_FREG28"; - return DW_DLV_OK; - case DW_FRAME_FREG29: - *s_out = "DW_FRAME_FREG29"; - return DW_DLV_OK; - case DW_FRAME_FREG30: - *s_out = "DW_FRAME_FREG30"; - return DW_DLV_OK; - case DW_FRAME_HIGHEST_NORMAL_REGISTER: - *s_out = "DW_FRAME_HIGHEST_NORMAL_REGISTER"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_CHILDREN_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_CHILDREN_no: - *s_out = "DW_CHILDREN_no"; - return DW_DLV_OK; - case DW_CHILDREN_yes: - *s_out = "DW_CHILDREN_yes"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} -/* ARGSUSED */ -int -dwarf_get_ADDR_name (unsigned int val,const char ** s_out) -{ - switch (val) { - case DW_ADDR_none: - *s_out = "DW_ADDR_none"; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} - -/* END FILE */ diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_names.h b/usr/src/tools/ctf/dwarf/common/dwarf_names.h deleted file mode 100644 index 6edafa5fdd..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_names.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Generated routines, do not edit. */ -/* Generated on May 22 2011 03:05:33 */ - -/* BEGIN FILE */ - -extern int dwarf_get_TAG_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_children_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_FORM_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_AT_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_OP_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_ATE_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_DS_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_END_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_ATCF_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_ACCESS_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_VIS_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_VIRTUALITY_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_LANG_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_ID_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_CC_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_INL_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_ORD_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_DSC_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_LNS_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_LNE_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_ISA_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_MACINFO_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_CFA_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_EH_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_FRAME_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_CHILDREN_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_ADDR_name(unsigned int /*val_in*/, const char ** /*s_out */); - -/* END FILE */ diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_opaque.h b/usr/src/tools/ctf/dwarf/common/dwarf_opaque.h deleted file mode 100644 index b235a9c7b4..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_opaque.h +++ /dev/null @@ -1,339 +0,0 @@ -/* - - Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. - Portions Copyright (C) 2008-2010 Arxan Technologies, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* The versions applicable by section are: - DWARF2 DWARF3 DWARF4 - .debug_abbrev - - - - .debug_aranges 2 2 2 - .debug_frame 1 3 4 - .debug_info 2 3 4 - .debug_line 2 3 4 - .debug_loc - - - - .debug_macinfo - - - - .debug_pubtypes x 2 2 - .debug_pubnames 2 2 2 - .debug_ranges x - - - .debug_str - - - - .debug_types x x 4 -*/ - -#include - - -struct Dwarf_Die_s { - Dwarf_Byte_Ptr di_debug_info_ptr; - Dwarf_Abbrev_List di_abbrev_list; - Dwarf_CU_Context di_cu_context; - int di_abbrev_code; -}; - -struct Dwarf_Attribute_s { - Dwarf_Half ar_attribute; /* Attribute Value. */ - Dwarf_Half ar_attribute_form; /* Attribute Form. */ - Dwarf_Half ar_attribute_form_direct; - /* Identical to ar_attribute_form except that if - the original form uleb was DW_FORM_indirect, - ar_attribute_form_direct contains DW_FORM_indirect - but ar_attribute_form contains the true form. */ - - Dwarf_CU_Context ar_cu_context; - Dwarf_Small *ar_debug_info_ptr; - Dwarf_Attribute ar_next; -}; - -/* - This structure provides the context for a compilation unit. - Thus, it contains the Dwarf_Debug, cc_dbg, that this cu - belongs to. It contains the information in the compilation - unit header, cc_length, cc_version_stamp, cc_abbrev_offset, - and cc_address_size, in the .debug_info section for that cu. - In addition, it contains the count, cc_count_cu, of the cu - number of that cu in the list of cu's in the .debug_info. - The count starts at 1, ie cc_count_cu is 1 for the first cu, - 2 for the second and so on. This struct also contains a - pointer, cc_abbrev_table, to a list of pairs of abbrev code - and a pointer to the start of that abbrev - in the .debug_abbrev section. - - Each die will also contain a pointer to such a struct to - record the context for that die. - - Notice that a pointer to the CU DIE itself is - Dwarf_Off off2 = cu_context->cc_debug_info_offset; - cu_die_info_ptr = dbg->de_debug_info.dss_data + - off2 + _dwarf_length_of_cu_header(dbg, off2); - - **Updated by dwarf_next_cu_header in dwarf_die_deliv.c -*/ -struct Dwarf_CU_Context_s { - Dwarf_Debug cc_dbg; - /* The sum of cc_length, cc_length_size, and cc_extension_size - is the total length of the CU including its header. */ - Dwarf_Word cc_length; - /* cc_length_size is the size in bytes of an offset. - 4 for 32bit dwarf, 8 for 64bit dwarf (whether MIPS/IRIX - 64bit dwarf or standard 64bit dwarf using the extension - mechanism). */ - Dwarf_Small cc_length_size; - /* cc_extension_size is zero unless this is standard - DWARF3 and later 64bit dwarf using the extension mechanism. - If it is the DWARF3 and later 64bit dwarf cc_extension - size is 4. So for 32bit dwarf and MIPS/IRIX 64bit dwarf - cc_extension_size is zero. */ - Dwarf_Small cc_extension_size; - Dwarf_Half cc_version_stamp; - Dwarf_Sword cc_abbrev_offset; - Dwarf_Small cc_address_size; - /* cc_debug_info_offset is the offset in the section - of the CU header of this CU. Dwarf_Word - should be large enough. */ - Dwarf_Word cc_debug_info_offset; - Dwarf_Byte_Ptr cc_last_abbrev_ptr; - Dwarf_Hash_Table cc_abbrev_hash_table; - Dwarf_CU_Context cc_next; - /*unsigned char cc_offset_length; */ -}; - -/* Consolidates section-specific data in one place. - Section is an Elf specific term, intended as a general - term (for non-Elf objects some code must synthesize the - values somehow). - Makes adding more section-data much simpler. */ -struct Dwarf_Section_s { - Dwarf_Small * dss_data; - Dwarf_Unsigned dss_size; - Dwarf_Word dss_index; - /* dss_addr is the 'section address' which is only - non-zero for a GNU eh section. - Purpose: to handle DW_EH_PE_pcrel encoding. Leaving - it zero is fine for non-elf. */ - Dwarf_Addr dss_addr; - Dwarf_Small dss_data_was_malloc; - - /* For non-elf, leaving the following fields zero - will mean they are ignored. */ - /* dss_link should be zero unless a section has a link - to another (sh_link). Used to access relocation data for - a section (and for symtab section, access its strtab). */ - Dwarf_Word dss_link; - /* The following is used when reading .rela sections - (such sections appear in some .o files). */ - Dwarf_Half dss_reloc_index; /* Zero means ignore the reloc fields. */ - Dwarf_Small * dss_reloc_data; - Dwarf_Unsigned dss_reloc_size; - Dwarf_Addr dss_reloc_addr; - /* dss_reloc_symtab is the sh_link of a .rela to its .symtab, leave - it 0 if non-meaningful. */ - Dwarf_Addr dss_reloc_symtab; - /* dss_reloc_link should be zero unless a reloc section has a link - to another (sh_link). Used to access the symtab for relocations - a section. */ - Dwarf_Word dss_reloc_link; - /* Pointer to the elf symtab, used for elf .rela. Leave it 0 - if not relevant. */ - struct Dwarf_Section_s *dss_symtab; -}; - -/* Overview: if next_to_use== first, no error slots are used. - If next_to_use+1 (mod maxcount) == first the slots are all used -*/ -struct Dwarf_Harmless_s { - unsigned dh_maxcount; - unsigned dh_next_to_use; - unsigned dh_first; - unsigned dh_errs_count; - char ** dh_errors; -}; - -struct Dwarf_Debug_s { - /* All file access methods and support data - are hidden in this structure. - We get a pointer, callers control the lifetime of the - structure and contents. */ - struct Dwarf_Obj_Access_Interface_s *de_obj_file; - - Dwarf_Handler de_errhand; - Dwarf_Ptr de_errarg; - - /* - Context for the compilation_unit just read by a call to - dwarf_next_cu_header. **Updated by dwarf_next_cu_header in - dwarf_die_deliv.c */ - Dwarf_CU_Context de_cu_context; - - /* - Points to linked list of CU Contexts for the CU's already read. - These are only CU's read by dwarf_next_cu_header(). */ - Dwarf_CU_Context de_cu_context_list; - - /* - Points to the last CU Context added to the list by - dwarf_next_cu_header(). */ - Dwarf_CU_Context de_cu_context_list_end; - - /* - This is the list of CU contexts read for dwarf_offdie(). These - may read ahead of dwarf_next_cu_header(). */ - Dwarf_CU_Context de_offdie_cu_context; - Dwarf_CU_Context de_offdie_cu_context_end; - - /* Offset of last byte of last CU read. */ - Dwarf_Word de_info_last_offset; - - /* - Number of bytes in the length, and offset field in various - .debug_* sections. It's not very meaningful, and is - only used in one 'approximate' calculation. */ - Dwarf_Small de_length_size; - - /* number of bytes in a pointer of the target in various .debug_ - sections. 4 in 32bit, 8 in MIPS 64, ia64. */ - Dwarf_Small de_pointer_size; - - /* set at creation of a Dwarf_Debug to say if form_string should be - checked for valid length at every call. 0 means do the check. - non-zero means do not do the check. */ - Dwarf_Small de_assume_string_in_bounds; - - /* - Dwarf_Alloc_Hdr_s structs used to manage chunks that are - malloc'ed for each allocation type for structs. */ - struct Dwarf_Alloc_Hdr_s de_alloc_hdr[ALLOC_AREA_REAL_TABLE_MAX]; -#ifdef DWARF_SIMPLE_MALLOC - struct simple_malloc_record_s * de_simple_malloc_base; -#endif - - - /* - These fields are used to process debug_frame section. **Updated - by dwarf_get_fde_list in dwarf_frame.h */ - /* - Points to contiguous block of pointers to Dwarf_Cie_s structs. */ - Dwarf_Cie *de_cie_data; - /* Count of number of Dwarf_Cie_s structs. */ - Dwarf_Signed de_cie_count; - /* Keep eh (GNU) separate!. */ - Dwarf_Cie *de_cie_data_eh; - Dwarf_Signed de_cie_count_eh; - /* - Points to contiguous block of pointers to Dwarf_Fde_s structs. */ - Dwarf_Fde *de_fde_data; - /* Count of number of Dwarf_Fde_s structs. */ - Dwarf_Signed de_fde_count; - /* Keep eh (GNU) separate!. */ - Dwarf_Fde *de_fde_data_eh; - Dwarf_Signed de_fde_count_eh; - - struct Dwarf_Section_s de_debug_info; - struct Dwarf_Section_s de_debug_abbrev; - struct Dwarf_Section_s de_debug_line; - struct Dwarf_Section_s de_debug_loc; - struct Dwarf_Section_s de_debug_aranges; - struct Dwarf_Section_s de_debug_macinfo; - struct Dwarf_Section_s de_debug_pubnames; - struct Dwarf_Section_s de_debug_str; - struct Dwarf_Section_s de_debug_frame; - - /* gnu: the g++ eh_frame section */ - struct Dwarf_Section_s de_debug_frame_eh_gnu; - - struct Dwarf_Section_s de_debug_pubtypes; /* DWARF3 .debug_pubtypes */ - - struct Dwarf_Section_s de_debug_funcnames; - struct Dwarf_Section_s de_debug_typenames; /* SGI IRIX extension essentially - identical to DWARF3 .debug_pubtypes. */ - struct Dwarf_Section_s de_debug_varnames; - struct Dwarf_Section_s de_debug_weaknames; - struct Dwarf_Section_s de_debug_ranges; - - /* For non-elf, simply leave the following two structs zeroed and - they will be ignored. */ - struct Dwarf_Section_s de_elf_symtab; - struct Dwarf_Section_s de_elf_strtab; - - - void *(*de_copy_word) (void *, const void *, size_t); - unsigned char de_same_endian; - unsigned char de_elf_must_close; /* if non-zero, then - it was dwarf_init (not dwarf_elf_init) - so must elf_end() */ - - /* Default is DW_FRAME_INITIAL_VALUE from header. */ - Dwarf_Half de_frame_rule_initial_value; - - /* Default is DW_FRAME_LAST_REG_NUM. */ - Dwarf_Half de_frame_reg_rules_entry_count; - - Dwarf_Half de_frame_cfa_col_number; - Dwarf_Half de_frame_same_value_number; - Dwarf_Half de_frame_undefined_value_number; - - unsigned char de_big_endian_object; /* non-zero if big-endian - object opened. */ - - struct Dwarf_Harmless_s de_harmless_errors; -}; - -typedef struct Dwarf_Chain_s *Dwarf_Chain; -struct Dwarf_Chain_s { - void *ch_item; - Dwarf_Chain ch_next; -}; - - -#define CURRENT_VERSION_STAMP 2 /* DWARF2 */ -#define CURRENT_VERSION_STAMP3 3 /* DWARF3 */ -#define CURRENT_VERSION_STAMP4 4 /* DWARF4 */ - - /* Size of cu header version stamp field. */ -#define CU_VERSION_STAMP_SIZE sizeof(Dwarf_Half) - - /* Size of cu header address size field. */ -#define CU_ADDRESS_SIZE_SIZE sizeof(Dwarf_Small) - -void *_dwarf_memcpy_swap_bytes(void *s1, const void *s2, size_t len); - -#define ORIGINAL_DWARF_OFFSET_SIZE 4 -#define DISTINGUISHED_VALUE 0xffffffff -#define DISTINGUISHED_VALUE_OFFSET_SIZE 8 - -/* - We don't load the sections until they are needed. This function is - used to load the section. - */ -int _dwarf_load_section(Dwarf_Debug, - struct Dwarf_Section_s *, - Dwarf_Error *); diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_original_elf_init.c b/usr/src/tools/ctf/dwarf/common/dwarf_original_elf_init.c deleted file mode 100644 index a6d943da0a..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_original_elf_init.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - - Copyright (C) 2000,2001,2002,2005,2006 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. - Portions Copyright 2008-2010 Arxan Technologies, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - -#include "config.h" -#include "dwarf_incl.h" -#include "dwarf_elf_access.h" - -#ifdef HAVE_ELF_H -#include -#endif -#ifdef HAVE_LIBELF_H -#include -#else -#ifdef HAVE_LIBELF_LIBELF_H -#include -#endif -#endif - -#include -#include -#include -#include -#include - -#define DWARF_DBG_ERROR(dbg,errval,retval) \ - _dwarf_error(dbg, error, errval); return(retval); - -#define FALSE 0 -#define TRUE 1 - -static int -dwarf_elf_init_file_ownership(dwarf_elf_handle elf_file_pointer, - int libdwarf_owns_elf, - Dwarf_Unsigned access, - Dwarf_Handler errhand, - Dwarf_Ptr errarg, - Dwarf_Debug * ret_dbg, - Dwarf_Error * error); - - -/* - The basic dwarf initializer function for consumers using - libelf. - Return a libdwarf error code on error, return DW_DLV_OK - if this succeeds. -*/ -int -dwarf_init(int fd, - Dwarf_Unsigned access, - Dwarf_Handler errhand, - Dwarf_Ptr errarg, Dwarf_Debug * ret_dbg, Dwarf_Error * error) -{ - struct stat fstat_buf; - dwarf_elf_handle elf_file_pointer = 0; - /* ELF_C_READ is a portable value */ - Elf_Cmd what_kind_of_elf_read = ELF_C_READ; - -#if !defined(S_ISREG) -#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) -#endif - if (fstat(fd, &fstat_buf) != 0) { - DWARF_DBG_ERROR(NULL, DW_DLE_FSTAT_ERROR, DW_DLV_ERROR); - } - if (!S_ISREG(fstat_buf.st_mode)) { - DWARF_DBG_ERROR(NULL, DW_DLE_FSTAT_MODE_ERROR, DW_DLV_ERROR); - } - - if (access != DW_DLC_READ) { - DWARF_DBG_ERROR(NULL, DW_DLE_INIT_ACCESS_WRONG, DW_DLV_ERROR); - } - - elf_version(EV_CURRENT); - /* changed to mmap request per bug 281217. 6/95 */ -#ifdef HAVE_ELF_C_READ_MMAP - /* ELF_C_READ_MMAP is an SGI IRIX specific enum value from IRIX - libelf.h meaning read but use mmap */ - what_kind_of_elf_read = ELF_C_READ_MMAP; -#endif /* !HAVE_ELF_C_READ_MMAP */ - - elf_file_pointer = elf_begin(fd, what_kind_of_elf_read, 0); - if (elf_file_pointer == NULL) { - DWARF_DBG_ERROR(NULL, DW_DLE_ELF_BEGIN_ERROR, DW_DLV_ERROR); - } - - return dwarf_elf_init_file_ownership(elf_file_pointer, - TRUE, - access, - errhand, - errarg, - ret_dbg, - error); -} - -/* - An alternate dwarf setup call for consumers using - libelf. - When the caller has opened libelf already, so the - caller must free libelf. -*/ -int -dwarf_elf_init(dwarf_elf_handle elf_file_pointer, - Dwarf_Unsigned access, - Dwarf_Handler errhand, - Dwarf_Ptr errarg, - Dwarf_Debug * ret_dbg, Dwarf_Error * error) -{ - return dwarf_elf_init_file_ownership(elf_file_pointer, - FALSE, - access, - errhand, - errarg, - ret_dbg, - error); -} - - -/* - Initialize the ELF object access for libdwarf. - */ -static int -dwarf_elf_init_file_ownership(dwarf_elf_handle elf_file_pointer, - int libdwarf_owns_elf, - Dwarf_Unsigned access, - Dwarf_Handler errhand, - Dwarf_Ptr errarg, - Dwarf_Debug * ret_dbg, - Dwarf_Error * error) -{ - /* ELF is no longer tied to libdwarf. */ - Dwarf_Obj_Access_Interface *binary_interface = 0; - int res = DW_DLV_OK; - int err = 0; - - if (access != DW_DLC_READ) { - DWARF_DBG_ERROR(NULL, DW_DLE_INIT_ACCESS_WRONG, DW_DLV_ERROR); - } - - /* This allocates and fills in *binary_interface. */ - res = dwarf_elf_object_access_init( - elf_file_pointer, - libdwarf_owns_elf, - &binary_interface, - &err); - if(res != DW_DLV_OK){ - DWARF_DBG_ERROR(NULL, err, DW_DLV_ERROR); - } - - /* This mallocs space and returns pointer thru ret_dbg, - saving the binary interface in 'ret-dbg' */ - res = dwarf_object_init(binary_interface, errhand, errarg, - ret_dbg, error); - if(res != DW_DLV_OK){ - dwarf_elf_object_access_finish(binary_interface); - } - return res; -} - - -/* - Frees all memory that was not previously freed - by dwarf_dealloc. - Aside from certain categories. - - This is only applicable when dwarf_init() or dwarf_elf_init() - was used to init 'dbg'. -*/ -int -dwarf_finish(Dwarf_Debug dbg, Dwarf_Error * error) -{ - dwarf_elf_object_access_finish(dbg->de_obj_file); - - return dwarf_object_finish(dbg, error); -} - diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_print_lines.c b/usr/src/tools/ctf/dwarf/common/dwarf_print_lines.c deleted file mode 100644 index 30c4889ee5..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_print_lines.c +++ /dev/null @@ -1,737 +0,0 @@ -/* - - Copyright (C) 2000,2002,2004,2005,2006 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the Crittenden Lane address. -*/ - - - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include -#include "dwarf_line.h" - -/* FIXME Need to add prologue_end epilogue_begin isa fields. */ -static void -print_line_header(void) -{ - printf - (" s b e\n" - " t l s\n" - " m c e\n" - " section op col t k q\n" - " offset code address file line umn ? ? ?\n"); -} - -/* FIXME: print new line values: prologue_end epilogue_begin isa */ -static void -print_line_detail(char *prefix, - int opcode, - Dwarf_Unsigned address, - unsigned long file, - unsigned long line, - unsigned long column, - int is_stmt, int basic_block, int end_sequence, - int prologue_end, int epilogue_begin, int isa) -{ - printf("%-15s %2d 0x%08" DW_PR_DUx " " - "%2lu %4lu %2lu %1d %1d %1d\n", - prefix, - (int) opcode, - (Dwarf_Unsigned) address, - (unsigned long) file, - (unsigned long) line, - (unsigned long) column, - (int) is_stmt, (int) basic_block, (int) end_sequence); - -} - - -/* - return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR - If err_count_out is non-NULL, this is a special 'check' - call. -*/ -int -_dwarf_internal_printlines(Dwarf_Die die, Dwarf_Error * error, - int * err_count_out, int only_line_header) -{ - /* - This pointer is used to scan the portion of the .debug_line - section for the current cu. */ - Dwarf_Small *line_ptr = 0; - Dwarf_Small *orig_line_ptr = 0; - - /* - This points to the last byte of the .debug_line portion for the - current cu. */ - Dwarf_Small *line_ptr_end = 0; - - /* - Pointer to a DW_AT_stmt_list attribute in case it exists in the - die. */ - Dwarf_Attribute stmt_list_attr = 0; - - /* Pointer to DW_AT_comp_dir attribute in die. */ - Dwarf_Attribute comp_dir_attr = 0; - - /* Pointer to name of compilation directory. */ - Dwarf_Small *comp_dir = NULL; - - /* - Offset into .debug_line specified by a DW_AT_stmt_list - attribute. */ - Dwarf_Unsigned line_offset = 0; - - struct Line_Table_Prefix_s prefix; - - - /* These are the state machine state variables. */ - Dwarf_Addr address = 0; - Dwarf_Word file = 1; - Dwarf_Word line = 1; - Dwarf_Word column = 0; - Dwarf_Bool is_stmt = false; - Dwarf_Bool basic_block = false; - Dwarf_Bool end_sequence = false; - Dwarf_Bool prologue_end = false; - Dwarf_Bool epilogue_begin = false; - Dwarf_Small isa = 0; - - - Dwarf_Sword i=0; - - /* - This is the current opcode read from the statement program. */ - Dwarf_Small opcode=0; - - - /* - These variables are used to decode leb128 numbers. Leb128_num - holds the decoded number, and leb128_length is its length in - bytes. */ - Dwarf_Word leb128_num=0; - Dwarf_Word leb128_length=0; - Dwarf_Sword advance_line=0; - Dwarf_Half attrform = 0; - /* - This is the operand of the latest fixed_advance_pc extended - opcode. */ - Dwarf_Half fixed_advance_pc=0; - - /* In case there are wierd bytes 'after' the line table - * prologue this lets us print something. This is a gcc - * compiler bug and we expect the bytes count to be 12. - */ - Dwarf_Small* bogus_bytes_ptr = 0; - Dwarf_Unsigned bogus_bytes_count = 0; - - - /* The Dwarf_Debug this die belongs to. */ - Dwarf_Debug dbg=0; - int resattr = DW_DLV_ERROR; - int lres = DW_DLV_ERROR; - int res = DW_DLV_ERROR; - - /* ***** BEGIN CODE ***** */ - - if (error != NULL) { - *error = NULL; - } - - CHECK_DIE(die, DW_DLV_ERROR); - dbg = die->di_cu_context->cc_dbg; - - res = _dwarf_load_section(dbg, &dbg->de_debug_line,error); - if (res != DW_DLV_OK) { - return res; - } - - resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error); - if (resattr != DW_DLV_OK) { - return resattr; - } - - - /* The list of relevant FORMs is small. - DW_FORM_data4, DW_FORM_data8, DW_FORM_sec_offset - */ - lres = dwarf_whatform(stmt_list_attr,&attrform,error); - if (lres != DW_DLV_OK) { - return lres; - } - if (attrform != DW_FORM_data4 && attrform != DW_FORM_data8 && - attrform != DW_FORM_sec_offset ) { - _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); - return (DW_DLV_ERROR); - } - lres = dwarf_global_formref(stmt_list_attr, &line_offset, error); - if (lres != DW_DLV_OK) { - return lres; - } - - if (line_offset >= dbg->de_debug_line.dss_size) { - _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); - return (DW_DLV_ERROR); - } - orig_line_ptr = dbg->de_debug_line.dss_data; - line_ptr = dbg->de_debug_line.dss_data + line_offset; - dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR); - - /* - If die has DW_AT_comp_dir attribute, get the string that names - the compilation directory. */ - resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error); - if (resattr == DW_DLV_ERROR) { - return resattr; - } - if (resattr == DW_DLV_OK) { - int cres = DW_DLV_ERROR; - char *cdir = 0; - - cres = dwarf_formstring(comp_dir_attr, &cdir, error); - if (cres == DW_DLV_ERROR) { - return cres; - } else if (cres == DW_DLV_OK) { - comp_dir = (Dwarf_Small *) cdir; - } - } - if (resattr == DW_DLV_OK) { - dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR); - } - - dwarf_init_line_table_prefix(&prefix); - { - Dwarf_Small *line_ptr_out = 0; - int dres = dwarf_read_line_table_prefix(dbg, - line_ptr,dbg->de_debug_line.dss_size - line_offset, - &line_ptr_out, - &prefix, - &bogus_bytes_ptr, - &bogus_bytes_count, - error, - err_count_out); - if (dres == DW_DLV_ERROR) { - dwarf_free_line_table_prefix(&prefix); - return dres; - } - if (dres == DW_DLV_NO_ENTRY) { - dwarf_free_line_table_prefix(&prefix); - return dres; - } - line_ptr_end = prefix.pf_line_ptr_end; - line_ptr = line_ptr_out; - } - if(only_line_header) { - /* Just checking for header errors, nothing more here.*/ - dwarf_free_line_table_prefix(&prefix); - return DW_DLV_OK; - } - - - printf("total line info length %ld bytes, " - "line offset 0x%" DW_PR_DUx " %" DW_PR_DSd "\n", - (long) prefix.pf_total_length, - (Dwarf_Unsigned) line_offset, - (Dwarf_Signed) line_offset); - printf("line table version %d\n",(int) prefix.pf_version); - printf("line table length field length %d prologue length %d\n", - (int)prefix.pf_length_field_length, - (int)prefix.pf_prologue_length); - printf("compilation_directory %s\n", - comp_dir ? ((char *) comp_dir) : ""); - - printf(" min instruction length %d\n", - (int) prefix.pf_minimum_instruction_length); - printf(" default is stmt %d\n", (int) - prefix.pf_default_is_stmt); - printf(" line base %d\n", (int) - prefix.pf_line_base); - printf(" line_range %d\n", (int) - prefix.pf_line_range); - printf(" opcode base %d\n", (int) - prefix.pf_opcode_base); - printf(" standard opcode count %d\n", (int) - prefix.pf_std_op_count); - - for (i = 1; i < prefix.pf_opcode_base; i++) { - printf(" opcode[%2d] length %d\n", (int) i, - (int) prefix.pf_opcode_length_table[i - 1]); - } - printf(" include directories count %d\n", (int) - prefix.pf_include_directories_count); - - - for (i = 0; i < prefix.pf_include_directories_count; ++i) { - printf(" include dir[%d] %s\n", - (int) i, prefix.pf_include_directories[i]); - } - printf(" files count %d\n", (int) - prefix.pf_files_count); - - for (i = 0; i < prefix.pf_files_count; ++i) { - struct Line_Table_File_Entry_s *lfile = - prefix.pf_line_table_file_entries + i; - - Dwarf_Unsigned tlm2 = lfile->lte_last_modification_time; - Dwarf_Unsigned di = lfile->lte_directory_index; - Dwarf_Unsigned fl = lfile->lte_length_of_file; - - printf(" file[%d] %s (file-number: %d) \n", - (int) i, (char *) lfile->lte_filename, - (int)(i+1)); - - printf(" dir index %d\n", (int) di); - { - time_t tt = (time_t) tlm2; - - printf(" last time 0x%x %s", /* ctime supplies - newline */ - (unsigned) tlm2, ctime(&tt)); - } - printf(" file length %ld 0x%lx\n", - (long) fl, (unsigned long) fl); - - - } - - - { - Dwarf_Unsigned offset = 0; - if(bogus_bytes_count > 0) { - Dwarf_Unsigned wcount = bogus_bytes_count; - Dwarf_Unsigned boffset = bogus_bytes_ptr - orig_line_ptr; - printf("*** DWARF CHECK: the line table prologue header_length " - " is %" DW_PR_DUu " too high, we pretend it is smaller." - "Section offset: %" DW_PR_DUu " (0x%" DW_PR_DUx ") ***\n", - wcount, boffset,boffset); - *err_count_out += 1; - } - offset = line_ptr - orig_line_ptr; - - printf(" statement prog offset in section: %" DW_PR_DUu " 0x%" DW_PR_DUx "\n", - offset, offset); - } - - /* Initialize the part of the state machine dependent on the - prefix. */ - is_stmt = prefix.pf_default_is_stmt; - - - print_line_header(); - /* Start of statement program. */ - while (line_ptr < line_ptr_end) { - int type = 0; - - printf(" [0x%06" DW_PR_DSx "] ", - (Dwarf_Signed) (line_ptr - orig_line_ptr)); - opcode = *(Dwarf_Small *) line_ptr; - line_ptr++; - /* 'type' is the output */ - WHAT_IS_OPCODE(type, opcode, prefix.pf_opcode_base, - prefix.pf_opcode_length_table, line_ptr, - prefix.pf_std_op_count); - - if (type == LOP_DISCARD) { - int oc; - int opcnt = prefix.pf_opcode_length_table[opcode]; - - printf("*** DWARF CHECK: DISCARD standard opcode %d " - "with %d operands: " - "not understood.", opcode, opcnt); - *err_count_out += 1; - for (oc = 0; oc < opcnt; oc++) { - /* - * Read and discard operands we don't - * understand. - * Arbitrary choice of unsigned read. - * Signed read would work as well. - */ - Dwarf_Unsigned utmp2; - - DECODE_LEB128_UWORD(line_ptr, utmp2); - printf(" %" DW_PR_DUu " (0x%" DW_PR_DUx ")", - (Dwarf_Unsigned) utmp2, - (Dwarf_Unsigned) utmp2); - } - - printf("***\n"); - /* do nothing, necessary ops done */ - } else if (type == LOP_SPECIAL) { - /* This op code is a special op in the object, no matter - that it might fall into the standard op range in this - compile Thatis, these are special opcodes between - special_opcode_base and MAX_LINE_OP_CODE. (including - special_opcode_base and MAX_LINE_OP_CODE) */ - char special[50]; - unsigned origop = opcode; - - opcode = opcode - prefix.pf_opcode_base; - address = address + prefix.pf_minimum_instruction_length * - (opcode / prefix.pf_line_range); - line = - line + prefix.pf_line_base + - opcode % prefix.pf_line_range; - - sprintf(special, "Specialop %3u", origop); - print_line_detail(special, - opcode, address, (int) file, line, column, - is_stmt, basic_block, end_sequence, - prologue_end, epilogue_begin, isa); - - basic_block = false; - - } else if (type == LOP_STANDARD) { - switch (opcode) { - - case DW_LNS_copy:{ - - print_line_detail("DW_LNS_copy", - opcode, address, file, line, - column, is_stmt, basic_block, - end_sequence, prologue_end, - epilogue_begin, isa); - - basic_block = false; - break; - } - - case DW_LNS_advance_pc:{ - Dwarf_Unsigned utmp2; - - - DECODE_LEB128_UWORD(line_ptr, utmp2); - printf("DW_LNS_advance_pc val %" DW_PR_DSd " 0x%" DW_PR_DUx "\n", - (Dwarf_Signed) (Dwarf_Word) utmp2, - (Dwarf_Unsigned) (Dwarf_Word) utmp2); - leb128_num = (Dwarf_Word) utmp2; - address = - address + - prefix.pf_minimum_instruction_length * - leb128_num; - break; - } - - case DW_LNS_advance_line:{ - Dwarf_Signed stmp; - - - DECODE_LEB128_SWORD(line_ptr, stmp); - advance_line = (Dwarf_Sword) stmp; - printf("DW_LNS_advance_line val %" DW_PR_DSd " 0x%" DW_PR_DSx "\n", - (Dwarf_Signed) advance_line, - (Dwarf_Signed) advance_line); - line = line + advance_line; - break; - } - - case DW_LNS_set_file:{ - Dwarf_Unsigned utmp2; - - - DECODE_LEB128_UWORD(line_ptr, utmp2); - file = (Dwarf_Word) utmp2; - printf("DW_LNS_set_file %ld\n", (long) file); - break; - } - - case DW_LNS_set_column:{ - Dwarf_Unsigned utmp2; - - - DECODE_LEB128_UWORD(line_ptr, utmp2); - column = (Dwarf_Word) utmp2; - printf("DW_LNS_set_column val %" DW_PR_DSd " 0x%" DW_PR_DSx "\n", - (Dwarf_Signed) column, (Dwarf_Signed) column); - break; - } - - case DW_LNS_negate_stmt:{ - is_stmt = !is_stmt; - printf("DW_LNS_negate_stmt\n"); - break; - } - - case DW_LNS_set_basic_block:{ - - printf("DW_LNS_set_basic_block\n"); - basic_block = true; - break; - } - - case DW_LNS_const_add_pc:{ - opcode = MAX_LINE_OP_CODE - prefix.pf_opcode_base; - address = - address + - prefix.pf_minimum_instruction_length * (opcode / - prefix. - pf_line_range); - - printf("DW_LNS_const_add_pc new address 0x%" DW_PR_DSx "\n", - (Dwarf_Signed) address); - break; - } - - case DW_LNS_fixed_advance_pc:{ - - READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half, - line_ptr, sizeof(Dwarf_Half)); - line_ptr += sizeof(Dwarf_Half); - address = address + fixed_advance_pc; - printf("DW_LNS_fixed_advance_pc val %" DW_PR_DSd - " 0x%" DW_PR_DSx " new address 0x%" DW_PR_DSx "\n", - (Dwarf_Signed) fixed_advance_pc, - (Dwarf_Signed) fixed_advance_pc, - (Dwarf_Signed) address); - break; - } - case DW_LNS_set_prologue_end:{ - - prologue_end = true; - printf("DW_LNS_set_prologue_end set true.\n"); - break; - - - } - /* New in DWARF3 */ - case DW_LNS_set_epilogue_begin:{ - epilogue_begin = true; - printf("DW_LNS_set_epilogue_begin set true.\n"); - break; - } - - /* New in DWARF3 */ - case DW_LNS_set_isa:{ - Dwarf_Unsigned utmp2; - - DECODE_LEB128_UWORD(line_ptr, utmp2); - isa = utmp2; - printf("DW_LNS_set_isa new value 0x%" DW_PR_DUx ".\n", - (Dwarf_Unsigned) utmp2); - if (isa != utmp2) { - /* The value of the isa did not fit in our - local so we record it wrong. declare an - error. */ - dwarf_free_line_table_prefix(&prefix); - - _dwarf_error(dbg, error, - DW_DLE_LINE_NUM_OPERANDS_BAD); - return (DW_DLV_ERROR); - } - break; - } - } - - - } else if (type == LOP_EXTENDED) { - Dwarf_Unsigned utmp3 = 0; - Dwarf_Word instr_length = 0; - Dwarf_Small ext_opcode = 0; - - DECODE_LEB128_UWORD(line_ptr, utmp3); - instr_length = (Dwarf_Word) utmp3; - ext_opcode = *(Dwarf_Small *) line_ptr; - line_ptr++; - switch (ext_opcode) { - - case DW_LNE_end_sequence:{ - end_sequence = true; - - print_line_detail("DW_LNE_end_sequence extended", - opcode, address, file, line, - column, is_stmt, basic_block, - end_sequence, prologue_end, - epilogue_begin, isa); - - address = 0; - file = 1; - line = 1; - column = 0; - is_stmt = prefix.pf_default_is_stmt; - basic_block = false; - end_sequence = false; - prologue_end = false; - epilogue_begin = false; - - - break; - } - - case DW_LNE_set_address:{ - { - READ_UNALIGNED(dbg, address, Dwarf_Addr, - line_ptr, - die->di_cu_context->cc_address_size); - - line_ptr += die->di_cu_context->cc_address_size; - printf("DW_LNE_set_address address 0x%" DW_PR_DUx "\n", - (Dwarf_Unsigned) address); - } - - break; - } - - case DW_LNE_define_file:{ - Dwarf_Unsigned di = 0; - Dwarf_Unsigned tlm = 0; - Dwarf_Unsigned fl = 0; - - Dwarf_Small *fn = (Dwarf_Small *) line_ptr; - line_ptr = line_ptr + strlen((char *) line_ptr) + 1; - - di = _dwarf_decode_u_leb128(line_ptr, - &leb128_length); - line_ptr = line_ptr + leb128_length; - - tlm = _dwarf_decode_u_leb128(line_ptr, - &leb128_length); - line_ptr = line_ptr + leb128_length; - - fl = _dwarf_decode_u_leb128(line_ptr, - &leb128_length); - line_ptr = line_ptr + leb128_length; - - - printf("DW_LNE_define_file %s \n", fn); - printf(" dir index %d\n", (int) di); - { - time_t tt3 = (time_t) tlm; - - /* ctime supplies newline */ - printf(" last time 0x%x %s", - (unsigned) tlm, ctime(&tt3)); - } - printf(" file length %ld 0x%lx\n", - (long) fl, (unsigned long) fl); - - break; - } - - default:{ - /* This is an extended op code we do not know about, - other than we know now many bytes it is - (and the op code and the bytes of operand). */ - - Dwarf_Unsigned remaining_bytes = instr_length -1; - if(instr_length < 1 || remaining_bytes > DW_LNE_LEN_MAX) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, - DW_DLE_LINE_EXT_OPCODE_BAD); - return (DW_DLV_ERROR); - } - printf("DW_LNE extended op 0x%x ",ext_opcode); - printf("Bytecount: " DW_PR_DUu , instr_length); - if(remaining_bytes > 0) { - printf(" linedata: 0x"); - while (remaining_bytes > 0) { - printf("%02x",(unsigned char)(*(line_ptr))); - line_ptr++; - remaining_bytes--; - } - } - printf("\n"); - } - break; - } - - } - } - - dwarf_free_line_table_prefix(&prefix); - return (DW_DLV_OK); -} - -/* - This is support for dwarfdump: making it possible - for clients wanting line detail info on stdout - to get that detail without including internal libdwarf - header information. - Caller passes in compilation unit DIE. - The _dwarf_ version is obsolete (though supported for - compatibility). - The dwarf_ version is preferred. - The functions are intentionally identical: having - _dwarf_print_lines call dwarf_print_lines might - better emphasize they are intentionally identical, but - that seemed slightly silly given how short the functions are. - Interface adds error_count (output value) February 2009. -*/ -int -dwarf_print_lines(Dwarf_Die die, Dwarf_Error * error,int *error_count) -{ - int only_line_header = 0; - int res = _dwarf_internal_printlines(die, error, - error_count, - only_line_header); - if (res != DW_DLV_OK) { - return res; - } - return res; -} -int -_dwarf_print_lines(Dwarf_Die die, Dwarf_Error * error) -{ - int only_line_header = 0; - int err_count = 0; - int res = _dwarf_internal_printlines(die, error, - &err_count, - only_line_header); - /* No way to get error count back in this interface */ - if (res != DW_DLV_OK) { - return res; - } - return res; -} - -/* The check is in case we are not printing full line data, - this gets some of the issues noted with .debug_line, - but not all. Call dwarf_print_lines() to get all issues. - Intended for apps like dwarfdump. -*/ -void -dwarf_check_lineheader(Dwarf_Die die, int *err_count_out) -{ - Dwarf_Error err; - int only_line_header = 1; - _dwarf_internal_printlines(die, &err,err_count_out, - only_line_header); - return; -} - diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_pubtypes.c b/usr/src/tools/ctf/dwarf/common/dwarf_pubtypes.c deleted file mode 100644 index 330c1c6adc..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_pubtypes.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - - Copyright (C) 2000,2002,2004,2005 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - -/* Reads DWARF3 .debug_pubtypes section. */ - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include "dwarf_types.h" -#include "dwarf_global.h" - -int -dwarf_get_pubtypes(Dwarf_Debug dbg, - Dwarf_Type ** types, - Dwarf_Signed * ret_type_count, Dwarf_Error * error) -{ - int res = _dwarf_load_section(dbg, &dbg->de_debug_pubtypes,error); - if (res != DW_DLV_OK) { - return res; - } - - return _dwarf_internal_get_pubnames_like_data(dbg, - dbg->de_debug_pubtypes.dss_data, - dbg->de_debug_pubtypes.dss_size, - (Dwarf_Global **) types, /* Type punning for sections - with identical format. */ - ret_type_count, error, - DW_DLA_PUBTYPES_CONTEXT, - DW_DLA_GLOBAL, /* We don't have DW_DLA_PUBTYPES, - so use DW_DLA_GLOBAL. */ - DW_DLE_DEBUG_PUBTYPES_LENGTH_BAD, - DW_DLE_DEBUG_PUBTYPES_VERSION_ERROR); -} - -/* Deallocating fully requires deallocating the list - and all entries. But some internal data is - not exposed, so we need a function with internal knowledge. -*/ - -void -dwarf_pubtypes_dealloc(Dwarf_Debug dbg, Dwarf_Type * dwgl, - Dwarf_Signed count) -{ - _dwarf_internal_globals_dealloc(dbg, - (Dwarf_Global *) dwgl, - count, - DW_DLA_PUBTYPES_CONTEXT, - DW_DLA_GLOBAL, /* We don't have DW_DLA_PUBTYPES, - so use DW_DLA_GLOBAL. */ - DW_DLA_LIST); - return; -} - - - -int -dwarf_pubtypename(Dwarf_Type type_in, char **ret_name, - Dwarf_Error * error) -{ - Dwarf_Global type = (Dwarf_Global) type_in; - if (type == NULL) { - _dwarf_error(NULL, error, DW_DLE_TYPE_NULL); - return (DW_DLV_ERROR); - } - *ret_name = (char *) (type->gl_name); - return DW_DLV_OK; -} - - -int -dwarf_pubtype_type_die_offset(Dwarf_Type type_in, - Dwarf_Off * ret_offset, - Dwarf_Error * error) -{ - Dwarf_Global type = (Dwarf_Global) type_in; - - return dwarf_global_die_offset(type, ret_offset, error); -} - - -int -dwarf_pubtype_cu_offset(Dwarf_Type type_in, - Dwarf_Off * ret_offset, Dwarf_Error * error) -{ - Dwarf_Global type = (Dwarf_Global) type_in; - - return dwarf_global_cu_offset(type, ret_offset, error); - -} - - -int -dwarf_pubtype_name_offsets(Dwarf_Type type_in, - char **returned_name, - Dwarf_Off * die_offset, - Dwarf_Off * cu_die_offset, - Dwarf_Error * error) -{ - Dwarf_Global type = (Dwarf_Global) type_in; - - return dwarf_global_name_offsets(type, - returned_name, - die_offset, cu_die_offset, error); -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_query.c b/usr/src/tools/ctf/dwarf/common/dwarf_query.c deleted file mode 100644 index 3f21abd039..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_query.c +++ /dev/null @@ -1,789 +0,0 @@ -/* - - Copyright (C) 2000,2002,2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the Crittenden Lane address. -*/ - - - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include "dwarf_die_deliv.h" - -/* This is normally reliable. -But not always. -If different compilation -units have different address sizes -this may not give the correct value in all contexts. -If the Elf offset size != address_size -(for example if address_size = 4 but recorded in elf64 object) -this may not give the correct value in all contexts. -*/ -int -dwarf_get_address_size(Dwarf_Debug dbg, - Dwarf_Half * ret_addr_size, Dwarf_Error * error) -{ - Dwarf_Half address_size = 0; - - if (dbg == 0) { - _dwarf_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - address_size = dbg->de_pointer_size; - *ret_addr_size = address_size; - return DW_DLV_OK; -} - -/* This will be correct in all contexts where the - CU context of a DIE is known. -*/ -int -dwarf_get_die_address_size(Dwarf_Die die, - Dwarf_Half * ret_addr_size, Dwarf_Error * error) -{ - Dwarf_Half address_size = 0; - CHECK_DIE(die, DW_DLV_ERROR); - address_size = die->di_cu_context->cc_address_size; - *ret_addr_size = address_size; - return DW_DLV_OK; -} - -int -dwarf_dieoffset(Dwarf_Die die, - Dwarf_Off * ret_offset, Dwarf_Error * error) -{ - CHECK_DIE(die, DW_DLV_ERROR); - - *ret_offset = (die->di_debug_info_ptr - - die->di_cu_context->cc_dbg->de_debug_info.dss_data); - return DW_DLV_OK; -} - - -/* - This function returns the offset of - the die relative to the start of its - compilation-unit rather than .debug_info. - Returns DW_DLV_ERROR on error. -*/ -int -dwarf_die_CU_offset(Dwarf_Die die, - Dwarf_Off * cu_off, Dwarf_Error * error) -{ - Dwarf_CU_Context cu_context = 0; - - CHECK_DIE(die, DW_DLV_ERROR); - cu_context = die->di_cu_context; - - *cu_off = - (die->di_debug_info_ptr - cu_context->cc_dbg->de_debug_info.dss_data - - cu_context->cc_debug_info_offset); - return DW_DLV_OK; -} - -/* - This function returns the global offset - (meaning the section offset) and length of - the CU that this die is a part of. - Used for correctness checking by dwarfdump. -*/ -int -dwarf_die_CU_offset_range(Dwarf_Die die, - Dwarf_Off * cu_off, - Dwarf_Off * cu_length, - Dwarf_Error * error) -{ - Dwarf_CU_Context cu_context = 0; - - CHECK_DIE(die, DW_DLV_ERROR); - cu_context = die->di_cu_context; - - *cu_off = cu_context->cc_debug_info_offset; - *cu_length = cu_context->cc_length + cu_context->cc_length_size - + cu_context->cc_extension_size; - return DW_DLV_OK; -} - - - -int -dwarf_tag(Dwarf_Die die, Dwarf_Half * tag, Dwarf_Error * error) -{ - CHECK_DIE(die, DW_DLV_ERROR); - *tag = (die->di_abbrev_list->ab_tag); - return DW_DLV_OK; -} - - -int -dwarf_attrlist(Dwarf_Die die, - Dwarf_Attribute ** attrbuf, - Dwarf_Signed * attrcnt, Dwarf_Error * error) -{ - Dwarf_Word attr_count = 0; - Dwarf_Word i = 0; - Dwarf_Half attr = 0; - Dwarf_Half attr_form = 0; - Dwarf_Byte_Ptr abbrev_ptr = 0; - Dwarf_Abbrev_List abbrev_list = 0; - Dwarf_Attribute new_attr = 0; - Dwarf_Attribute head_attr = NULL; - Dwarf_Attribute curr_attr = NULL; - Dwarf_Attribute *attr_ptr = 0; - Dwarf_Debug dbg = 0; - Dwarf_Byte_Ptr info_ptr = 0; - - CHECK_DIE(die, DW_DLV_ERROR); - dbg = die->di_cu_context->cc_dbg; - - abbrev_list = _dwarf_get_abbrev_for_code(die->di_cu_context, - die->di_abbrev_list-> - ab_code); - if (abbrev_list == NULL) { - _dwarf_error(dbg, error, DW_DLE_DIE_ABBREV_BAD); - return (DW_DLV_ERROR); - } - abbrev_ptr = abbrev_list->ab_abbrev_ptr; - - info_ptr = die->di_debug_info_ptr; - SKIP_LEB128_WORD(info_ptr); - - do { - Dwarf_Unsigned utmp2; - - DECODE_LEB128_UWORD(abbrev_ptr, utmp2); - attr = (Dwarf_Half) utmp2; - DECODE_LEB128_UWORD(abbrev_ptr, utmp2); - attr_form = (Dwarf_Half) utmp2; - - if (attr != 0) { - new_attr = - (Dwarf_Attribute) _dwarf_get_alloc(dbg, DW_DLA_ATTR, 1); - if (new_attr == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - new_attr->ar_attribute = attr; - new_attr->ar_attribute_form_direct = attr_form; - new_attr->ar_attribute_form = attr_form; - if (attr_form == DW_FORM_indirect) { - Dwarf_Unsigned utmp6; - - /* DECODE_LEB128_UWORD does info_ptr update */ - DECODE_LEB128_UWORD(info_ptr, utmp6); - attr_form = (Dwarf_Half) utmp6; - new_attr->ar_attribute_form = attr_form; - } - new_attr->ar_cu_context = die->di_cu_context; - new_attr->ar_debug_info_ptr = info_ptr; - - { - Dwarf_Unsigned sov = _dwarf_get_size_of_val(dbg, - attr_form, - die->di_cu_context->cc_address_size, - info_ptr, - die->di_cu_context->cc_length_size); - info_ptr += sov; - } - - - if (head_attr == NULL) - head_attr = curr_attr = new_attr; - else { - curr_attr->ar_next = new_attr; - curr_attr = new_attr; - } - attr_count++; - } - } while (attr != 0 || attr_form != 0); - - if (attr_count == 0) { - *attrbuf = NULL; - *attrcnt = 0; - return (DW_DLV_NO_ENTRY); - } - - attr_ptr = (Dwarf_Attribute *) - _dwarf_get_alloc(dbg, DW_DLA_LIST, attr_count); - if (attr_ptr == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - curr_attr = head_attr; - for (i = 0; i < attr_count; i++) { - *(attr_ptr + i) = curr_attr; - curr_attr = curr_attr->ar_next; - } - - *attrbuf = attr_ptr; - *attrcnt = attr_count; - return (DW_DLV_OK); -} - - -/* - This function takes a die, and an attr, and returns - a pointer to the start of the value of that attr in - the given die in the .debug_info section. The form - is returned in *attr_form. - - Returns NULL on error, or if attr is not found. - However, *attr_form is 0 on error, and positive - otherwise. -*/ -static Dwarf_Byte_Ptr -_dwarf_get_value_ptr(Dwarf_Die die, - Dwarf_Half attr, Dwarf_Half * attr_form) -{ - Dwarf_Byte_Ptr abbrev_ptr = 0; - Dwarf_Abbrev_List abbrev_list; - Dwarf_Half curr_attr = 0; - Dwarf_Half curr_attr_form = 0; - Dwarf_Byte_Ptr info_ptr = 0; - - abbrev_list = _dwarf_get_abbrev_for_code(die->di_cu_context, - die->di_abbrev_list->ab_code); - if (abbrev_list == NULL) { - *attr_form = 0; - return (NULL); - } - abbrev_ptr = abbrev_list->ab_abbrev_ptr; - - info_ptr = die->di_debug_info_ptr; - SKIP_LEB128_WORD(info_ptr); - - do { - Dwarf_Unsigned utmp3; - - DECODE_LEB128_UWORD(abbrev_ptr, utmp3); - curr_attr = (Dwarf_Half) utmp3; - DECODE_LEB128_UWORD(abbrev_ptr, utmp3); - curr_attr_form = (Dwarf_Half) utmp3; - if (curr_attr_form == DW_FORM_indirect) { - Dwarf_Unsigned utmp6; - - /* DECODE_LEB128_UWORD updates info_ptr */ - DECODE_LEB128_UWORD(info_ptr, utmp6); - curr_attr_form = (Dwarf_Half) utmp6; - } - - if (curr_attr == attr) { - *attr_form = curr_attr_form; - return (info_ptr); - } - - info_ptr += _dwarf_get_size_of_val(die->di_cu_context->cc_dbg, - curr_attr_form, - die->di_cu_context->cc_address_size, - info_ptr, - die->di_cu_context->cc_length_size); - } while (curr_attr != 0 || curr_attr_form != 0); - - *attr_form = 1; - return (NULL); -} - - -int -dwarf_diename(Dwarf_Die die, char **ret_name, Dwarf_Error * error) -{ - Dwarf_Half attr_form = 0; - Dwarf_Debug dbg = 0; - Dwarf_Byte_Ptr info_ptr = 0; - Dwarf_Unsigned string_offset = 0; - int res = DW_DLV_ERROR; - - CHECK_DIE(die, DW_DLV_ERROR); - - info_ptr = _dwarf_get_value_ptr(die, DW_AT_name, &attr_form); - if (info_ptr == NULL) { - if (attr_form == 0) { - _dwarf_error(die->di_cu_context->cc_dbg, error, - DW_DLE_DIE_BAD); - return (DW_DLV_ERROR); - } - return DW_DLV_NO_ENTRY; - } - - if (attr_form == DW_FORM_string) { - *ret_name = (char *) (info_ptr); - return DW_DLV_OK; - } - - dbg = die->di_cu_context->cc_dbg; - if (attr_form != DW_FORM_strp) { - _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD); - return (DW_DLV_ERROR); - } - - READ_UNALIGNED(dbg, string_offset, Dwarf_Unsigned, - info_ptr, die->di_cu_context->cc_length_size); - - if (string_offset >= dbg->de_debug_str.dss_size) { - _dwarf_error(dbg, error, DW_DLE_STRING_OFFSET_BAD); - return (DW_DLV_ERROR); - } - - res = _dwarf_load_section(dbg, &dbg->de_debug_str,error); - if (res != DW_DLV_OK) { - return res; - } - - *ret_name = (char *) (dbg->de_debug_str.dss_data + string_offset); - return DW_DLV_OK; -} - - -int -dwarf_hasattr(Dwarf_Die die, - Dwarf_Half attr, - Dwarf_Bool * return_bool, Dwarf_Error * error) -{ - Dwarf_Half attr_form = 0; - - CHECK_DIE(die, DW_DLV_ERROR); - - if (_dwarf_get_value_ptr(die, attr, &attr_form) == NULL) { - if (attr_form == 0) { - _dwarf_error(die->di_cu_context->cc_dbg, error, - DW_DLE_DIE_BAD); - return (DW_DLV_ERROR); - } - *return_bool = false; - return DW_DLV_OK; - } - - *return_bool = (true); - return DW_DLV_OK; -} - - -int -dwarf_attr(Dwarf_Die die, - Dwarf_Half attr, - Dwarf_Attribute * ret_attr, Dwarf_Error * error) -{ - Dwarf_Half attr_form = 0; - Dwarf_Attribute attrib = 0; - Dwarf_Byte_Ptr info_ptr = 0; - Dwarf_Debug dbg = 0; - - CHECK_DIE(die, DW_DLV_ERROR); - dbg = die->di_cu_context->cc_dbg; - - info_ptr = _dwarf_get_value_ptr(die, attr, &attr_form); - if (info_ptr == NULL) { - if (attr_form == 0) { - _dwarf_error(dbg, error, DW_DLE_DIE_BAD); - return (DW_DLV_ERROR); - } - return DW_DLV_NO_ENTRY; - } - - attrib = (Dwarf_Attribute) _dwarf_get_alloc(dbg, DW_DLA_ATTR, 1); - if (attrib == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - attrib->ar_attribute = attr; - attrib->ar_attribute_form = attr_form; - attrib->ar_attribute_form_direct = attr_form; - attrib->ar_cu_context = die->di_cu_context; - attrib->ar_debug_info_ptr = info_ptr; - *ret_attr = (attrib); - return DW_DLV_OK; -} - - -int -dwarf_lowpc(Dwarf_Die die, - Dwarf_Addr * return_addr, Dwarf_Error * error) -{ - Dwarf_Addr ret_addr = 0; - Dwarf_Byte_Ptr info_ptr = 0; - Dwarf_Half attr_form = 0; - Dwarf_Debug dbg = 0; - Dwarf_Half address_size = 0; - - CHECK_DIE(die, DW_DLV_ERROR); - - dbg = die->di_cu_context->cc_dbg; - address_size = die->di_cu_context->cc_address_size; - info_ptr = _dwarf_get_value_ptr(die, DW_AT_low_pc, &attr_form); - if ((info_ptr == NULL && attr_form == 0) || - (info_ptr != NULL && attr_form != DW_FORM_addr)) { - _dwarf_error(dbg, error, DW_DLE_DIE_BAD); - return (DW_DLV_ERROR); - } - if (info_ptr == NULL) { - return (DW_DLV_NO_ENTRY); - } - - - READ_UNALIGNED(dbg, ret_addr, Dwarf_Addr, - info_ptr, address_size); - - *return_addr = ret_addr; - return (DW_DLV_OK); -} - - -int -dwarf_highpc(Dwarf_Die die, - Dwarf_Addr * return_addr, Dwarf_Error * error) -{ - Dwarf_Addr ret_addr = 0; - Dwarf_Byte_Ptr info_ptr = 0; - Dwarf_Half attr_form = 0; - Dwarf_Debug dbg = 0; - Dwarf_Half address_size = 0; - - CHECK_DIE(die, DW_DLV_ERROR); - dbg = die->di_cu_context->cc_dbg; - address_size = die->di_cu_context->cc_address_size; - info_ptr = _dwarf_get_value_ptr(die, DW_AT_high_pc, &attr_form); - if ((info_ptr == NULL && attr_form == 0) || - (info_ptr != NULL && attr_form != DW_FORM_addr)) { - _dwarf_error(dbg, error, DW_DLE_DIE_BAD); - return (DW_DLV_ERROR); - } - if (info_ptr == NULL) { - return (DW_DLV_NO_ENTRY); - } - - READ_UNALIGNED(dbg, ret_addr, Dwarf_Addr, - info_ptr, address_size); - - *return_addr = ret_addr; - return (DW_DLV_OK); -} - - -/* - Takes a die, an attribute attr, and checks if attr - occurs in die. Attr is required to be an attribute - whose form is in the "constant" class. If attr occurs - in die, the value is returned. - Returns DW_DLV_OK, DW_DLV_ERROR, or DW_DLV_NO_ENTRY as - appropriate. Sets the value thru the pointer return_val. - This function is meant to do all the - processing for dwarf_bytesize, dwarf_bitsize, dwarf_bitoffset, - and dwarf_srclang. -*/ -static int -_dwarf_die_attr_unsigned_constant(Dwarf_Die die, - Dwarf_Half attr, - Dwarf_Unsigned * return_val, - Dwarf_Error * error) -{ - Dwarf_Byte_Ptr info_ptr; - Dwarf_Half attr_form; - Dwarf_Unsigned ret_value; - Dwarf_Debug dbg; - - CHECK_DIE(die, DW_DLV_ERROR); - - dbg = die->di_cu_context->cc_dbg; - info_ptr = _dwarf_get_value_ptr(die, attr, &attr_form); - if (info_ptr != NULL) { - switch (attr_form) { - - case DW_FORM_data1: - *return_val = (*(Dwarf_Small *) info_ptr); - return (DW_DLV_OK); - - case DW_FORM_data2: - READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, - info_ptr, sizeof(Dwarf_Shalf)); - *return_val = ret_value; - return (DW_DLV_OK); - - case DW_FORM_data4: - READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, - info_ptr, sizeof(Dwarf_sfixed)); - *return_val = ret_value; - return (DW_DLV_OK); - - case DW_FORM_data8: - READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, - info_ptr, sizeof(Dwarf_Unsigned)); - *return_val = ret_value; - return (DW_DLV_OK); - - case DW_FORM_udata: - *return_val = (_dwarf_decode_u_leb128(info_ptr, NULL)); - return (DW_DLV_OK); - - default: - _dwarf_error(dbg, error, DW_DLE_DIE_BAD); - return (DW_DLV_ERROR); - } - } - if (attr_form == 0) { - _dwarf_error(dbg, error, DW_DLE_DIE_BAD); - return (DW_DLV_ERROR); - } - return DW_DLV_NO_ENTRY; -} - - -int -dwarf_bytesize(Dwarf_Die die, - Dwarf_Unsigned * ret_size, Dwarf_Error * error) -{ - Dwarf_Unsigned luns = 0; - int res = _dwarf_die_attr_unsigned_constant(die, DW_AT_byte_size, - &luns, error); - *ret_size = luns; - return res; -} - - -int -dwarf_bitsize(Dwarf_Die die, - Dwarf_Unsigned * ret_size, Dwarf_Error * error) -{ - Dwarf_Unsigned luns = 0; - int res = _dwarf_die_attr_unsigned_constant(die, DW_AT_bit_size, - &luns, error); - *ret_size = luns; - return res; -} - - -int -dwarf_bitoffset(Dwarf_Die die, - Dwarf_Unsigned * ret_size, Dwarf_Error * error) -{ - Dwarf_Unsigned luns = 0; - int res = _dwarf_die_attr_unsigned_constant(die, - DW_AT_bit_offset, &luns, error); - *ret_size = luns; - return res; -} - - -/* Refer section 3.1, page 21 in Dwarf Definition. */ -int -dwarf_srclang(Dwarf_Die die, - Dwarf_Unsigned * ret_size, Dwarf_Error * error) -{ - Dwarf_Unsigned luns = 0; - int res = _dwarf_die_attr_unsigned_constant(die, DW_AT_language, - &luns, error); - *ret_size = luns; - return res; -} - - -/* Refer section 5.4, page 37 in Dwarf Definition. */ -int -dwarf_arrayorder(Dwarf_Die die, - Dwarf_Unsigned * ret_size, Dwarf_Error * error) -{ - Dwarf_Unsigned luns = 0; - int res = _dwarf_die_attr_unsigned_constant(die, DW_AT_ordering, - &luns, error); - *ret_size = luns; - return res; -} - -/* - Return DW_DLV_OK if ok - DW_DLV_ERROR if failure. - - If the die and the attr are not related the result is - meaningless. -*/ -int -dwarf_attr_offset(Dwarf_Die die, Dwarf_Attribute attr, - Dwarf_Off * offset /* return offset thru this ptr */, - Dwarf_Error * error) -{ - Dwarf_Off attroff = 0; - - CHECK_DIE(die, DW_DLV_ERROR); - - attroff = (attr->ar_debug_info_ptr - - die->di_cu_context->cc_dbg->de_debug_info.dss_data); - *offset = attroff; - return DW_DLV_OK; -} - -int -dwarf_die_abbrev_code(Dwarf_Die die) -{ - return die->di_abbrev_code; -} - -/* Helper function for finding form class. */ -static enum Dwarf_Form_Class -dw_get_special_offset(Dwarf_Half attrnum) -{ - switch(attrnum) { - case DW_AT_stmt_list: - return DW_FORM_CLASS_LINEPTR; - case DW_AT_macro_info: - return DW_FORM_CLASS_MACPTR; - case DW_AT_ranges: - return DW_FORM_CLASS_RANGELISTPTR; - case DW_AT_location: - case DW_AT_string_length: - case DW_AT_return_addr: - case DW_AT_data_member_location: - case DW_AT_frame_base: - case DW_AT_segment: - case DW_AT_static_link: - case DW_AT_use_location: - case DW_AT_vtable_elem_location: - return DW_FORM_CLASS_LOCLISTPTR; - case DW_AT_sibling: - case DW_AT_byte_size : - case DW_AT_bit_offset : - case DW_AT_bit_size : - case DW_AT_discr : - case DW_AT_import : - case DW_AT_common_reference: - case DW_AT_containing_type: - case DW_AT_default_value: - case DW_AT_lower_bound: - case DW_AT_bit_stride: - case DW_AT_upper_bound: - case DW_AT_abstract_origin: - case DW_AT_base_types: - case DW_AT_count: - case DW_AT_friend: - case DW_AT_namelist_item: - case DW_AT_priority: - case DW_AT_specification: - case DW_AT_type: - case DW_AT_allocated: - case DW_AT_associated: - case DW_AT_byte_stride: - case DW_AT_extension: - case DW_AT_trampoline: - case DW_AT_small: - case DW_AT_object_pointer: - case DW_AT_signature: - return DW_FORM_CLASS_REFERENCE; - case DW_AT_MIPS_fde: /* SGI/IRIX extension */ - return DW_FORM_CLASS_FRAMEPTR; - } - return DW_FORM_CLASS_UNKNOWN; -} - -/* It takes 4 pieces of data (including the FORM) - to accurately determine the form 'class' as documented - in the DWARF spec. This is per DWARF4, but will work - for DWARF2 or 3 as well. */ -enum Dwarf_Form_Class dwarf_get_form_class( - Dwarf_Half dwversion, - Dwarf_Half attrnum, - Dwarf_Half offset_size, - Dwarf_Half form) -{ - switch(form) { - case DW_FORM_addr: return DW_FORM_CLASS_ADDRESS; - - case DW_FORM_data2: return DW_FORM_CLASS_CONSTANT; - - case DW_FORM_data4: - if(dwversion <= 3 && offset_size == 4) { - enum Dwarf_Form_Class class = dw_get_special_offset(attrnum); - if(class != DW_FORM_CLASS_UNKNOWN) { - return class; - } - } - return DW_FORM_CLASS_CONSTANT; - case DW_FORM_data8: - if(dwversion <= 3 && offset_size == 8) { - enum Dwarf_Form_Class class = dw_get_special_offset(attrnum); - if(class != DW_FORM_CLASS_UNKNOWN) { - return class; - } - } - return DW_FORM_CLASS_CONSTANT; - - case DW_FORM_sec_offset: - { - enum Dwarf_Form_Class class = dw_get_special_offset(attrnum); - if(class != DW_FORM_CLASS_UNKNOWN) { - return class; - } - } - /* We do not know what this is. */ - break; - - case DW_FORM_string: return DW_FORM_CLASS_STRING; - case DW_FORM_strp: return DW_FORM_CLASS_STRING; - - case DW_FORM_block: return DW_FORM_CLASS_BLOCK; - case DW_FORM_block1: return DW_FORM_CLASS_BLOCK; - case DW_FORM_block2: return DW_FORM_CLASS_BLOCK; - case DW_FORM_block4: return DW_FORM_CLASS_BLOCK; - - case DW_FORM_data1: return DW_FORM_CLASS_CONSTANT; - case DW_FORM_sdata: return DW_FORM_CLASS_CONSTANT; - case DW_FORM_udata: return DW_FORM_CLASS_CONSTANT; - - case DW_FORM_ref_addr: return DW_FORM_CLASS_REFERENCE; - case DW_FORM_ref1: return DW_FORM_CLASS_REFERENCE; - case DW_FORM_ref2: return DW_FORM_CLASS_REFERENCE; - case DW_FORM_ref4: return DW_FORM_CLASS_REFERENCE; - case DW_FORM_ref8: return DW_FORM_CLASS_REFERENCE; - case DW_FORM_ref_udata: return DW_FORM_CLASS_REFERENCE; - case DW_FORM_ref_sig8: return DW_FORM_CLASS_REFERENCE; - - case DW_FORM_exprloc: return DW_FORM_CLASS_EXPRLOC; - - case DW_FORM_flag: return DW_FORM_CLASS_FLAG; - case DW_FORM_flag_present: return DW_FORM_CLASS_FLAG; - - - case DW_FORM_indirect: - default: - break; - }; - return DW_FORM_CLASS_UNKNOWN; -} - diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_ranges.c b/usr/src/tools/ctf/dwarf/common/dwarf_ranges.c deleted file mode 100644 index ae6d5cf9b5..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_ranges.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - - Copyright (C) 2008-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the Crittenden Lane address. -*/ - - - -#include "config.h" -#include -#include "dwarf_incl.h" - -struct ranges_entry { - struct ranges_entry *next; - Dwarf_Ranges cur; -}; - - -#define MAX_ADDR ((address_size == 8)?0xffffffffffffffffULL:0xffffffff) -int dwarf_get_ranges_a(Dwarf_Debug dbg, - Dwarf_Off rangesoffset, - Dwarf_Die die, - Dwarf_Ranges ** rangesbuf, - Dwarf_Signed * listlen, - Dwarf_Unsigned * bytecount, - Dwarf_Error * error) -{ - Dwarf_Small *rangeptr = 0; - Dwarf_Small *beginrangeptr = 0; - Dwarf_Small *section_end = 0; - unsigned entry_count = 0; - struct ranges_entry *base = 0; - struct ranges_entry *last = 0; - struct ranges_entry *curre = 0; - Dwarf_Ranges * ranges_data_out = 0; - unsigned copyindex = 0; - Dwarf_Half address_size = 0; - int res = DW_DLV_ERROR; - - res = _dwarf_load_section(dbg, &dbg->de_debug_ranges,error); - if (res != DW_DLV_OK) { - return res; - } - if(rangesoffset >= dbg->de_debug_ranges.dss_size) { - _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OFFSET_BAD); - return (DW_DLV_ERROR); - - } - address_size = _dwarf_get_address_size(dbg, die); - section_end = dbg->de_debug_ranges.dss_data + - dbg->de_debug_ranges.dss_size; - rangeptr = dbg->de_debug_ranges.dss_data + rangesoffset; - beginrangeptr = rangeptr; - - for(;;) { - struct ranges_entry * re = calloc(sizeof(struct ranges_entry),1); - if(!re) { - _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OUT_OF_MEM); - return (DW_DLV_ERROR); - } - if(rangeptr >= section_end) { - return (DW_DLV_NO_ENTRY); - } - if((rangeptr + (2*address_size)) > section_end) { - _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OFFSET_BAD); - return (DW_DLV_ERROR); - } - entry_count++; - READ_UNALIGNED(dbg,re->cur.dwr_addr1, - Dwarf_Addr, rangeptr, - address_size); - rangeptr += address_size; - READ_UNALIGNED(dbg,re->cur.dwr_addr2 , - Dwarf_Addr, rangeptr, - address_size); - rangeptr += address_size; - if(!base) { - base = re; - last = re; - } else { - last->next = re; - last = re; - } - if(re->cur.dwr_addr1 == 0 && re->cur.dwr_addr2 == 0) { - re->cur.dwr_type = DW_RANGES_END; - break; - } else if ( re->cur.dwr_addr1 == MAX_ADDR) { - re->cur.dwr_type = DW_RANGES_ADDRESS_SELECTION; - } else { - re->cur.dwr_type = DW_RANGES_ENTRY; - } - } - - ranges_data_out = (Dwarf_Ranges *) - _dwarf_get_alloc(dbg,DW_DLA_RANGES,entry_count); - if(!ranges_data_out) { - _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OUT_OF_MEM); - return (DW_DLV_ERROR); - } - curre = base; - *rangesbuf = ranges_data_out; - *listlen = entry_count; - for( copyindex = 0; curre && (copyindex < entry_count); - ++copyindex,++ranges_data_out) { - - struct ranges_entry *r = curre; - *ranges_data_out = curre->cur; - curre = curre->next; - free(r); - } - /* Callers will often not care about the bytes used. */ - if(bytecount) { - *bytecount = rangeptr - beginrangeptr; - } - return DW_DLV_OK; -} -int dwarf_get_ranges(Dwarf_Debug dbg, - Dwarf_Off rangesoffset, - Dwarf_Ranges ** rangesbuf, - Dwarf_Signed * listlen, - Dwarf_Unsigned * bytecount, - Dwarf_Error * error) -{ - Dwarf_Die die = 0; - int res = dwarf_get_ranges_a(dbg,rangesoffset,die, - rangesbuf,listlen,bytecount,error); - return res; -} - -void -dwarf_ranges_dealloc(Dwarf_Debug dbg, Dwarf_Ranges * rangesbuf, - Dwarf_Signed rangecount) -{ - dwarf_dealloc(dbg,rangesbuf, DW_DLA_RANGES); - -} - diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_sort_line.c b/usr/src/tools/ctf/dwarf/common/dwarf_sort_line.c deleted file mode 100644 index 3576614129..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_sort_line.c +++ /dev/null @@ -1,733 +0,0 @@ -/* - Copyright (C) 2000,2002,2004,2006 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the Crittenden Lane address. -*/ - - -/* This file was designed for SGI IRIX compiler use. - The static linker can rearrange the order of functions - in the layout in memory - and provided each has the right form - this will (when called by the SGI IRIX - static linker) rearrange the table so the line table - is arranged in the same order as the memory layout. */ - - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include -#include "dwarf_line.h" -#ifdef HAVE_ALLOCA_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif - -#define MINIMUM_POSSIBLE_PROLOG_LEN 10 /* 10 is based on */ - /* the definition of the DWARF2/3 line table prolog. The value - here should be >8 (accounting for a 64 bit read) and <= the - length of a legal DWARF2/3 line prolog, which is at least 10 - bytes long (but can be longer). What this constant helps - avoid is reading past the end of a malloc'd buffer in - _dwarf_update_line_sec(). */ - -static int - _dwarf_update_line_sec(Dwarf_Small * line_ptr, - unsigned long remaining_bytes, - int *any_change, - int length_size, - int *err_code, Dwarf_Small ** new_line_ptr); - -/* Used to construct - a linked list of so we can sort and reorder the line info. -*/ -struct a_line_area { - Dwarf_Addr ala_address; /* from DW_LNE_set_address */ - Dwarf_Unsigned ala_offset; /* byte offset in buffer */ - Dwarf_Unsigned ala_length; /* byte length in buffer */ - long ala_entry_num; /* to guarantee stable sort */ - struct a_line_area *ala_next; -}; - - -/* - Written to support the SGI IRIX static linker. - It helps SGI IRIX ld - rearrange lines in .debug_line in a .o created with a text - section per function. The SGI IRIX linker option is: - -OPT:procedure_reorder=ON - where ld-cord (cord(1)ing by ld, - not by cord(1)) may have changed the function order. - - Returns - DW_DLV_OK if nothing went wrong. - DW_DLV_ERROR if could not do anything due to - error. the original buffer is unchanged. - - is_64_bit must be passed in by caller and tells - if this is a 32 or 64bit pointer object section - being processed. - - err_code must be a non-null pointer to integer. - If DW_DLV_ERROR is returned that integer is set - to a dwarf error code so the caller may - print it for diagnostic purposes. - - *any_change is set here - set 0 if no sorting (movement) done. - set 1 if some sorting (movement) done. - on all returns. On error return sets to 0. - - The _dwarf name form is now obsolete, - the dwarf_ name for is preferred. - Both names supported. - -*/ -int -_dwarf_ld_sort_lines(void *orig_buffer, - unsigned long buffer_len, - int is_64_bit, int *any_change, int *err_code) -{ - return dwarf_ld_sort_lines(orig_buffer,buffer_len, - is_64_bit,any_change,err_code); -} -int -dwarf_ld_sort_lines(void *orig_buffer, - unsigned long buffer_len, - int is_64_bit, int *any_change, int *err_code) -{ - - int length_size = 4; - Dwarf_Small *orig_line_ptr; /* our local copy of the user's input - buffer */ - Dwarf_Small *line_ptr; /* starts at orig_line_ptr, gets - incremented thru to end of our copy - of the input buffer */ - Dwarf_Small *new_line_ptr; /* output of _dwarf_update_line_sec(), - used to update line_ptr as we pass - thru compilation units in a .o - .debug_line */ - - unsigned long remaining_bytes = buffer_len; /* total length of - original area left - to be processed. - Changes as we pass - thru compilation - units in a .o - .debug_line */ - - int sec_res; - int lany_change = 0; - int did_change = 0; - - if (is_64_bit) - length_size = 8; - - *any_change = 0; - line_ptr = malloc(buffer_len); - if (!line_ptr) { - *err_code = DW_DLE_ALLOC_FAIL; - return DW_DLV_ERROR; - } - orig_line_ptr = line_ptr; - memcpy(line_ptr, orig_buffer, buffer_len); - - - /* - We must iterate thru each of a set of prologues and line data. - We process each set in turn. If all pass, we update the - passed-in buffer. */ - sec_res = DW_DLV_OK; - - for (sec_res = _dwarf_update_line_sec(line_ptr, - remaining_bytes, - &lany_change, - length_size, - err_code, - &new_line_ptr); - (sec_res == DW_DLV_OK) && (remaining_bytes > 0); - sec_res = _dwarf_update_line_sec(line_ptr, - remaining_bytes, - &lany_change, - length_size, - err_code, &new_line_ptr)) { - long bytes_used = new_line_ptr - line_ptr; - - line_ptr = new_line_ptr; - remaining_bytes -= bytes_used; - if (lany_change) { - did_change = 1; - } - if (remaining_bytes > 0) { - continue; - } - break; - } - if (sec_res == DW_DLV_ERROR) { - free(orig_line_ptr); - return sec_res; - } - - - /* all passed */ - if (did_change) { - /* So update the passed in buffer orig_buffer is caller's input - area. orig_line_ptr is our modified copy of input area. */ - memcpy(orig_buffer, orig_line_ptr, buffer_len); - *any_change = 1; - } - free(orig_line_ptr); - - return sec_res; -} - - -/* By setting ala_entry_num we guarantee a stable sort, - no duplicates - Sorting in address order. -*/ -static int -cmpr(const void *lin, const void *rin) -{ - const struct a_line_area *l = lin; - const struct a_line_area *r = rin; - - if (l->ala_address < r->ala_address) { - return -1; - } - if (l->ala_address > r->ala_address) { - return 1; - } - if (l->ala_entry_num < r->ala_entry_num) { - return -1; - } - if (l->ala_entry_num > r->ala_entry_num) { - return 1; - } - return 0; /* should never happen. */ -} - -/* The list of line area records is no longer needed. - Free the data allocated. */ -static void -free_area_data(struct a_line_area *arp) -{ - while(arp) { - struct a_line_area *next = arp->ala_next; - free(arp); - arp = next; - } -} - -/* - On entry: - line_ptr must point to first - byte of a line group for one (original) .o - - remaining_bytes is the size of the area pointed to - by line_ptr: may be larger than the - current original compilation unit . - - length size is 4 for 32bit pointers, 8 for 64bit pointers - in the data pointed to. - - - On return: - return DW_DLV_OK if all ok. (ignore - *err_code in this case) - - return DW_DLV_ERROR and set *err_code if an error. - - If some line data was moved around, set *any_change to 1. - If error or no movement, set *any_change to 0; - - Set *new_line_ptr to one-byte-past the end of the - current original compilation unit (not necessary - if returning DW_DLV_ERROR, but not harmful). - - - This copies the entire array to a malloc area, then - mallocs pieces of it (another malloc) for sorting a CU entries - and copying back. Then at end the whole new thing copied in. - The result is that on error, the input is not touched. - - An alternative would be to just update a piece at a time - and on error stop updating but leave what was done, done. - This alternative would save some temporary malloc space. - - -*/ -static int -_dwarf_update_line_sec(Dwarf_Small * line_ptr, - unsigned long remaining_bytes, - int *any_change, - int length_size, - int *err_code, Dwarf_Small ** new_line_ptr) -{ - - - /* - This points to the last byte of the .debug_line portion for the - current cu. */ - Dwarf_Small *line_ptr_end = 0; - - /* - This points to the end of the statement program prologue for the - current cu, and serves to check that the prologue was correctly - decoded. */ - - Dwarf_Small *orig_line_ptr = 0; - - /* These are the fields of the statement program header. */ - struct Dwarf_Debug_s dbg_data; - Dwarf_Debug dbg = &dbg_data; - - /* These are the state machine state variables. */ - Dwarf_Addr address = 0; - Dwarf_Word line = 1; - Dwarf_Bool is_stmt = false; - - /* Dwarf_Bool prologue_end; Dwarf_Bool epilogue_begin; */ - Dwarf_Small isa = 0; - - - struct a_line_area *area_base = 0; - struct a_line_area *area_current = 0; - long area_count = 0; - - Dwarf_Addr last_address = 0; - int need_to_sort = 0; - - /* - This is the current opcode read from the statement program. */ - Dwarf_Small opcode = 0; - - - /* - These variables are used to decode leb128 numbers. Leb128_num - holds the decoded number, and leb128_length is its length in - bytes. */ - Dwarf_Word leb128_num = 0; - Dwarf_Sword advance_line = 0; - - /* - This is the operand of the latest fixed_advance_pc extended - opcode. */ - Dwarf_Half fixed_advance_pc = 0; - - /* This is the length of an extended opcode instr. */ - Dwarf_Word instr_length = 0; - Dwarf_Small ext_opcode = 0; - struct Line_Table_Prefix_s prefix; - - - - memset(dbg, 0, sizeof(struct Dwarf_Debug_s)); - dbg->de_copy_word = memcpy; - /* - Following is a straightforward decoding of the statement program - prologue information. */ - *any_change = 0; - - - orig_line_ptr = line_ptr; - if (remaining_bytes < MINIMUM_POSSIBLE_PROLOG_LEN) { - /* We are at the end. Remaining should be zero bytes, padding. - This is really just 'end of CU buffer' not an error. The is - no 'entry' left so report there is none. We don't want to - READ_UNALIGNED the total_length below and then belatedly - discover that we read off the end already. */ - return (DW_DLV_NO_ENTRY); - } - - dwarf_init_line_table_prefix(&prefix); - { - Dwarf_Small *line_ptr_out = 0; - Dwarf_Error error; - int dres = dwarf_read_line_table_prefix(dbg, - line_ptr, - remaining_bytes, - &line_ptr_out, - &prefix, - NULL, NULL,&error, - NULL); - - if (dres == DW_DLV_ERROR) { - dwarf_free_line_table_prefix(&prefix); - *err_code = dwarf_errno(error); - dwarf_dealloc(dbg, error, DW_DLA_ERROR); - free_area_data(area_base); - return dres; - } - if (dres == DW_DLV_NO_ENTRY) { - dwarf_free_line_table_prefix(&prefix); - return dres; - } - line_ptr_end = prefix.pf_line_ptr_end; - - line_ptr = line_ptr_out; - } - - - /* Initialize the state machine. */ - /* file = 1; */ - /* column = 0; */ - is_stmt = prefix.pf_default_is_stmt; - /* basic_block = false; */ - /* end_sequence = false; */ - /* prologue_end = false; */ - /* epilogue_begin = false; */ - isa = 0; - - - /* Start of statement program. */ - while (line_ptr < line_ptr_end) { - int type; - - Dwarf_Small *stmt_prog_entry_start = line_ptr; - - opcode = *(Dwarf_Small *) line_ptr; - line_ptr++; - /* 'type' is the output */ - WHAT_IS_OPCODE(type, opcode, prefix.pf_opcode_base, - prefix.pf_opcode_length_table, line_ptr, - prefix.pf_std_op_count); - - if (type == LOP_DISCARD) { - int oc; - int opcnt = prefix.pf_opcode_length_table[opcode]; - - for (oc = 0; oc < opcnt; oc++) { - /* - ** Read and discard operands we don't - ** understand. - ** arbitrary choice of unsigned read. - ** signed read would work as well. - */ - Dwarf_Unsigned utmp2; - - DECODE_LEB128_UWORD(line_ptr, utmp2); - } - - } else if (type == LOP_SPECIAL) { - opcode = opcode - prefix.pf_opcode_base; - address = address + prefix.pf_minimum_instruction_length * - (opcode / prefix.pf_line_range); - line = - line + prefix.pf_line_base + - opcode % prefix.pf_line_range; - - /* basic_block = false; */ - - - } else if (type == LOP_STANDARD) { - - - switch (opcode) { - - - case DW_LNS_copy:{ - - /* basic_block = false; */ - break; - } - - case DW_LNS_advance_pc:{ - Dwarf_Unsigned utmp2; - - - DECODE_LEB128_UWORD(line_ptr, utmp2); - leb128_num = (Dwarf_Word) utmp2; - address = - address + - prefix.pf_minimum_instruction_length * - leb128_num; - break; - } - - case DW_LNS_advance_line:{ - Dwarf_Signed stmp; - - - DECODE_LEB128_SWORD(line_ptr, stmp); - advance_line = (Dwarf_Sword) stmp; - line = line + advance_line; - break; - } - - case DW_LNS_set_file:{ - Dwarf_Unsigned utmp2; - - - DECODE_LEB128_UWORD(line_ptr, utmp2); - /* file = (Dwarf_Word)utmp2; */ - break; - } - - case DW_LNS_set_column:{ - Dwarf_Unsigned utmp2; - - - DECODE_LEB128_UWORD(line_ptr, utmp2); - /* column = (Dwarf_Word)utmp2; */ - break; - } - - case DW_LNS_negate_stmt:{ - - is_stmt = !is_stmt; - break; - } - - case DW_LNS_set_basic_block:{ - - /* basic_block = true; */ - break; - } - - case DW_LNS_const_add_pc:{ - opcode = MAX_LINE_OP_CODE - prefix.pf_opcode_base; - address = - address + - prefix.pf_minimum_instruction_length * (opcode / - prefix. - pf_line_range); - - break; - } - - case DW_LNS_fixed_advance_pc:{ - - READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half, - line_ptr, sizeof(Dwarf_Half)); - line_ptr += sizeof(Dwarf_Half); - address = address + fixed_advance_pc; - break; - } - /* New in DWARF3 */ - case DW_LNS_set_prologue_end:{ - - /* prologue_end = true; */ - break; - - - } - /* New in DWARF3 */ - case DW_LNS_set_epilogue_begin:{ - /* epilogue_begin = true; */ - break; - } - - /* New in DWARF3 */ - case DW_LNS_set_isa:{ - Dwarf_Unsigned utmp2; - - DECODE_LEB128_UWORD(line_ptr, utmp2); - isa = utmp2; - if (isa != utmp2) { - /* The value of the isa did not fit in our - local so we record it wrong. declare an - error. */ - dwarf_free_line_table_prefix(&prefix); - *err_code = DW_DLE_LINE_NUM_OPERANDS_BAD; - free_area_data(area_base); - return (DW_DLV_ERROR); - } - break; - } - - } - } else if (type == LOP_EXTENDED) { - - Dwarf_Unsigned utmp3; - - DECODE_LEB128_UWORD(line_ptr, utmp3); - instr_length = (Dwarf_Word) utmp3; - ext_opcode = *(Dwarf_Small *) line_ptr; - line_ptr++; - switch (ext_opcode) { - - case DW_LNE_end_sequence:{ - /* end_sequence = true; */ - - address = 0; - /* file = 1; */ - line = 1; - /* column = 0; */ - is_stmt = prefix.pf_default_is_stmt; - /* basic_block = false; */ - /* end_sequence = false; */ - /* prologue_end = false; */ - /* epilogue_begin = false; */ - break; - } - - case DW_LNE_set_address:{ - { - struct a_line_area *area; - - READ_UNALIGNED(dbg, address, Dwarf_Addr, - line_ptr, length_size); - /* Here we need to remember the offset into the - buffer and check to see if address went - down. */ - if (address < last_address) { - need_to_sort = 1; - } - last_address = address; - - area = malloc(sizeof(struct a_line_area)); - area->ala_address = address; - area->ala_offset = stmt_prog_entry_start - - orig_line_ptr; - area->ala_entry_num = area_count; - area->ala_next = 0; - area->ala_length = 0; - if (area_current) { - area_current->ala_next = area; - area_current->ala_length = - area->ala_offset - - area_current->ala_offset; - } - ++area_count; - area_current = area; - if (area_base == 0) { - area_base = area; - } - - line_ptr += length_size; - } - break; - } - - case DW_LNE_define_file:{ - break; - } - - default:{ - Dwarf_Unsigned remaining_bytes = instr_length -1; - line_ptr += remaining_bytes; - break; - } - } - - } - } - - - *new_line_ptr = line_ptr; - if (!need_to_sort) { - dwarf_free_line_table_prefix(&prefix); - free_area_data(area_base); - return (DW_DLV_OK); - } - - /* So now we have something to sort. First, finish off the last - area record: */ - area_current->ala_length = (line_ptr - orig_line_ptr) - -area_current->ala_offset; - - /* Build and sort a simple array of sections. Forcing a stable sort - by comparing on sequence number. We will use the sorted list to - move sections of this part of the line table. Each 'section' - starting with a DW_LNE_set_address opcode, on the assumption - that such only get out of order where there was an ld-cord - function rearrangement and that it is meaningful to restart the - line info there. */ - { - struct a_line_area *ala_array; - struct a_line_area *local; - long start_len; - Dwarf_Small *new_area; - long i; - - ala_array = malloc(area_count * sizeof(struct a_line_area)); - if (!ala_array) { - dwarf_free_line_table_prefix(&prefix); - *err_code = DW_DLE_ALLOC_FAIL; - free_area_data(area_base); - return DW_DLV_ERROR; - } - - for (local = area_base, i = 0; local; - local = local->ala_next, ++i) { - - ala_array[i] = *local; - } - free_area_data(area_base); - /* Zero the stale pointers so we don't use them accidentally. */ - area_base = 0; - area_current = 0; - - qsort(ala_array, area_count, sizeof(struct a_line_area), cmpr); - - /* Now we must rearrange the pieces of the line table. */ - - start_len = - (prefix.pf_line_prologue_start + - prefix.pf_prologue_length) - orig_line_ptr; - new_area = malloc(remaining_bytes); - if (!new_area) { - free(ala_array); - *err_code = DW_DLE_ALLOC_FAIL; - dwarf_free_line_table_prefix(&prefix); - return DW_DLV_ERROR; - } - memcpy(new_area, orig_line_ptr, start_len); - line_ptr = new_area + start_len; - for (i = 0; i < area_count; ++i) { - memcpy(line_ptr, orig_line_ptr + - ala_array[i].ala_offset, ala_array[i].ala_length); - line_ptr += ala_array[i].ala_length; - } - - memcpy(orig_line_ptr, new_area, remaining_bytes); - - free(new_area); - free(ala_array); - ala_array = 0; - new_area = 0; - } - - *any_change = 1; - dwarf_free_line_table_prefix(&prefix); - return (DW_DLV_OK); -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_string.c b/usr/src/tools/ctf/dwarf/common/dwarf_string.c deleted file mode 100644 index fafa5a097c..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_string.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - - Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "dwarf_incl.h" - -int -dwarf_get_str(Dwarf_Debug dbg, - Dwarf_Off offset, - char **string, - Dwarf_Signed * returned_str_len, Dwarf_Error * error) -{ - int res = DW_DLV_ERROR; - - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - - if (offset == dbg->de_debug_str.dss_size) { - /* Normal (if we've iterated thru the set of strings using - dwarf_get_str and are at the end). */ - return DW_DLV_NO_ENTRY; - } - if (offset > dbg->de_debug_str.dss_size) { - _dwarf_error(dbg, error, DW_DLE_DEBUG_STR_OFFSET_BAD); - return (DW_DLV_ERROR); - } - - if (string == NULL) { - _dwarf_error(dbg, error, DW_DLE_STRING_PTR_NULL); - return (DW_DLV_ERROR); - } - - res = _dwarf_load_section(dbg, &dbg->de_debug_str,error); - if (res != DW_DLV_OK) { - return res; - } - - *string = (char *) dbg->de_debug_str.dss_data + offset; - - *returned_str_len = (strlen(*string)); - return DW_DLV_OK; -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_stubs.c b/usr/src/tools/ctf/dwarf/common/dwarf_stubs.c deleted file mode 100644 index f2c1f7fd45..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_stubs.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "dwarf_incl.h" -#include - - - - /*ARGSUSED*/ int -dwarf_nextglob(Dwarf_Debug dbg, - Dwarf_Global glob, - Dwarf_Global * returned_nextglob, Dwarf_Error * error) -{ - return (DW_DLV_NO_ENTRY); -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_types.c b/usr/src/tools/ctf/dwarf/common/dwarf_types.c deleted file mode 100644 index d547805289..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_types.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include "dwarf_types.h" -#include "dwarf_global.h" - -int -dwarf_get_types(Dwarf_Debug dbg, - Dwarf_Type ** types, - Dwarf_Signed * ret_type_count, Dwarf_Error * error) -{ - int res = _dwarf_load_section(dbg, &dbg->de_debug_typenames,error); - if (res != DW_DLV_OK) { - return res; - } - - return _dwarf_internal_get_pubnames_like_data(dbg, - dbg->de_debug_typenames.dss_data, - dbg->de_debug_typenames.dss_size, - (Dwarf_Global **) types, /* type punning, Dwarf_Type is - never a completed type */ - ret_type_count, - error, - DW_DLA_TYPENAME_CONTEXT, - DW_DLA_TYPENAME, - DW_DLE_DEBUG_TYPENAMES_LENGTH_BAD, - DW_DLE_DEBUG_TYPENAMES_VERSION_ERROR); -} - -/* Deallocating fully requires deallocating the list - and all entries. But some internal data is - not exposed, so we need a function with internal knowledge. -*/ - -void -dwarf_types_dealloc(Dwarf_Debug dbg, Dwarf_Type * dwgl, - Dwarf_Signed count) -{ - _dwarf_internal_globals_dealloc(dbg, (Dwarf_Global *) dwgl, - count, - DW_DLA_TYPENAME_CONTEXT, - DW_DLA_TYPENAME, DW_DLA_LIST); - return; -} - - -int -dwarf_typename(Dwarf_Type type_in, char **ret_name, Dwarf_Error * error) -{ - Dwarf_Global type = (Dwarf_Global) type_in; - - if (type == NULL) { - _dwarf_error(NULL, error, DW_DLE_TYPE_NULL); - return (DW_DLV_ERROR); - } - - *ret_name = (char *) (type->gl_name); - return DW_DLV_OK; -} - - -int -dwarf_type_die_offset(Dwarf_Type type_in, - Dwarf_Off * ret_offset, Dwarf_Error * error) -{ - Dwarf_Global type = (Dwarf_Global) type_in; - - return dwarf_global_die_offset(type, ret_offset, error); -} - - -int -dwarf_type_cu_offset(Dwarf_Type type_in, - Dwarf_Off * ret_offset, Dwarf_Error * error) -{ - Dwarf_Global type = (Dwarf_Global) type_in; - - return dwarf_global_cu_offset(type, ret_offset, error); -} - - -int -dwarf_type_name_offsets(Dwarf_Type type_in, - char **returned_name, - Dwarf_Off * die_offset, - Dwarf_Off * cu_die_offset, Dwarf_Error * error) -{ - Dwarf_Global type = (Dwarf_Global) type_in; - return dwarf_global_name_offsets(type, - returned_name, - die_offset, cu_die_offset, error); -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_types.h b/usr/src/tools/ctf/dwarf/common/dwarf_types.h deleted file mode 100644 index ebd31c6c79..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_types.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - - -typedef struct Dwarf_Type_Context_s *Dwarf_Type_Context; - -/* type never completed see dwarf_global.h */ diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_util.c b/usr/src/tools/ctf/dwarf/common/dwarf_util.c deleted file mode 100644 index 01e0dd755d..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_util.c +++ /dev/null @@ -1,547 +0,0 @@ -/* - Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the Crittenden Lane address. -*/ - - - - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include "dwarf_die_deliv.h" - - - -/* - Given a form, and a pointer to the bytes encoding - a value of that form, val_ptr, this function returns - the length, in bytes, of a value of that form. - When using this function, check for a return of 0 - a recursive DW_FORM_INDIRECT value. -*/ -Dwarf_Unsigned -_dwarf_get_size_of_val(Dwarf_Debug dbg, - Dwarf_Unsigned form, - Dwarf_Half address_size, - Dwarf_Small * val_ptr, int v_length_size) -{ - Dwarf_Unsigned length = 0; - Dwarf_Word leb128_length = 0; - Dwarf_Unsigned form_indirect = 0; - Dwarf_Unsigned ret_value = 0; - - switch (form) { - - default: /* Handles form = 0. */ - return (form); - - case DW_FORM_addr: - if(address_size) { - return address_size; - } - /* This should never happen, address_size should be set. */ - return (dbg->de_pointer_size); - - /* DWARF2 was wrong on the size of the attribute for - DW_FORM_ref_addr. We assume compilers are using the - corrected DWARF3 text (for 32bit pointer target objects pointer and - offsets are the same size anyway). */ - case DW_FORM_ref_addr: - return (v_length_size); - - case DW_FORM_block1: - return (*(Dwarf_Small *) val_ptr + 1); - - case DW_FORM_block2: - READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, - val_ptr, sizeof(Dwarf_Half)); - return (ret_value + sizeof(Dwarf_Half)); - - case DW_FORM_block4: - READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, - val_ptr, sizeof(Dwarf_ufixed)); - return (ret_value + sizeof(Dwarf_ufixed)); - - - case DW_FORM_data1: - return (1); - - case DW_FORM_data2: - return (2); - - case DW_FORM_data4: - return (4); - - case DW_FORM_data8: - return (8); - - case DW_FORM_string: - return (strlen((char *) val_ptr) + 1); - - case DW_FORM_block: - case DW_FORM_exprloc: - length = _dwarf_decode_u_leb128(val_ptr, &leb128_length); - return (length + leb128_length); - - case DW_FORM_flag_present: - return (0); - case DW_FORM_flag: - return (1); - - case DW_FORM_sec_offset: - /* If 32bit dwarf, is 4. Else is 64bit dwarf and is 8. */ - return (v_length_size); - - case DW_FORM_ref_udata: - length = _dwarf_decode_u_leb128(val_ptr, &leb128_length); - return (leb128_length); - - case DW_FORM_indirect: - { - Dwarf_Word indir_len = 0; - - form_indirect = _dwarf_decode_u_leb128(val_ptr, &indir_len); - if (form_indirect == DW_FORM_indirect) { - return (0); /* We are in big trouble: The true form - of DW_FORM_indirect is - DW_FORM_indirect? Nonsense. Should - never happen. */ - } - return (indir_len + _dwarf_get_size_of_val(dbg, - form_indirect, - address_size, - val_ptr + indir_len, - v_length_size)); - } - - case DW_FORM_ref1: - return (1); - - case DW_FORM_ref2: - return (2); - - case DW_FORM_ref4: - return (4); - - case DW_FORM_ref8: - return (8); - - case DW_FORM_sdata: - _dwarf_decode_s_leb128(val_ptr, &leb128_length); - return (leb128_length); - - case DW_FORM_strp: - return (v_length_size); - - case DW_FORM_udata: - _dwarf_decode_u_leb128(val_ptr, &leb128_length); - return (leb128_length); - } -} - -/* We allow an arbitrary number of HT_MULTIPLE entries - before resizing. It seems up to 20 or 30 - would work nearly as well. - We could have a different resize multiple than 'resize now' - test multiple, but for now we don't do that. -*/ -#define HT_MULTIPLE 8 - -/* Copy the old entries, updating each to be in - a new list. Don't delete anything. Leave the - htin with stale data. */ -static void -copy_abbrev_table_to_new_table(Dwarf_Hash_Table htin, - Dwarf_Hash_Table htout) -{ - Dwarf_Hash_Table_Entry entry_in = htin->tb_entries; - unsigned entry_in_count = htin->tb_table_entry_count; - Dwarf_Hash_Table_Entry entry_out = htout->tb_entries; - unsigned entry_out_count = htout->tb_table_entry_count; - unsigned k = 0; - for ( ; k < entry_in_count; ++k,++entry_in) { - Dwarf_Abbrev_List listent = entry_in->at_head; - Dwarf_Abbrev_List nextlistent = 0; - - for ( ; listent ; listent = nextlistent) { - unsigned newtmp = listent->ab_code; - unsigned newhash = newtmp%entry_out_count; - Dwarf_Hash_Table_Entry e; - nextlistent = listent->ab_next; - e = entry_out+newhash; - /* Move_entry_to_new_hash. This reverses the - order of the entries, effectively, but - that does not seem significant. */ - listent->ab_next = e->at_head; - e->at_head = listent; - - htout->tb_total_abbrev_count++; - } - } -} - -/* - This function returns a pointer to a Dwarf_Abbrev_List_s - struct for the abbrev with the given code. It puts the - struct on the appropriate hash table. It also adds all - the abbrev between the last abbrev added and this one to - the hash table. In other words, the .debug_abbrev section - is scanned sequentially from the top for an abbrev with - the given code. All intervening abbrevs are also put - into the hash table. - - This function hashes the given code, and checks the chain - at that hash table entry to see if a Dwarf_Abbrev_List_s - with the given code exists. If yes, it returns a pointer - to that struct. Otherwise, it scans the .debug_abbrev - section from the last byte scanned for that CU till either - an abbrev with the given code is found, or an abbrev code - of 0 is read. It puts Dwarf_Abbrev_List_s entries for all - abbrev's read till that point into the hash table. The - hash table contains both a head pointer and a tail pointer - for each entry. - - While the lists can move and entries can be moved between - lists on reallocation, any given Dwarf_Abbrev_list entry - never moves once allocated, so the pointer is safe to return. - - Returns NULL on error. -*/ -Dwarf_Abbrev_List -_dwarf_get_abbrev_for_code(Dwarf_CU_Context cu_context, Dwarf_Unsigned code) -{ - Dwarf_Debug dbg = cu_context->cc_dbg; - Dwarf_Hash_Table hash_table_base = cu_context->cc_abbrev_hash_table; - Dwarf_Hash_Table_Entry entry_base = 0; - Dwarf_Hash_Table_Entry entry_cur = 0; - Dwarf_Word hash_num = 0; - Dwarf_Unsigned abbrev_code = 0; - Dwarf_Unsigned abbrev_tag = 0; - Dwarf_Unsigned attr_name = 0; - Dwarf_Unsigned attr_form = 0; - - Dwarf_Abbrev_List hash_abbrev_entry = 0; - - Dwarf_Abbrev_List inner_list_entry = 0; - Dwarf_Hash_Table_Entry inner_hash_entry = 0; - - Dwarf_Byte_Ptr abbrev_ptr = 0; - unsigned hashable_val; - - if ( !hash_table_base->tb_entries ) { - hash_table_base->tb_table_entry_count = HT_MULTIPLE; - hash_table_base->tb_total_abbrev_count= 0; - hash_table_base->tb_entries = _dwarf_get_alloc(dbg, - DW_DLA_HASH_TABLE_ENTRY, - hash_table_base->tb_table_entry_count); - if(! hash_table_base->tb_entries) { - return NULL; - } - - } else if (hash_table_base->tb_total_abbrev_count > - ( hash_table_base->tb_table_entry_count * HT_MULTIPLE) ) { - struct Dwarf_Hash_Table_s newht; - /* Effectively multiplies by >= HT_MULTIPLE */ - newht.tb_table_entry_count = hash_table_base->tb_total_abbrev_count; - newht.tb_total_abbrev_count = 0; - newht.tb_entries = _dwarf_get_alloc(dbg, - DW_DLA_HASH_TABLE_ENTRY, - newht.tb_table_entry_count); - - if(! newht.tb_entries) { - return NULL; - } - /* Copy the existing entries to the new table, - rehashing each. - */ - copy_abbrev_table_to_new_table(hash_table_base, &newht); - /* Dealloc only the entries hash table array, not the lists - of things pointed to by a hash table entry array. */ - dwarf_dealloc(dbg, hash_table_base->tb_entries,DW_DLA_HASH_TABLE_ENTRY); - hash_table_base->tb_entries = 0; - /* Now overwrite the existing table descriptor with - the new, newly valid, contents. */ - *hash_table_base = newht; - } /* Else is ok as is, add entry */ - - - hashable_val = code; - hash_num = hashable_val % - hash_table_base->tb_table_entry_count; - entry_base = hash_table_base->tb_entries; - entry_cur = entry_base + hash_num; - - /* Determine if the 'code' is the list of synonyms already. */ - for (hash_abbrev_entry = entry_cur->at_head; - hash_abbrev_entry != NULL && hash_abbrev_entry->ab_code != code; - hash_abbrev_entry = hash_abbrev_entry->ab_next); - if (hash_abbrev_entry != NULL) { - /* This returns a pointer to an abbrev list entry, not - the list itself. */ - return (hash_abbrev_entry); - } - - abbrev_ptr = cu_context->cc_last_abbrev_ptr != NULL ? - cu_context->cc_last_abbrev_ptr : - dbg->de_debug_abbrev.dss_data + cu_context->cc_abbrev_offset; - - /* End of abbrev's for this cu, since abbrev code is 0. */ - if (*abbrev_ptr == 0) { - return (NULL); - } - - do { - unsigned new_hashable_val; - DECODE_LEB128_UWORD(abbrev_ptr, abbrev_code); - DECODE_LEB128_UWORD(abbrev_ptr, abbrev_tag); - - inner_list_entry = (Dwarf_Abbrev_List) - _dwarf_get_alloc(cu_context->cc_dbg, DW_DLA_ABBREV_LIST, 1); - if (inner_list_entry == NULL) - return (NULL); - - new_hashable_val = abbrev_code; - hash_num = new_hashable_val % - hash_table_base->tb_table_entry_count; - inner_hash_entry = entry_base + hash_num; - /* Move_entry_to_new_hash */ - inner_list_entry->ab_next = inner_hash_entry->at_head; - inner_hash_entry->at_head = inner_list_entry; - - hash_table_base->tb_total_abbrev_count++; - - inner_list_entry->ab_code = abbrev_code; - inner_list_entry->ab_tag = abbrev_tag; - inner_list_entry->ab_has_child = *(abbrev_ptr++); - inner_list_entry->ab_abbrev_ptr = abbrev_ptr; - - /* Cycle thru the abbrev content, ignoring the content except - to find the end of the content. */ - do { - DECODE_LEB128_UWORD(abbrev_ptr, attr_name); - DECODE_LEB128_UWORD(abbrev_ptr, attr_form); - } while (attr_name != 0 && attr_form != 0); - - } while (*abbrev_ptr != 0 && abbrev_code != code); - - cu_context->cc_last_abbrev_ptr = abbrev_ptr; - return (abbrev_code == code ? inner_list_entry : NULL); -} - - -/* return 1 if string ends before 'endptr' else -** return 0 meaning string is not properly terminated. -** Presumption is the 'endptr' pts to end of some dwarf section data. -*/ -int -_dwarf_string_valid(void *startptr, void *endptr) -{ - - char *start = startptr; - char *end = endptr; - - while (start < end) { - if (*start == 0) { - return 1; /* OK! */ - } - ++start; - ++end; - } - return 0; /* FAIL! bad string! */ -} - -/* - A byte-swapping version of memcpy - for cross-endian use. - Only 2,4,8 should be lengths passed in. -*/ -void * -_dwarf_memcpy_swap_bytes(void *s1, const void *s2, size_t len) -{ - void *orig_s1 = s1; - unsigned char *targ = (unsigned char *) s1; - unsigned char *src = (unsigned char *) s2; - - if (len == 4) { - targ[3] = src[0]; - targ[2] = src[1]; - targ[1] = src[2]; - targ[0] = src[3]; - } else if (len == 8) { - targ[7] = src[0]; - targ[6] = src[1]; - targ[5] = src[2]; - targ[4] = src[3]; - targ[3] = src[4]; - targ[2] = src[5]; - targ[1] = src[6]; - targ[0] = src[7]; - } else if (len == 2) { - targ[1] = src[0]; - targ[0] = src[1]; - } -/* should NOT get below here: is not the intended use */ - else if (len == 1) { - targ[0] = src[0]; - } else { - memcpy(s1, s2, len); - } - - return orig_s1; -} - - -/* - This calculation used to be sprinkled all over. - Now brought to one place. - - We try to accurately compute the size of a cu header - given a known cu header location ( an offset in .debug_info). - -*/ -/* ARGSUSED */ -Dwarf_Unsigned -_dwarf_length_of_cu_header(Dwarf_Debug dbg, Dwarf_Unsigned offset) -{ - int local_length_size = 0; - int local_extension_size = 0; - Dwarf_Unsigned length = 0; - Dwarf_Small *cuptr = dbg->de_debug_info.dss_data + offset; - - READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned, - cuptr, local_length_size, local_extension_size); - - return local_extension_size + /* initial extesion, if present - */ - local_length_size + /* Size of cu length field. */ - sizeof(Dwarf_Half) + /* Size of version stamp field. */ - local_length_size + /* Size of abbrev offset field. */ - sizeof(Dwarf_Small); /* Size of address size field. */ - -} - -/* - Pretend we know nothing about the CU - and just roughly compute the result. -*/ -Dwarf_Unsigned -_dwarf_length_of_cu_header_simple(Dwarf_Debug dbg) -{ - return dbg->de_length_size + /* Size of cu length field. */ - sizeof(Dwarf_Half) + /* Size of version stamp field. */ - dbg->de_length_size + /* Size of abbrev offset field. */ - sizeof(Dwarf_Small); /* Size of address size field. */ -} - -/* Now that we delay loading .debug_info, we need to do the - load in more places. So putting the load - code in one place now instead of replicating it in multiple - places. - -*/ -int -_dwarf_load_debug_info(Dwarf_Debug dbg, Dwarf_Error * error) -{ - int res = DW_DLV_ERROR; - - /* Testing de_debug_info.dss_data allows us to avoid testing - de_debug_abbrev.dss_data. - One test instead of 2. .debug_info is useless - without .debug_abbrev. */ - if (dbg->de_debug_info.dss_data) { - return DW_DLV_OK; - } - - res = _dwarf_load_section(dbg, &dbg->de_debug_abbrev,error); - if (res != DW_DLV_OK) { - return res; - } - res = _dwarf_load_section(dbg, &dbg->de_debug_info, error); - return res; - -} -void -_dwarf_free_abbrev_hash_table_contents(Dwarf_Debug dbg,Dwarf_Hash_Table hash_table) -{ - /* A Hash Table is an array with tb_table_entry_count struct - Dwarf_Hash_Table_s entries in the array. */ - int hashnum = 0; - for (; hashnum < hash_table->tb_table_entry_count; ++hashnum) { - struct Dwarf_Abbrev_List_s *abbrev = 0; - struct Dwarf_Abbrev_List_s *nextabbrev = 0; - struct Dwarf_Hash_Table_Entry_s *tb = &hash_table->tb_entries[hashnum]; - - abbrev = tb->at_head; - for (; abbrev; abbrev = nextabbrev) { - nextabbrev = abbrev->ab_next; - dwarf_dealloc(dbg, abbrev, DW_DLA_ABBREV_LIST); - } - } - /* Frees all the entries at once: an array. */ - dwarf_dealloc(dbg,hash_table->tb_entries,DW_DLA_HASH_TABLE_ENTRY); -} - -/* - If no die provided the size value returned might be wrong. - If different compilation units have different address sizes - this may not give the correct value in all contexts if the die - pointer is NULL. - If the Elf offset size != address_size - (for example if address_size = 4 but recorded in elf64 object) - this may not give the correct value in all contexts if the die - pointer is NULL. - If the die pointer is non-NULL (in which case it must point to - a valid DIE) this will return the correct size. -*/ -int -_dwarf_get_address_size(Dwarf_Debug dbg, Dwarf_Die die) -{ - Dwarf_CU_Context context = 0; - Dwarf_Half addrsize = 0; - if(!die) { - return dbg->de_pointer_size; - } - context = die->di_cu_context; - addrsize = context->cc_address_size; - return addrsize; -} - - - diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_util.h b/usr/src/tools/ctf/dwarf/common/dwarf_util.h deleted file mode 100644 index 4046bb2478..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_util.h +++ /dev/null @@ -1,311 +0,0 @@ -#ifndef DWARF_UTIL_H -#define DWARF_UTIL_H -/* - - Copyright (C) 2000,2003,2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the Crittenden Lane address. -*/ - - - - -/* - Decodes unsigned leb128 encoded numbers. - Make sure ptr is a pointer to a 1-byte type. - In 2003 and earlier this was a hand-inlined - version of _dwarf_decode_u_leb128() which did - not work correctly if Dwarf_Word was 64 bits. -*/ -#define DECODE_LEB128_UWORD(ptr, value) \ - do { \ - Dwarf_Word uleblen; \ - value = _dwarf_decode_u_leb128(ptr,&uleblen); \ - ptr += uleblen; \ - } while (0) - -/* - Decodes signed leb128 encoded numbers. - Make sure ptr is a pointer to a 1-byte type. - In 2003 and earlier this was a hand-inlined - version of _dwarf_decode_s_leb128() which did - not work correctly if Dwarf_Word was 64 bits. - -*/ -#define DECODE_LEB128_SWORD(ptr, value) \ - do { \ - Dwarf_Word sleblen; \ - value = _dwarf_decode_s_leb128(ptr,&sleblen); \ - ptr += sleblen; \ - } while(0) - - -/* - Skips leb128_encoded numbers that are guaranteed - to be no more than 4 bytes long. Same for both - signed and unsigned numbers. -*/ -#define SKIP_LEB128_WORD(ptr) \ - do{ if ((*(ptr++) & 0x80) != 0) { \ - if ((*(ptr++) & 0x80) != 0) { \ - if ((*(ptr++) & 0x80) != 0) { \ - if ((*(ptr++) & 0x80) != 0) { \ - } \ - } \ - } \ - } } while (0) - - -#define CHECK_DIE(die, error_ret_value) \ -do {if (die == NULL) { \ - _dwarf_error(NULL, error, DW_DLE_DIE_NULL); \ - return(error_ret_value); \ - } \ - if (die->di_cu_context == NULL) { \ - _dwarf_error(NULL, error, DW_DLE_DIE_NO_CU_CONTEXT); \ - return(error_ret_value); \ - } \ - if (die->di_cu_context->cc_dbg == NULL) { \ - _dwarf_error(NULL, error, DW_DLE_DBG_NULL); \ - return(error_ret_value); \ - } \ -} while (0) - - -/* - Reads 'source' for 'length' bytes from unaligned addr. - - Avoids any constant-in-conditional warnings and - avoids a test in the generated code (for non-const cases, - which are in the majority.) - Uses a temp to avoid the test. - The decl here should avoid any problem of size in the temp. - This code is ENDIAN DEPENDENT - The memcpy args are the endian issue. -*/ -typedef Dwarf_Unsigned BIGGEST_UINT; - -#ifdef WORDS_BIGENDIAN -#define READ_UNALIGNED(dbg,dest,desttype, source, length) \ - do { \ - BIGGEST_UINT _ltmp = 0; \ - dbg->de_copy_word( (((char *)(&_ltmp)) + sizeof(_ltmp) - length), \ - source, length) ; \ - dest = (desttype)_ltmp; \ - } while (0) - - -/* - This macro sign-extends a variable depending on the length. - It fills the bytes between the size of the destination and - the length with appropriate padding. - This code is ENDIAN DEPENDENT but dependent only - on host endianness, not object file endianness. - The memcpy args are the issue. -*/ -#define SIGN_EXTEND(dest, length) \ - do {if (*(Dwarf_Sbyte *)((char *)&dest + sizeof(dest) - length) < 0) {\ - memcpy((char *)&dest, "\xff\xff\xff\xff\xff\xff\xff\xff", \ - sizeof(dest) - length); \ - } \ - } while (0) -#else /* LITTLE ENDIAN */ - -#define READ_UNALIGNED(dbg,dest,desttype, source, length) \ - do { \ - BIGGEST_UINT _ltmp = 0; \ - dbg->de_copy_word( (char *)(&_ltmp) , \ - source, length) ; \ - dest = (desttype)_ltmp; \ - } while (0) - - -/* - This macro sign-extends a variable depending on the length. - It fills the bytes between the size of the destination and - the length with appropriate padding. - This code is ENDIAN DEPENDENT but dependent only - on host endianness, not object file endianness. - The memcpy args are the issue. -*/ -#define SIGN_EXTEND(dest, length) \ - do {if (*(Dwarf_Sbyte *)((char *)&dest + (length-1)) < 0) {\ - memcpy((char *)&dest+length, \ - "\xff\xff\xff\xff\xff\xff\xff\xff", \ - sizeof(dest) - length); \ - } \ - } while (0) - -#endif /* ! LITTLE_ENDIAN */ - - - -/* - READ_AREA LENGTH reads the length (the older way - of pure 32 or 64 bit - or the new proposed dwarfv2.1 64bit-extension way) - - It reads the bits from where rw_src_data_p points to - and updates the rw_src_data_p to point past what was just read. - - It updates w_length_size (to the size of an offset, either 4 or 8) - and w_exten_size (set 0 unless this frame has the DWARF3,4 64bit - extension, in which case w_exten_size is set to 4). - - r_dbg is just the current dbg pointer. - w_target is the output length field. - r_targtype is the output type. Always Dwarf_Unsigned so far. - -*/ -/* This one handles the v2.1 64bit extension - and 32bit (and MIPS fixed 64 bit via the - dwarf_init-set r_dbg->de_length_size).. - It does not recognize any but the one distingushed value - (the only one with defined meaning). - It assumes that no CU will have a length - 0xffffffxx (32bit length) - or - 0xffffffxx xxxxxxxx (64bit length) - which makes possible auto-detection of the extension. - - This depends on knowing that only a non-zero length - is legitimate (AFAICT), and for IRIX non-standard -64 - dwarf that the first 32 bits of the 64bit offset will be - zero (because the compiler could not handle a truly large - value as of Jan 2003 and because no app has that much debug - info anyway, at least not in the IRIX case). - - At present not testing for '64bit elf' here as that - does not seem necessary (none of the 64bit length seems - appropriate unless it's ident[EI_CLASS] == ELFCLASS64). -*/ -# define READ_AREA_LENGTH(r_dbg,w_target,r_targtype, \ - rw_src_data_p,w_length_size,w_exten_size) \ -do { READ_UNALIGNED(r_dbg,w_target,r_targtype, \ - rw_src_data_p, ORIGINAL_DWARF_OFFSET_SIZE); \ - if(w_target == DISTINGUISHED_VALUE) { \ - /* dwarf3 64bit extension */ \ - w_length_size = DISTINGUISHED_VALUE_OFFSET_SIZE; \ - rw_src_data_p += ORIGINAL_DWARF_OFFSET_SIZE; \ - w_exten_size = ORIGINAL_DWARF_OFFSET_SIZE; \ - READ_UNALIGNED(r_dbg,w_target,r_targtype, \ - rw_src_data_p, DISTINGUISHED_VALUE_OFFSET_SIZE);\ - rw_src_data_p += DISTINGUISHED_VALUE_OFFSET_SIZE; \ - } else { \ - if(w_target == 0 && r_dbg->de_big_endian_object) { \ - /* IRIX 64 bit, big endian. This test */ \ - /* is not a truly precise test, a precise test */ \ - /* would check if the target was IRIX. */ \ - READ_UNALIGNED(r_dbg,w_target,r_targtype, \ - rw_src_data_p, DISTINGUISHED_VALUE_OFFSET_SIZE); \ - w_length_size = DISTINGUISHED_VALUE_OFFSET_SIZE; \ - rw_src_data_p += DISTINGUISHED_VALUE_OFFSET_SIZE; \ - w_exten_size = 0; \ - } else { \ - /* standard 32 bit dwarf2/dwarf3 */ \ - w_exten_size = 0; \ - w_length_size = ORIGINAL_DWARF_OFFSET_SIZE; \ - rw_src_data_p += w_length_size; \ - } \ - } } while(0) - -Dwarf_Unsigned -_dwarf_decode_u_leb128(Dwarf_Small * leb128, - Dwarf_Word * leb128_length); - -Dwarf_Signed -_dwarf_decode_s_leb128(Dwarf_Small * leb128, - Dwarf_Word * leb128_length); - -Dwarf_Unsigned -_dwarf_get_size_of_val(Dwarf_Debug dbg, - Dwarf_Unsigned form, - Dwarf_Half address_size, - Dwarf_Small * val_ptr, - int v_length_size); - -struct Dwarf_Hash_Table_Entry_s; -/* This single struct is the base for the hash table. - The intent is that once the total_abbrev_count across - all the entries is greater than 10*current_table_entry_count - one should build a new Dwarf_Hash_Table_Base_s, rehash - all the existing entries, and delete the old table and entries. - (10 is a heuristic, nothing magic about it, but once the - count gets to 30 or 40 times current_table_entry_count - things really slow down a lot. One (500MB) application had - 127000 abbreviations in one compilation unit) - The incoming 'code' is an abbrev number and those simply - increase linearly so the hashing is perfect always. -*/ -struct Dwarf_Hash_Table_s { - unsigned long tb_table_entry_count; - unsigned long tb_total_abbrev_count; - /* Each table entry is a list of abbreviations. */ - struct Dwarf_Hash_Table_Entry_s *tb_entries; -}; - -/* - This struct is used to build a hash table for the - abbreviation codes for a compile-unit. -*/ -struct Dwarf_Hash_Table_Entry_s { - Dwarf_Abbrev_List at_head; -}; - - - -Dwarf_Abbrev_List -_dwarf_get_abbrev_for_code(Dwarf_CU_Context cu_context, - Dwarf_Unsigned code); - - -/* return 1 if string ends before 'endptr' else -** return 0 meaning string is not properly terminated. -** Presumption is the 'endptr' pts to end of some dwarf section data. -*/ -int _dwarf_string_valid(void *startptr, void *endptr); - -Dwarf_Unsigned _dwarf_length_of_cu_header(Dwarf_Debug, - Dwarf_Unsigned offset); -Dwarf_Unsigned _dwarf_length_of_cu_header_simple(Dwarf_Debug); - -int _dwarf_load_debug_info(Dwarf_Debug dbg, Dwarf_Error *error); -void _dwarf_free_abbrev_hash_table_contents(Dwarf_Debug dbg, - struct Dwarf_Hash_Table_s* hash_table); -int _dwarf_get_address_size(Dwarf_Debug dbg, Dwarf_Die die); - -#endif /* DWARF_UTIL_H */ diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_vars.c b/usr/src/tools/ctf/dwarf/common/dwarf_vars.c deleted file mode 100644 index 24105289ba..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_vars.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - - Copyright (C) 2000,2002,2004,2005 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include "dwarf_vars.h" -#include "dwarf_global.h" - -int -dwarf_get_vars(Dwarf_Debug dbg, - Dwarf_Var ** vars, - Dwarf_Signed * ret_var_count, Dwarf_Error * error) -{ - int res = _dwarf_load_section(dbg, &dbg->de_debug_varnames,error); - if (res != DW_DLV_OK) { - return res; - } - - return _dwarf_internal_get_pubnames_like_data(dbg, - dbg->de_debug_varnames.dss_data, - dbg->de_debug_varnames.dss_size, - (Dwarf_Global **) vars, /* Type punning for sections - with identical format. */ - ret_var_count, - error, - DW_DLA_VAR_CONTEXT, - DW_DLA_VAR, - DW_DLE_DEBUG_VARNAMES_LENGTH_BAD, - DW_DLE_DEBUG_VARNAMES_VERSION_ERROR); -} - -/* Deallocating fully requires deallocating the list - and all entries. But some internal data is - not exposed, so we need a function with internal knowledge. -*/ - -void -dwarf_vars_dealloc(Dwarf_Debug dbg, Dwarf_Var * dwgl, - Dwarf_Signed count) -{ - _dwarf_internal_globals_dealloc(dbg, (Dwarf_Global *) dwgl, - count, - DW_DLA_VAR_CONTEXT, - DW_DLA_VAR, DW_DLA_LIST); - return; -} - - -int -dwarf_varname(Dwarf_Var var_in, char **ret_varname, Dwarf_Error * error) -{ - Dwarf_Global var = (Dwarf_Global) var_in; - - if (var == NULL) { - _dwarf_error(NULL, error, DW_DLE_VAR_NULL); - return (DW_DLV_ERROR); - } - - *ret_varname = (char *) (var->gl_name); - return DW_DLV_OK; -} - - -int -dwarf_var_die_offset(Dwarf_Var var_in, - Dwarf_Off * returned_offset, Dwarf_Error * error) -{ - Dwarf_Global var = (Dwarf_Global) var_in; - - return dwarf_global_die_offset(var, returned_offset, error); - -} - - -int -dwarf_var_cu_offset(Dwarf_Var var_in, - Dwarf_Off * returned_offset, Dwarf_Error * error) -{ - Dwarf_Global var = (Dwarf_Global) var_in; - - return dwarf_global_cu_offset(var, returned_offset, error); -} - - -int -dwarf_var_name_offsets(Dwarf_Var var_in, - char **returned_name, - Dwarf_Off * die_offset, - Dwarf_Off * cu_offset, Dwarf_Error * error) -{ - Dwarf_Global var = (Dwarf_Global) var_in; - - return - dwarf_global_name_offsets(var, - returned_name, die_offset, cu_offset, - error); -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_vars.h b/usr/src/tools/ctf/dwarf/common/dwarf_vars.h deleted file mode 100644 index bd5f967e48..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_vars.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - - -typedef struct Dwarf_Var_Context_s *Dwarf_Var_Context; - -/* struct never completed: see dwarf_global.h */ diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_weaks.c b/usr/src/tools/ctf/dwarf/common/dwarf_weaks.c deleted file mode 100644 index 425916e62e..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_weaks.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - - Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "dwarf_incl.h" -#include -#include "dwarf_weaks.h" -#include "dwarf_global.h" - -int -dwarf_get_weaks(Dwarf_Debug dbg, - Dwarf_Weak ** weaks, - Dwarf_Signed * ret_weak_count, Dwarf_Error * error) -{ - int res = _dwarf_load_section(dbg, &dbg->de_debug_weaknames,error); - if (res != DW_DLV_OK) { - return res; - } - - return _dwarf_internal_get_pubnames_like_data(dbg, - dbg->de_debug_weaknames.dss_data, - dbg->de_debug_weaknames.dss_size, - (Dwarf_Global **) weaks, /* Type punning for sections - with identical format. */ - ret_weak_count, - error, - DW_DLA_WEAK_CONTEXT, - DW_DLA_WEAK, - DW_DLE_DEBUG_WEAKNAMES_LENGTH_BAD, - DW_DLE_DEBUG_WEAKNAMES_VERSION_ERROR); -} - -/* Deallocating fully requires deallocating the list - and all entries. But some internal data is - not exposed, so we need a function with internal knowledge. -*/ - -void -dwarf_weaks_dealloc(Dwarf_Debug dbg, Dwarf_Weak * dwgl, - Dwarf_Signed count) -{ - _dwarf_internal_globals_dealloc(dbg, (Dwarf_Global *) dwgl, - count, - DW_DLA_WEAK_CONTEXT, - DW_DLA_WEAK, DW_DLA_LIST); - return; -} - - - -int -dwarf_weakname(Dwarf_Weak weak_in, char **ret_name, Dwarf_Error * error) -{ - Dwarf_Global weak = (Dwarf_Global) weak_in; - - if (weak == NULL) { - _dwarf_error(NULL, error, DW_DLE_WEAK_NULL); - return (DW_DLV_ERROR); - } - *ret_name = (char *) (weak->gl_name); - return DW_DLV_OK; -} - - -int -dwarf_weak_die_offset(Dwarf_Weak weak_in, - Dwarf_Off * weak_off, Dwarf_Error * error) -{ - Dwarf_Global weak = (Dwarf_Global) weak_in; - - return dwarf_global_die_offset(weak, weak_off, error); -} - - -int -dwarf_weak_cu_offset(Dwarf_Weak weak_in, - Dwarf_Off * weak_off, Dwarf_Error * error) -{ - Dwarf_Global weak = (Dwarf_Global) weak_in; - - return dwarf_global_cu_offset(weak, weak_off, error); -} - - -int -dwarf_weak_name_offsets(Dwarf_Weak weak_in, - char **weak_name, - Dwarf_Off * die_offset, - Dwarf_Off * cu_offset, Dwarf_Error * error) -{ - Dwarf_Global weak = (Dwarf_Global) weak_in; - - return dwarf_global_name_offsets(weak, - weak_name, die_offset, cu_offset, error); -} diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_weaks.h b/usr/src/tools/ctf/dwarf/common/dwarf_weaks.h deleted file mode 100644 index d38f5f118a..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_weaks.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - - -typedef struct Dwarf_Weak_Context_s *Dwarf_Weak_Context; - -/* struct never completed: see dwarf_global.h */ diff --git a/usr/src/tools/ctf/dwarf/common/libdwarf.h b/usr/src/tools/ctf/dwarf/common/libdwarf.h deleted file mode 100644 index 78627a96a6..0000000000 --- a/usr/src/tools/ctf/dwarf/common/libdwarf.h +++ /dev/null @@ -1,2736 +0,0 @@ -/* - - Copyright (C) 2000-2010 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. - Portions Copyright 2008-2010 David Anderson. All rights reserved. - Portions Copyright 2008-2010 Arxan Technologies, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - -#ifndef _LIBDWARF_H -#define _LIBDWARF_H -#ifdef __cplusplus -extern "C" { -#endif -/* - libdwarf.h - $Revision: #9 $ $Date: 2008/01/17 $ - - For libdwarf producers and consumers - - The interface is defined as having 8-byte signed and unsigned - values so it can handle 64-or-32bit target on 64-or-32bit host. - Addr is the native size: it represents pointers on - the host machine (not the target!). - - This contains declarations for types and all producer - and consumer functions. - - Function declarations are written on a single line each here - so one can use grep to each declaration in its entirety. - The declarations are a little harder to read this way, but... - -*/ - -struct Elf; -typedef struct Elf* dwarf_elf_handle; - -/* To enable printing with printf regardless of the - actual underlying data type, we define the DW_PR_xxx macros. */ -#if (_MIPS_SZLONG == 64) -/* Special case for MIPS, so -64 (LP64) build gets simple -long-. - Non-MIPS LP64 or ILP64 environments should probably ensure - _MIPS_SZLONG set to 64 everywhere this header is #included. -*/ -typedef int Dwarf_Bool; /* boolean type */ -typedef unsigned long Dwarf_Off; /* 4 or 8 byte file offset */ -typedef unsigned long Dwarf_Unsigned; /* 4 or 8 byte unsigned value */ -typedef unsigned short Dwarf_Half; /* 2 byte unsigned value */ -typedef unsigned char Dwarf_Small; /* 1 byte unsigned value */ -typedef signed long Dwarf_Signed; /* 4 or 8 byte signed value */ -typedef unsigned long Dwarf_Addr; /* target memory address */ -#define DW_PR_DUx "lx" -#define DW_PR_DSx "lx" -#define DW_PR_DUu "lu" -#define DW_PR_DSd "ld" - -#else /* 32-bit */ -/* This is for ILP32, allowing i/o of 64bit dwarf info. - Also should be fine for LP64 and ILP64 cases. -*/ -typedef int Dwarf_Bool; /* boolean type */ -typedef unsigned long long Dwarf_Off; /* 8 byte file offset */ -typedef unsigned long long Dwarf_Unsigned; /* 8 byte unsigned value*/ -typedef unsigned short Dwarf_Half; /* 2 byte unsigned value */ -typedef unsigned char Dwarf_Small; /* 1 byte unsigned value */ -typedef signed long long Dwarf_Signed; /* 8 byte signed value */ -typedef unsigned long long Dwarf_Addr; /* target memory address */ -#define DW_PR_DUx "llx" -#define DW_PR_DSx "llx" -#define DW_PR_DUu "llu" -#define DW_PR_DSd "lld" -#endif -#ifdef HAVE_NONSTANDARD_PRINTF_64_FORMAT -/* Windows does not use std C formatting, so allow it. */ -#undef DW_PR_DUx -#undef DW_PR_DSx -#undef DW_PR_DUu -#undef DW_PR_DSd -#define DW_PR_DUx "I64x" -#define DW_PR_DSx "I64x" -#define DW_PR_DUu "I64u" -#define DW_PR_DSd "I64d" -#endif /* HAVE_NONSTANDARD_FORMAT */ - -typedef void* Dwarf_Ptr; /* host machine pointer */ - -/* Used for DW_FORM_ref_sig8. It is not a string, it - is 8 bytes of a signature one would use to find - a type unit. See dwarf_formsig8() -*/ -typedef struct { - char signature[8]; -} Dwarf_Sig8; - -/* Contains info on an uninterpreted block of data -*/ -typedef struct { - Dwarf_Unsigned bl_len; /* length of block */ - Dwarf_Ptr bl_data; /* uninterpreted data */ - Dwarf_Small bl_from_loclist; /*non-0 if loclist, else debug_info*/ - Dwarf_Unsigned bl_section_offset; /* Section (not CU) offset - which 'data' comes from. */ -} Dwarf_Block; - - -/* location record -*/ -typedef struct { - Dwarf_Small lr_atom; /* location operation */ - Dwarf_Unsigned lr_number; /* operand */ - Dwarf_Unsigned lr_number2; /* for OP_BREGx */ - Dwarf_Unsigned lr_offset; /* offset in locexpr for OP_BRA etc */ -} Dwarf_Loc; - - -/* location description -*/ -typedef struct { - Dwarf_Addr ld_lopc; /* beginning of active range */ - Dwarf_Addr ld_hipc; /* end of active range */ - Dwarf_Half ld_cents; /* count of location records */ - Dwarf_Loc* ld_s; /* pointer to list of same */ - Dwarf_Small ld_from_loclist; - /* non-0 if loclist, else debug_info*/ - - Dwarf_Unsigned ld_section_offset; /* Section (not CU) offset - where loc-expr begins*/ -} Dwarf_Locdesc; - -/* First appears in DWARF3. - The dwr_addr1/addr2 data is either an offset (DW_RANGES_ENTRY) - or an address (dwr_addr2 in DW_RANGES_ADDRESS_SELECTION) or - both are zero (DW_RANGES_END). -*/ -enum Dwarf_Ranges_Entry_Type { DW_RANGES_ENTRY, - DW_RANGES_ADDRESS_SELECTION, - DW_RANGES_END }; -typedef struct { - Dwarf_Addr dwr_addr1; - Dwarf_Addr dwr_addr2; - enum Dwarf_Ranges_Entry_Type dwr_type; -} Dwarf_Ranges; - -/* Frame description instructions expanded. -*/ -typedef struct { - Dwarf_Small fp_base_op; - Dwarf_Small fp_extended_op; - Dwarf_Half fp_register; - - /* Value may be signed, depends on op. - Any applicable data_alignment_factor has - not been applied, this is the raw offset. */ - Dwarf_Unsigned fp_offset; - Dwarf_Off fp_instr_offset; -} Dwarf_Frame_Op; /* DWARF2 */ - -typedef struct { - Dwarf_Small fp_base_op; - Dwarf_Small fp_extended_op; - Dwarf_Half fp_register; - - /* Value may be signed, depends on op. - Any applicable data_alignment_factor has - not been applied, this is the raw offset. */ - Dwarf_Unsigned fp_offset_or_block_len; - Dwarf_Small *fp_expr_block; - - Dwarf_Off fp_instr_offset; -} Dwarf_Frame_Op3; /* DWARF3 and DWARF2 compatible */ - -/* ***IMPORTANT NOTE, TARGET DEPENDENCY **** - DW_REG_TABLE_SIZE must be at least as large as - the number of registers - (DW_FRAME_LAST_REG_NUM) as defined in dwarf.h - Preferably identical to DW_FRAME_LAST_REG_NUM. - Ensure [0-DW_REG_TABLE_SIZE] does not overlap - DW_FRAME_UNDEFINED_VAL or DW_FRAME_SAME_VAL. - Also ensure DW_FRAME_REG_INITIAL_VALUE is set to what - is appropriate to your cpu. - For various CPUs DW_FRAME_UNDEFINED_VAL is correct - as the value for DW_FRAME_REG_INITIAL_VALUE. - - For consumer apps, this can be set dynamically: see - dwarf_set_frame_rule_table_size(); - */ -#ifndef DW_REG_TABLE_SIZE -#define DW_REG_TABLE_SIZE 66 -#endif - -/* For MIPS, DW_FRAME_SAME_VAL is the correct default value - for a frame register value. For other CPUS another value - may be better, such as DW_FRAME_UNDEFINED_VAL. - See dwarf_set_frame_rule_table_size -*/ -#ifndef DW_FRAME_REG_INITIAL_VALUE -#define DW_FRAME_REG_INITIAL_VALUE DW_FRAME_SAME_VAL -#endif - -/* Taken as meaning 'undefined value', this is not - a column or register number. - Only present at libdwarf runtime in the consumer - interfaces. Never on disk. - DW_FRAME_* Values present on disk are in dwarf.h - Ensure this is > DW_REG_TABLE_SIZE (the reg table - size is changeable at runtime with the *reg3() interfaces, - and this value must be greater than the reg table size). -*/ -#define DW_FRAME_UNDEFINED_VAL 1034 - -/* Taken as meaning 'same value' as caller had, not a column - or register number. - Only present at libdwarf runtime in the consumer - interfaces. Never on disk. - DW_FRAME_* Values present on disk are in dwarf.h - Ensure this is > DW_REG_TABLE_SIZE (the reg table - size is changeable at runtime with the *reg3() interfaces, - and this value must be greater than the reg table size). -*/ -#define DW_FRAME_SAME_VAL 1035 - -/* For DWARF3 consumer interfaces, make the CFA a column with no - real table number. This is what should have been done - for the DWARF2 interfaces. This actually works for - both DWARF2 and DWARF3, but see the libdwarf documentation - on Dwarf_Regtable3 and dwarf_get_fde_info_for_reg3() - and dwarf_get_fde_info_for_all_regs3() - Do NOT use this with the older dwarf_get_fde_info_for_reg() - or dwarf_get_fde_info_for_all_regs() consumer interfaces. - Must be higher than any register count for *any* ABI - (ensures maximum applicability with minimum effort). - Ensure this is > DW_REG_TABLE_SIZE (the reg table - size is changeable at runtime with the *reg3() interfaces, - and this value must be greater than the reg table size). - Only present at libdwarf runtime in the consumer - interfaces. Never on disk. -*/ -#define DW_FRAME_CFA_COL3 1436 - -/* The following are all needed to evaluate DWARF3 register rules. -*/ -#define DW_EXPR_OFFSET 0 /* DWARF2 only sees this. */ -#define DW_EXPR_VAL_OFFSET 1 -#define DW_EXPR_EXPRESSION 2 -#define DW_EXPR_VAL_EXPRESSION 3 - -typedef struct Dwarf_Regtable_Entry_s { - /* For each index i (naming a hardware register with dwarf number - i) the following is true and defines the value of that register: - - If dw_regnum is Register DW_FRAME_UNDEFINED_VAL - it is not DWARF register number but - a place holder indicating the register has no defined value. - If dw_regnum is Register DW_FRAME_SAME_VAL - it is not DWARF register number but - a place holder indicating the register has the same - value in the previous frame. - DW_FRAME_UNDEFINED_VAL, DW_FRAME_SAME_VAL are - only present at libdwarf runtime. Never on disk. - DW_FRAME_* Values present on disk are in dwarf.h - - Otherwise: the register number is a DWARF register number - (see ABI documents for how this translates to hardware/ - software register numbers in the machine hardware) - and the following applies: - - if dw_value_type == DW_EXPR_OFFSET (the only case for dwarf2): - If dw_offset_relevant is non-zero, then - the value is stored at at the address CFA+N where - N is a signed offset. - Rule: Offset(N) - If dw_offset_relevant is zero, then the value of the register - is the value of (DWARF) register number dw_regnum. - Rule: register(F) - Other values of dw_value_type are an error. - */ - Dwarf_Small dw_offset_relevant; - - /* For DWARF2, always 0 */ - Dwarf_Small dw_value_type; - - Dwarf_Half dw_regnum; - - /* The data type here should the larger of Dwarf_Addr - and Dwarf_Unsigned and Dwarf_Signed. */ - Dwarf_Addr dw_offset; -} Dwarf_Regtable_Entry; - -typedef struct Dwarf_Regtable_s { - struct Dwarf_Regtable_Entry_s rules[DW_REG_TABLE_SIZE]; -} Dwarf_Regtable; - -/* opaque type. Functional interface shown later. */ -struct Dwarf_Reg_value3_s; -typedef struct Dwarf_Reg_value3_s Dwarf_Reg_Value3; - -typedef struct Dwarf_Regtable_Entry3_s { - /* For each index i (naming a hardware register with dwarf number - i) the following is true and defines the value of that register: - - If dw_regnum is Register DW_FRAME_UNDEFINED_VAL - it is not DWARF register number but - a place holder indicating the register has no defined value. - If dw_regnum is Register DW_FRAME_SAME_VAL - it is not DWARF register number but - a place holder indicating the register has the same - value in the previous frame. - DW_FRAME_UNDEFINED_VAL, DW_FRAME_SAME_VAL and - DW_FRAME_CFA_COL3 are only present at libdwarf runtime. - Never on disk. - DW_FRAME_* Values present on disk are in dwarf.h - Because DW_FRAME_SAME_VAL and DW_FRAME_UNDEFINED_VAL - and DW_FRAME_CFA_COL3 are defineable at runtime - consider the names symbolic in this comment, not absolute. - - Otherwise: the register number is a DWARF register number - (see ABI documents for how this translates to hardware/ - software register numbers in the machine hardware) - and the following applies: - - In a cfa-defining entry (rt3_cfa_rule) the regnum is the - CFA 'register number'. Which is some 'normal' register, - not DW_FRAME_CFA_COL3, nor DW_FRAME_SAME_VAL, nor - DW_FRAME_UNDEFINED_VAL. - - If dw_value_type == DW_EXPR_OFFSET (the only possible case for - dwarf2): - If dw_offset_relevant is non-zero, then - the value is stored at at the address - CFA+N where N is a signed offset. - dw_regnum is the cfa register rule which means - one ignores dw_regnum and uses the CFA appropriately. - So dw_offset_or_block_len is a signed value, really, - and must be printed/evaluated as such. - Rule: Offset(N) - If dw_offset_relevant is zero, then the value of the register - is the value of (DWARF) register number dw_regnum. - Rule: register(R) - If dw_value_type == DW_EXPR_VAL_OFFSET - the value of this register is CFA +N where N is a signed offset. - dw_regnum is the cfa register rule which means - one ignores dw_regnum and uses the CFA appropriately. - Rule: val_offset(N) - If dw_value_type == DW_EXPR_EXPRESSION - The value of the register is the value at the address - computed by evaluating the DWARF expression E. - Rule: expression(E) - The expression E byte stream is pointed to by dw_block_ptr. - The expression length in bytes is given by - dw_offset_or_block_len. - If dw_value_type == DW_EXPR_VAL_EXPRESSION - The value of the register is the value - computed by evaluating the DWARF expression E. - Rule: val_expression(E) - The expression E byte stream is pointed to by dw_block_ptr. - The expression length in bytes is given by - dw_offset_or_block_len. - Other values of dw_value_type are an error. - */ - Dwarf_Small dw_offset_relevant; - Dwarf_Small dw_value_type; - Dwarf_Half dw_regnum; - Dwarf_Unsigned dw_offset_or_block_len; - Dwarf_Ptr dw_block_ptr; - -}Dwarf_Regtable_Entry3; - -/* For the DWARF3 version, moved the DW_FRAME_CFA_COL - out of the array and into its own struct. - Having it part of the array is not very easy to work - with from a portability point of view: changing - the number for every architecture is a pain (if one fails - to set it correctly a register rule gets clobbered when - setting CFA). With MIPS it just happened to be easy to use - DW_FRAME_CFA_COL (it was wrong conceptually but it was easy...). - - rt3_rules and rt3_reg_table_size must be filled in before - calling libdwarf. Filled in with a pointer to an array - (pointer and array set up by the calling application) - of rt3_reg_table_size Dwarf_Regtable_Entry3_s structs. - libdwarf does not allocate or deallocate space for the - rules, you must do so. libdwarf will initialize the - contents rules array, you do not need to do so (though - if you choose to initialize the array somehow that is ok: - libdwarf will overwrite your initializations with its own). - -*/ -typedef struct Dwarf_Regtable3_s { - struct Dwarf_Regtable_Entry3_s rt3_cfa_rule; - - Dwarf_Half rt3_reg_table_size; - struct Dwarf_Regtable_Entry3_s * rt3_rules; -} Dwarf_Regtable3; - - -/* Use for DW_EPXR_STANDARD., DW_EXPR_VAL_OFFSET. - Returns DW_DLV_OK if the value is available. - If DW_DLV_OK returns the regnum and offset thru the pointers - (which the consumer must use appropriately). -*/ -int dwarf_frame_get_reg_register(struct Dwarf_Regtable_Entry3_s *reg_in, - Dwarf_Small *offset_relevant, - Dwarf_Half *regnum_out, - Dwarf_Signed *offset_out); - -/* Use for DW_EXPR_EXPRESSION, DW_EXPR_VAL_EXPRESSION. - Returns DW_DLV_OK if the value is available. - The caller must pass in the address of a valid - Dwarf_Block (the caller need not initialize it). -*/ -int dwarf_frame_get_reg_expression(struct Dwarf_Regtable_Entry3_s *reg_in, - Dwarf_Block *block_out); - - -/* For DW_DLC_SYMBOLIC_RELOCATIONS output to caller - v2, adding drd_length: some relocations are 4 and - some 8 bytes (pointers are 8, section offsets 4) in - some dwarf environments. (MIPS relocations are all one - size in any given ABI.) Changing drd_type to an unsigned char - to keep struct size down. -*/ -enum Dwarf_Rel_Type { - dwarf_drt_none, /* Should not get to caller */ - dwarf_drt_data_reloc, /* Simple normal relocation. */ - dwarf_drt_segment_rel, /* Special reloc, exceptions. */ - /* dwarf_drt_first_of_length_pair and drt_second - are for for the .word end - begin case. */ - dwarf_drt_first_of_length_pair, - dwarf_drt_second_of_length_pair -}; - -typedef struct Dwarf_P_Marker_s * Dwarf_P_Marker; -struct Dwarf_P_Marker_s { - Dwarf_Unsigned ma_marker; - Dwarf_Unsigned ma_offset; -}; - -typedef struct Dwarf_Relocation_Data_s * Dwarf_Relocation_Data; -struct Dwarf_Relocation_Data_s { - unsigned char drd_type; /* Cast to/from Dwarf_Rel_Type - to keep size small in struct. */ - unsigned char drd_length; /* Length in bytes of data being - relocated. 4 for 32bit data, - 8 for 64bit data. */ - Dwarf_Unsigned drd_offset; /* Where the data to reloc is. */ - Dwarf_Unsigned drd_symbol_index; -}; - -typedef struct Dwarf_P_String_Attr_s * Dwarf_P_String_Attr; -struct Dwarf_P_String_Attr_s { - Dwarf_Unsigned sa_offset; /* Offset of string attribute data */ - Dwarf_Unsigned sa_nbytes; -}; - - -/* Opaque types for Consumer Library. */ -typedef struct Dwarf_Debug_s* Dwarf_Debug; -typedef struct Dwarf_Die_s* Dwarf_Die; -typedef struct Dwarf_Line_s* Dwarf_Line; -typedef struct Dwarf_Global_s* Dwarf_Global; -typedef struct Dwarf_Func_s* Dwarf_Func; -typedef struct Dwarf_Type_s* Dwarf_Type; -typedef struct Dwarf_Var_s* Dwarf_Var; -typedef struct Dwarf_Weak_s* Dwarf_Weak; -typedef struct Dwarf_Error_s* Dwarf_Error; -typedef struct Dwarf_Attribute_s* Dwarf_Attribute; -typedef struct Dwarf_Abbrev_s* Dwarf_Abbrev; -typedef struct Dwarf_Fde_s* Dwarf_Fde; -typedef struct Dwarf_Cie_s* Dwarf_Cie; -typedef struct Dwarf_Arange_s* Dwarf_Arange; - -/* Opaque types for Producer Library. */ -typedef struct Dwarf_P_Debug_s* Dwarf_P_Debug; -typedef struct Dwarf_P_Die_s* Dwarf_P_Die; -typedef struct Dwarf_P_Attribute_s* Dwarf_P_Attribute; -typedef struct Dwarf_P_Fde_s* Dwarf_P_Fde; -typedef struct Dwarf_P_Expr_s* Dwarf_P_Expr; -typedef Dwarf_Unsigned Dwarf_Tag; - - -/* error handler function -*/ -typedef void (*Dwarf_Handler)(Dwarf_Error /*error*/, Dwarf_Ptr /*errarg*/); - - -/* Begin libdwarf Object File Interface declarations. - -As of February 2008 there are multiple dwarf_reader object access -initialization methods available: -The traditional dwarf_elf_init() and dwarf_init() and dwarf_finish() - which assume libelf and POSIX file access. -An object-file and library agnostic dwarf_object_init() and dwarf_object_finish() - which allow the coder to provide object access routines - abstracting away the elf interface. So there is no dependence in the - reader code on the object format and no dependence on libelf. - See the code in dwarf_elf_access.c and dwarf_original_elf_init.c - to see an example of initializing the structures mentioned below. - -Projects using dwarf_elf_init() or dwarf_init() can ignore -the Dwarf_Obj_Access* structures entirely as all these details -are completed for you. - -*/ - -typedef struct Dwarf_Obj_Access_Interface_s Dwarf_Obj_Access_Interface; -typedef struct Dwarf_Obj_Access_Methods_s Dwarf_Obj_Access_Methods; -typedef struct Dwarf_Obj_Access_Section_s Dwarf_Obj_Access_Section; - - -/* Used in the get_section interface function - in Dwarf_Obj_Access_Section_s. Since libdwarf - depends on standard DWARF section names an object - format that has no such names (but has some - method of setting up 'sections equivalents') - must arrange to return standard DWARF section - names in the 'name' field. libdwarf does - not free the strings in 'name'. */ -struct Dwarf_Obj_Access_Section_s { - Dwarf_Addr addr; - Dwarf_Unsigned size; - const char* name; - /* Set link to zero if it is meaningless. If non-zero - it should be a link to a rela section or from symtab - to strtab. In Elf it is sh_link. */ - Dwarf_Unsigned link; -}; - -/* Returned by the get_endianness function in - Dwarf_Obj_Access_Methods_s. */ -typedef enum { - DW_OBJECT_MSB, - DW_OBJECT_LSB -} Dwarf_Endianness; - -/* The functions we need to access object data from libdwarf are declared here. - - In these function pointer declarations - 'void *obj' is intended to be a pointer (the object field in - Dwarf_Obj_Access_Interface_s) - that hides the library-specific and object-specific data that makes - it possible to handle multiple object formats and multiple libraries. - It's not required that one handles multiple such in a single libdwarf - archive/shared-library (but not ruled out either). - See dwarf_elf_object_access_internals_t and dwarf_elf_access.c - for an example. - -*/ -struct Dwarf_Obj_Access_Methods_s { - /** - * get_section_info - * - * Get address, size, and name info about a section. - * - * Parameters - * section_index - Zero-based index. - * return_section - Pointer to a structure in which section info - * will be placed. Caller must provide a valid pointer to a - * structure area. The structure's contents will be overwritten - * by the call to get_section_info. - * error - A pointer to an integer in which an error code may be stored. - * - * Return - * DW_DLV_OK - Everything ok. - * DW_DLV_ERROR - Error occurred. Use 'error' to determine the - * libdwarf defined error. - * DW_DLV_NO_ENTRY - No such section. - */ - int (*get_section_info)(void* obj, Dwarf_Half section_index, - Dwarf_Obj_Access_Section* return_section, int* error); - /** - * get_byte_order - * - * Get whether the object file represented by this interface is big-endian - * (DW_OBJECT_MSB) or little endian (DW_OBJECT_LSB). - * - * Parameters - * obj - Equivalent to 'this' in OO languages. - * - * Return - * Endianness of object. Cannot fail. - */ - Dwarf_Endianness (*get_byte_order)(void* obj); - /** - * get_length_size - * - * Get the size of a length field in the underlying object file. - * libdwarf currently supports * 4 and 8 byte sizes, but may - * support larger in the future. - * Perhaps the return type should be an enumeration? - * - * Parameters - * obj - Equivalent to 'this' in OO languages. - * - * Return - * Size of length. Cannot fail. - */ - Dwarf_Small (*get_length_size)(void* obj); - /** - * get_pointer_size - * - * Get the size of a pointer field in the underlying object file. - * libdwarf currently supports 4 and 8 byte sizes. - * Perhaps the return type should be an enumeration? - - * Return - * Size of pointer. Cannot fail. - */ - Dwarf_Small (*get_pointer_size)(void* obj); - /** - * get_section_count - * - * Get the number of sections in the object file. - * - * Parameters - * - * Return - * Number of sections - */ - Dwarf_Unsigned (*get_section_count)(void* obj); - /** - * load_section - * - * Get a pointer to an array of bytes that represent the section. - * - * Parameters - * section_index - Zero-based index. - * return_data - The address of a pointer to which the section data block - * will be assigned. - * error - Pointer to an integer for returning libdwarf-defined - * error numbers. - * - * Return - * DW_DLV_OK - No error. - * DW_DLV_ERROR - Error. Use 'error' to indicate a libdwarf-defined - * error number. - * DW_DLV_NO_ENTRY - No such section. - */ - int (*load_section)(void* obj, Dwarf_Half section_index, - Dwarf_Small** return_data, int* error); - - /** - * relocate_a_section - * If relocations are not supported leave this pointer NULL. - * - * Get a pointer to an array of bytes that represent the section. - * - * Parameters - * section_index - Zero-based index of the section to be relocated. - * error - Pointer to an integer for returning libdwarf-defined - * error numbers. - * - * Return - * DW_DLV_OK - No error. - * DW_DLV_ERROR - Error. Use 'error' to indicate a libdwarf-defined - * error number. - * DW_DLV_NO_ENTRY - No such section. - */ - int (*relocate_a_section)(void* obj, Dwarf_Half section_index, - Dwarf_Debug dbg, - int* error); - -}; - - - -/* These structures are allocated and deallocated by your code - when you are using the libdwarf Object File Interface - [dwarf_object_init() and dwarf_object_finish()] directly. - dwarf_object_finish() does not free - struct Dwarf_Obj_Access_Interface_s or its content. - (libdwarf does record a pointer to this struct: you must - ensure that pointer remains valid for as long as - a libdwarf instance is open (meaning - after dwarf_init() and before dwarf_finish()). - - If you are reading Elf objects and libelf use dwarf_init() - or dwarf_elf_init() which take care of these details. -*/ -struct Dwarf_Obj_Access_Interface_s { - /* object is a void* as it hides the data the object access routines - need (which varies by library in use and object format). - */ - void* object; - const Dwarf_Obj_Access_Methods * methods; -}; - -/* End libdwarf Object File Interface */ - -/* - Dwarf_dealloc() alloc_type arguments. - Argument points to: -*/ -#define DW_DLA_STRING 0x01 /* char* */ -#define DW_DLA_LOC 0x02 /* Dwarf_Loc */ -#define DW_DLA_LOCDESC 0x03 /* Dwarf_Locdesc */ -#define DW_DLA_ELLIST 0x04 /* Dwarf_Ellist (not used)*/ -#define DW_DLA_BOUNDS 0x05 /* Dwarf_Bounds (not used) */ -#define DW_DLA_BLOCK 0x06 /* Dwarf_Block */ -#define DW_DLA_DEBUG 0x07 /* Dwarf_Debug */ -#define DW_DLA_DIE 0x08 /* Dwarf_Die */ -#define DW_DLA_LINE 0x09 /* Dwarf_Line */ -#define DW_DLA_ATTR 0x0a /* Dwarf_Attribute */ -#define DW_DLA_TYPE 0x0b /* Dwarf_Type (not used) */ -#define DW_DLA_SUBSCR 0x0c /* Dwarf_Subscr (not used) */ -#define DW_DLA_GLOBAL 0x0d /* Dwarf_Global */ -#define DW_DLA_ERROR 0x0e /* Dwarf_Error */ -#define DW_DLA_LIST 0x0f /* a list */ -#define DW_DLA_LINEBUF 0x10 /* Dwarf_Line* (not used) */ -#define DW_DLA_ARANGE 0x11 /* Dwarf_Arange */ -#define DW_DLA_ABBREV 0x12 /* Dwarf_Abbrev */ -#define DW_DLA_FRAME_OP 0x13 /* Dwarf_Frame_Op */ -#define DW_DLA_CIE 0x14 /* Dwarf_Cie */ -#define DW_DLA_FDE 0x15 /* Dwarf_Fde */ -#define DW_DLA_LOC_BLOCK 0x16 /* Dwarf_Loc Block (not used) */ -#define DW_DLA_FRAME_BLOCK 0x17 /* Dwarf_Frame Block (not used) */ -#define DW_DLA_FUNC 0x18 /* Dwarf_Func */ -#define DW_DLA_TYPENAME 0x19 /* Dwarf_Type */ -#define DW_DLA_VAR 0x1a /* Dwarf_Var */ -#define DW_DLA_WEAK 0x1b /* Dwarf_Weak */ -#define DW_DLA_ADDR 0x1c /* Dwarf_Addr sized entries */ -#define DW_DLA_RANGES 0x1d /* Dwarf_Ranges */ - -/* The augmenter string for CIE */ -#define DW_CIE_AUGMENTER_STRING_V0 "z" - -/* dwarf_init() access arguments -*/ -#define DW_DLC_READ 0 /* read only access */ -#define DW_DLC_WRITE 1 /* write only access */ -#define DW_DLC_RDWR 2 /* read/write access NOT SUPPORTED*/ - -/* pro_init() access flag modifiers - If HAVE_DWARF2_99_EXTENSION is defined at libdwarf build time - and DW_DLC_OFFSET_SIZE_64 is passed in pro_init() flags then the DWARF3 - 64 bit offset extension is used to generate 64 bit offsets. -*/ -#define DW_DLC_SIZE_64 0x40000000 /* 32-bit address-size target */ -#define DW_DLC_SIZE_32 0x20000000 /* 64-bit address-size target */ -#define DW_DLC_OFFSET_SIZE_64 0x10000000 /* 64-bit offset-size DWARF */ - -/* dwarf_pro_init() access flag modifiers -*/ -#define DW_DLC_ISA_MIPS 0x00000000 /* MIPS target */ -#define DW_DLC_ISA_IA64 0x01000000 /* IA64 target */ -#define DW_DLC_STREAM_RELOCATIONS 0x02000000 /* Old style binary relocs */ - - /* Usable with assembly output because it is up to the producer to - deal with locations in whatever manner the producer code wishes. - Possibly emitting text an assembler will recognize. */ -#define DW_DLC_SYMBOLIC_RELOCATIONS 0x04000000 - -#define DW_DLC_TARGET_BIGENDIAN 0x08000000 /* Big endian target */ -#define DW_DLC_TARGET_LITTLEENDIAN 0x00100000 /* Little endian target */ - -#if 0 - /* - The libdwarf producer interfaces jumble these two semantics together in - confusing ways. We *should* have flags like these... - But changing the code means a lot of diffs. So for now, - we leave things as they are - */ - #define DW_DLC_SUN_OFFSET32 0x00010000 /* use 32-bit sec offsets */ - #define DW_DLC_SUN_OFFSET64 0x00020000 /* use 64-bit sec offsets */ - #define DW_DLC_SUN_POINTER32 0x00040000 /* use 4 for address_size */ - #define DW_DLC_SUN_POINTER64 0x00080000 /* use 8 for address_size */ -#endif - -/* dwarf_pcline() slide arguments -*/ -#define DW_DLS_BACKWARD -1 /* slide backward to find line */ -#define DW_DLS_NOSLIDE 0 /* match exactly without sliding */ -#define DW_DLS_FORWARD 1 /* slide forward to find line */ - -/* libdwarf error numbers -*/ -#define DW_DLE_NE 0 /* no error */ -#define DW_DLE_VMM 1 /* dwarf format/library version mismatch */ -#define DW_DLE_MAP 2 /* memory map failure */ -#define DW_DLE_LEE 3 /* libelf error */ -#define DW_DLE_NDS 4 /* no debug section */ -#define DW_DLE_NLS 5 /* no line section */ -#define DW_DLE_ID 6 /* invalid descriptor for query */ -#define DW_DLE_IOF 7 /* I/O failure */ -#define DW_DLE_MAF 8 /* memory allocation failure */ -#define DW_DLE_IA 9 /* invalid argument */ -#define DW_DLE_MDE 10 /* mangled debugging entry */ -#define DW_DLE_MLE 11 /* mangled line number entry */ -#define DW_DLE_FNO 12 /* file not open */ -#define DW_DLE_FNR 13 /* file not a regular file */ -#define DW_DLE_FWA 14 /* file open with wrong access */ -#define DW_DLE_NOB 15 /* not an object file */ -#define DW_DLE_MOF 16 /* mangled object file header */ -#define DW_DLE_EOLL 17 /* end of location list entries */ -#define DW_DLE_NOLL 18 /* no location list section */ -#define DW_DLE_BADOFF 19 /* Invalid offset */ -#define DW_DLE_EOS 20 /* end of section */ -#define DW_DLE_ATRUNC 21 /* abbreviations section appears truncated*/ -#define DW_DLE_BADBITC 22 /* Address size passed to dwarf bad*/ - /* It is not an allowed size (64 or 32) */ - /* Error codes defined by the current Libdwarf Implementation. */ -#define DW_DLE_DBG_ALLOC 23 -#define DW_DLE_FSTAT_ERROR 24 -#define DW_DLE_FSTAT_MODE_ERROR 25 -#define DW_DLE_INIT_ACCESS_WRONG 26 -#define DW_DLE_ELF_BEGIN_ERROR 27 -#define DW_DLE_ELF_GETEHDR_ERROR 28 -#define DW_DLE_ELF_GETSHDR_ERROR 29 -#define DW_DLE_ELF_STRPTR_ERROR 30 -#define DW_DLE_DEBUG_INFO_DUPLICATE 31 -#define DW_DLE_DEBUG_INFO_NULL 32 -#define DW_DLE_DEBUG_ABBREV_DUPLICATE 33 -#define DW_DLE_DEBUG_ABBREV_NULL 34 -#define DW_DLE_DEBUG_ARANGES_DUPLICATE 35 -#define DW_DLE_DEBUG_ARANGES_NULL 36 -#define DW_DLE_DEBUG_LINE_DUPLICATE 37 -#define DW_DLE_DEBUG_LINE_NULL 38 -#define DW_DLE_DEBUG_LOC_DUPLICATE 39 -#define DW_DLE_DEBUG_LOC_NULL 40 -#define DW_DLE_DEBUG_MACINFO_DUPLICATE 41 -#define DW_DLE_DEBUG_MACINFO_NULL 42 -#define DW_DLE_DEBUG_PUBNAMES_DUPLICATE 43 -#define DW_DLE_DEBUG_PUBNAMES_NULL 44 -#define DW_DLE_DEBUG_STR_DUPLICATE 45 -#define DW_DLE_DEBUG_STR_NULL 46 -#define DW_DLE_CU_LENGTH_ERROR 47 -#define DW_DLE_VERSION_STAMP_ERROR 48 -#define DW_DLE_ABBREV_OFFSET_ERROR 49 -#define DW_DLE_ADDRESS_SIZE_ERROR 50 -#define DW_DLE_DEBUG_INFO_PTR_NULL 51 -#define DW_DLE_DIE_NULL 52 -#define DW_DLE_STRING_OFFSET_BAD 53 -#define DW_DLE_DEBUG_LINE_LENGTH_BAD 54 -#define DW_DLE_LINE_PROLOG_LENGTH_BAD 55 -#define DW_DLE_LINE_NUM_OPERANDS_BAD 56 -#define DW_DLE_LINE_SET_ADDR_ERROR 57 /* No longer used. */ -#define DW_DLE_LINE_EXT_OPCODE_BAD 58 -#define DW_DLE_DWARF_LINE_NULL 59 -#define DW_DLE_INCL_DIR_NUM_BAD 60 -#define DW_DLE_LINE_FILE_NUM_BAD 61 -#define DW_DLE_ALLOC_FAIL 62 -#define DW_DLE_NO_CALLBACK_FUNC 63 -#define DW_DLE_SECT_ALLOC 64 -#define DW_DLE_FILE_ENTRY_ALLOC 65 -#define DW_DLE_LINE_ALLOC 66 -#define DW_DLE_FPGM_ALLOC 67 -#define DW_DLE_INCDIR_ALLOC 68 -#define DW_DLE_STRING_ALLOC 69 -#define DW_DLE_CHUNK_ALLOC 70 -#define DW_DLE_BYTEOFF_ERR 71 -#define DW_DLE_CIE_ALLOC 72 -#define DW_DLE_FDE_ALLOC 73 -#define DW_DLE_REGNO_OVFL 74 -#define DW_DLE_CIE_OFFS_ALLOC 75 -#define DW_DLE_WRONG_ADDRESS 76 -#define DW_DLE_EXTRA_NEIGHBORS 77 -#define DW_DLE_WRONG_TAG 78 -#define DW_DLE_DIE_ALLOC 79 -#define DW_DLE_PARENT_EXISTS 80 -#define DW_DLE_DBG_NULL 81 -#define DW_DLE_DEBUGLINE_ERROR 82 -#define DW_DLE_DEBUGFRAME_ERROR 83 -#define DW_DLE_DEBUGINFO_ERROR 84 -#define DW_DLE_ATTR_ALLOC 85 -#define DW_DLE_ABBREV_ALLOC 86 -#define DW_DLE_OFFSET_UFLW 87 -#define DW_DLE_ELF_SECT_ERR 88 -#define DW_DLE_DEBUG_FRAME_LENGTH_BAD 89 -#define DW_DLE_FRAME_VERSION_BAD 90 -#define DW_DLE_CIE_RET_ADDR_REG_ERROR 91 -#define DW_DLE_FDE_NULL 92 -#define DW_DLE_FDE_DBG_NULL 93 -#define DW_DLE_CIE_NULL 94 -#define DW_DLE_CIE_DBG_NULL 95 -#define DW_DLE_FRAME_TABLE_COL_BAD 96 -#define DW_DLE_PC_NOT_IN_FDE_RANGE 97 -#define DW_DLE_CIE_INSTR_EXEC_ERROR 98 -#define DW_DLE_FRAME_INSTR_EXEC_ERROR 99 -#define DW_DLE_FDE_PTR_NULL 100 -#define DW_DLE_RET_OP_LIST_NULL 101 -#define DW_DLE_LINE_CONTEXT_NULL 102 -#define DW_DLE_DBG_NO_CU_CONTEXT 103 -#define DW_DLE_DIE_NO_CU_CONTEXT 104 -#define DW_DLE_FIRST_DIE_NOT_CU 105 -#define DW_DLE_NEXT_DIE_PTR_NULL 106 -#define DW_DLE_DEBUG_FRAME_DUPLICATE 107 -#define DW_DLE_DEBUG_FRAME_NULL 108 -#define DW_DLE_ABBREV_DECODE_ERROR 109 -#define DW_DLE_DWARF_ABBREV_NULL 110 -#define DW_DLE_ATTR_NULL 111 -#define DW_DLE_DIE_BAD 112 -#define DW_DLE_DIE_ABBREV_BAD 113 -#define DW_DLE_ATTR_FORM_BAD 114 -#define DW_DLE_ATTR_NO_CU_CONTEXT 115 -#define DW_DLE_ATTR_FORM_SIZE_BAD 116 -#define DW_DLE_ATTR_DBG_NULL 117 -#define DW_DLE_BAD_REF_FORM 118 -#define DW_DLE_ATTR_FORM_OFFSET_BAD 119 -#define DW_DLE_LINE_OFFSET_BAD 120 -#define DW_DLE_DEBUG_STR_OFFSET_BAD 121 -#define DW_DLE_STRING_PTR_NULL 122 -#define DW_DLE_PUBNAMES_VERSION_ERROR 123 -#define DW_DLE_PUBNAMES_LENGTH_BAD 124 -#define DW_DLE_GLOBAL_NULL 125 -#define DW_DLE_GLOBAL_CONTEXT_NULL 126 -#define DW_DLE_DIR_INDEX_BAD 127 -#define DW_DLE_LOC_EXPR_BAD 128 -#define DW_DLE_DIE_LOC_EXPR_BAD 129 -#define DW_DLE_ADDR_ALLOC 130 -#define DW_DLE_OFFSET_BAD 131 -#define DW_DLE_MAKE_CU_CONTEXT_FAIL 132 -#define DW_DLE_REL_ALLOC 133 -#define DW_DLE_ARANGE_OFFSET_BAD 134 -#define DW_DLE_SEGMENT_SIZE_BAD 135 -#define DW_DLE_ARANGE_LENGTH_BAD 136 -#define DW_DLE_ARANGE_DECODE_ERROR 137 -#define DW_DLE_ARANGES_NULL 138 -#define DW_DLE_ARANGE_NULL 139 -#define DW_DLE_NO_FILE_NAME 140 -#define DW_DLE_NO_COMP_DIR 141 -#define DW_DLE_CU_ADDRESS_SIZE_BAD 142 -#define DW_DLE_INPUT_ATTR_BAD 143 -#define DW_DLE_EXPR_NULL 144 -#define DW_DLE_BAD_EXPR_OPCODE 145 -#define DW_DLE_EXPR_LENGTH_BAD 146 -#define DW_DLE_MULTIPLE_RELOC_IN_EXPR 147 -#define DW_DLE_ELF_GETIDENT_ERROR 148 -#define DW_DLE_NO_AT_MIPS_FDE 149 -#define DW_DLE_NO_CIE_FOR_FDE 150 -#define DW_DLE_DIE_ABBREV_LIST_NULL 151 -#define DW_DLE_DEBUG_FUNCNAMES_DUPLICATE 152 -#define DW_DLE_DEBUG_FUNCNAMES_NULL 153 -#define DW_DLE_DEBUG_FUNCNAMES_VERSION_ERROR 154 -#define DW_DLE_DEBUG_FUNCNAMES_LENGTH_BAD 155 -#define DW_DLE_FUNC_NULL 156 -#define DW_DLE_FUNC_CONTEXT_NULL 157 -#define DW_DLE_DEBUG_TYPENAMES_DUPLICATE 158 -#define DW_DLE_DEBUG_TYPENAMES_NULL 159 -#define DW_DLE_DEBUG_TYPENAMES_VERSION_ERROR 160 -#define DW_DLE_DEBUG_TYPENAMES_LENGTH_BAD 161 -#define DW_DLE_TYPE_NULL 162 -#define DW_DLE_TYPE_CONTEXT_NULL 163 -#define DW_DLE_DEBUG_VARNAMES_DUPLICATE 164 -#define DW_DLE_DEBUG_VARNAMES_NULL 165 -#define DW_DLE_DEBUG_VARNAMES_VERSION_ERROR 166 -#define DW_DLE_DEBUG_VARNAMES_LENGTH_BAD 167 -#define DW_DLE_VAR_NULL 168 -#define DW_DLE_VAR_CONTEXT_NULL 169 -#define DW_DLE_DEBUG_WEAKNAMES_DUPLICATE 170 -#define DW_DLE_DEBUG_WEAKNAMES_NULL 171 -#define DW_DLE_DEBUG_WEAKNAMES_VERSION_ERROR 172 -#define DW_DLE_DEBUG_WEAKNAMES_LENGTH_BAD 173 -#define DW_DLE_WEAK_NULL 174 -#define DW_DLE_WEAK_CONTEXT_NULL 175 -#define DW_DLE_LOCDESC_COUNT_WRONG 176 -#define DW_DLE_MACINFO_STRING_NULL 177 -#define DW_DLE_MACINFO_STRING_EMPTY 178 -#define DW_DLE_MACINFO_INTERNAL_ERROR_SPACE 179 -#define DW_DLE_MACINFO_MALLOC_FAIL 180 -#define DW_DLE_DEBUGMACINFO_ERROR 181 -#define DW_DLE_DEBUG_MACRO_LENGTH_BAD 182 -#define DW_DLE_DEBUG_MACRO_MAX_BAD 183 -#define DW_DLE_DEBUG_MACRO_INTERNAL_ERR 184 -#define DW_DLE_DEBUG_MACRO_MALLOC_SPACE 185 -#define DW_DLE_DEBUG_MACRO_INCONSISTENT 186 -#define DW_DLE_DF_NO_CIE_AUGMENTATION 187 -#define DW_DLE_DF_REG_NUM_TOO_HIGH 188 -#define DW_DLE_DF_MAKE_INSTR_NO_INIT 189 -#define DW_DLE_DF_NEW_LOC_LESS_OLD_LOC 190 -#define DW_DLE_DF_POP_EMPTY_STACK 191 -#define DW_DLE_DF_ALLOC_FAIL 192 -#define DW_DLE_DF_FRAME_DECODING_ERROR 193 -#define DW_DLE_DEBUG_LOC_SECTION_SHORT 194 -#define DW_DLE_FRAME_AUGMENTATION_UNKNOWN 195 -#define DW_DLE_PUBTYPE_CONTEXT 196 /* Unused. */ -#define DW_DLE_DEBUG_PUBTYPES_LENGTH_BAD 197 -#define DW_DLE_DEBUG_PUBTYPES_VERSION_ERROR 198 -#define DW_DLE_DEBUG_PUBTYPES_DUPLICATE 199 -#define DW_DLE_FRAME_CIE_DECODE_ERROR 200 -#define DW_DLE_FRAME_REGISTER_UNREPRESENTABLE 201 -#define DW_DLE_FRAME_REGISTER_COUNT_MISMATCH 202 -#define DW_DLE_LINK_LOOP 203 -#define DW_DLE_STRP_OFFSET_BAD 204 -#define DW_DLE_DEBUG_RANGES_DUPLICATE 205 -#define DW_DLE_DEBUG_RANGES_OFFSET_BAD 206 -#define DW_DLE_DEBUG_RANGES_MISSING_END 207 -#define DW_DLE_DEBUG_RANGES_OUT_OF_MEM 208 -#define DW_DLE_DEBUG_SYMTAB_ERR 209 -#define DW_DLE_DEBUG_STRTAB_ERR 210 -#define DW_DLE_RELOC_MISMATCH_INDEX 211 -#define DW_DLE_RELOC_MISMATCH_RELOC_INDEX 212 -#define DW_DLE_RELOC_MISMATCH_STRTAB_INDEX 213 -#define DW_DLE_RELOC_SECTION_MISMATCH 214 -#define DW_DLE_RELOC_SECTION_MISSING_INDEX 215 -#define DW_DLE_RELOC_SECTION_LENGTH_ODD 216 -#define DW_DLE_RELOC_SECTION_PTR_NULL 217 -#define DW_DLE_RELOC_SECTION_MALLOC_FAIL 218 -#define DW_DLE_NO_ELF64_SUPPORT 219 -#define DW_DLE_MISSING_ELF64_SUPPORT 220 -#define DW_DLE_ORPHAN_FDE 221 -#define DW_DLE_DUPLICATE_INST_BLOCK 222 -#define DW_DLE_BAD_REF_SIG8_FORM 223 -#define DW_DLE_ATTR_EXPRLOC_FORM_BAD 224 -#define DW_DLE_FORM_SEC_OFFSET_LENGTH_BAD 225 -#define DW_DLE_NOT_REF_FORM 226 -#define DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE 227 - - - - /* DW_DLE_LAST MUST EQUAL LAST ERROR NUMBER */ -#define DW_DLE_LAST 227 -#define DW_DLE_LO_USER 0x10000 - - /* Taken as meaning 'undefined value', this is not - a column or register number. - Only present at libdwarf runtime. Never on disk. - DW_FRAME_* Values present on disk are in dwarf.h - */ -#define DW_FRAME_UNDEFINED_VAL 1034 - - /* Taken as meaning 'same value' as caller had, not a column - or register number - Only present at libdwarf runtime. Never on disk. - DW_FRAME_* Values present on disk are in dwarf.h - */ -#define DW_FRAME_SAME_VAL 1035 - - - -/* error return values -*/ -#define DW_DLV_BADADDR (~(Dwarf_Addr)0) - /* for functions returning target address */ - -#define DW_DLV_NOCOUNT ((Dwarf_Signed)-1) - /* for functions returning count */ - -#define DW_DLV_BADOFFSET (~(Dwarf_Off)0) - /* for functions returning offset */ - -/* standard return values for functions */ -#define DW_DLV_NO_ENTRY -1 -#define DW_DLV_OK 0 -#define DW_DLV_ERROR 1 - -/* Special values for offset_into_exception_table field of dwarf fde's. */ -/* The following value indicates that there is no Exception table offset - associated with a dwarf frame. */ -#define DW_DLX_NO_EH_OFFSET (-1LL) -/* The following value indicates that the producer was unable to analyse the - source file to generate Exception tables for this function. */ -#define DW_DLX_EH_OFFSET_UNAVAILABLE (-2LL) - - -/*===========================================================================*/ -/* Dwarf consumer interface initialization and termination operations */ - -/* Initialization based on Unix open fd (using libelf internally). */ -int dwarf_init(int /*fd*/, - Dwarf_Unsigned /*access*/, - Dwarf_Handler /*errhand*/, - Dwarf_Ptr /*errarg*/, - Dwarf_Debug* /*dbg*/, - Dwarf_Error* /*error*/); - -/* Initialization based on libelf/sgi-fastlibelf open pointer. */ -int dwarf_elf_init(dwarf_elf_handle /*elf*/, - Dwarf_Unsigned /*access*/, - Dwarf_Handler /*errhand*/, - Dwarf_Ptr /*errarg*/, - Dwarf_Debug* /*dbg*/, - Dwarf_Error* /*error*/); - -/* Undocumented function for memory allocator. */ -void dwarf_print_memory_stats(Dwarf_Debug /*dbg*/); - -int dwarf_get_elf(Dwarf_Debug /*dbg*/, - dwarf_elf_handle* /*return_elfptr*/, - Dwarf_Error* /*error*/); - -int dwarf_finish(Dwarf_Debug /*dbg*/, Dwarf_Error* /*error*/); - - -int dwarf_object_init(Dwarf_Obj_Access_Interface* /* obj */, - Dwarf_Handler /* errhand */, - Dwarf_Ptr /* errarg */, - Dwarf_Debug* /* dbg */, - Dwarf_Error* /* error */); - -int dwarf_object_finish(Dwarf_Debug /* dbg */, - Dwarf_Error* /* error */); - -/* die traversal operations */ -int dwarf_next_cu_header_b(Dwarf_Debug /*dbg*/, - Dwarf_Unsigned* /*cu_header_length*/, - Dwarf_Half* /*version_stamp*/, - Dwarf_Off* /*abbrev_offset*/, - Dwarf_Half* /*address_size*/, - Dwarf_Half* /*length_size*/, - Dwarf_Half* /*extension_size*/, - Dwarf_Unsigned* /*next_cu_header_offset*/, - Dwarf_Error* /*error*/); -/* The following is now obsolete, though supported. November 2009. */ -int dwarf_next_cu_header(Dwarf_Debug /*dbg*/, - Dwarf_Unsigned* /*cu_header_length*/, - Dwarf_Half* /*version_stamp*/, - Dwarf_Off* /*abbrev_offset*/, - Dwarf_Half* /*address_size*/, - Dwarf_Unsigned* /*next_cu_header_offset*/, - Dwarf_Error* /*error*/); - -int dwarf_siblingof(Dwarf_Debug /*dbg*/, - Dwarf_Die /*die*/, - Dwarf_Die* /*return_siblingdie*/, - Dwarf_Error* /*error*/); - -int dwarf_child(Dwarf_Die /*die*/, - Dwarf_Die* /*return_childdie*/, - Dwarf_Error* /*error*/); - -/* Finding die given global (not CU-relative) offset */ -int dwarf_offdie(Dwarf_Debug /*dbg*/, - Dwarf_Off /*offset*/, - Dwarf_Die* /*return_die*/, - Dwarf_Error* /*error*/); - -/* Higher level functions (Unimplemented) */ -int dwarf_pcfile(Dwarf_Debug /*dbg*/, - Dwarf_Addr /*pc*/, - Dwarf_Die* /*return_die*/, - Dwarf_Error* /*error*/); - -/* Unimplemented */ -int dwarf_pcsubr(Dwarf_Debug /*dbg*/, - Dwarf_Addr /*pc*/, - Dwarf_Die* /*return_die*/, - Dwarf_Error* /*error*/); - -/* Unimplemented */ -int dwarf_pcscope(Dwarf_Debug /*dbg*/, - Dwarf_Addr /*pc*/, - Dwarf_Die* /*return_die*/, - Dwarf_Error* /*error*/); - -/* operations on DIEs */ -int dwarf_tag(Dwarf_Die /*die*/, - Dwarf_Half* /*return_tag*/, - Dwarf_Error* /*error*/); - -/* utility? */ -/* dwarf_dieoffset returns the global debug_info - section offset, not the CU relative offset. */ -int dwarf_dieoffset(Dwarf_Die /*die*/, - Dwarf_Off* /*return_offset*/, - Dwarf_Error* /*error*/); - -/* dwarf_CU_dieoffset_given_die returns - the global debug_info section offset of the CU die - that is the CU containing the given_die - (the passed in DIE can be any DIE). - This information makes it possible for a consumer to - find and print CU context information for any die. - See also dwarf_get_cu_die_offset_given_cu_header_offset(). */ -int dwarf_CU_dieoffset_given_die(Dwarf_Die /*given_die*/, - Dwarf_Off* /*return_offset*/, - Dwarf_Error* /*error*/); - -/* dwarf_die_CU_offset returns the CU relative offset - not the global debug_info section offset, given - any DIE in the CU. See also dwarf_CU_dieoffset_given_die(). - */ -int dwarf_die_CU_offset(Dwarf_Die /*die*/, - Dwarf_Off* /*return_offset*/, - Dwarf_Error* /*error*/); - -int dwarf_die_CU_offset_range(Dwarf_Die /*die*/, - Dwarf_Off* /*return_CU_header_offset*/, - Dwarf_Off* /*return_CU_length_bytes*/, - Dwarf_Error* /*error*/); - -int dwarf_attr (Dwarf_Die /*die*/, - Dwarf_Half /*attr*/, - Dwarf_Attribute * /*returned_attr*/, - Dwarf_Error* /*error*/); - -int dwarf_diename(Dwarf_Die /*die*/, - char ** /*diename*/, - Dwarf_Error* /*error*/); - -/* Returns the abbrev code of the die. Cannot fail. */ -int dwarf_die_abbrev_code(Dwarf_Die /*die */); - - -/* convenience functions, alternative to using dwarf_attrlist() */ -int dwarf_hasattr(Dwarf_Die /*die*/, - Dwarf_Half /*attr*/, - Dwarf_Bool * /*returned_bool*/, - Dwarf_Error* /*error*/); - -/* dwarf_loclist_n preferred over dwarf_loclist */ -int dwarf_loclist_n(Dwarf_Attribute /*attr*/, - Dwarf_Locdesc*** /*llbuf*/, - Dwarf_Signed * /*locCount*/, - Dwarf_Error* /*error*/); - -int dwarf_loclist(Dwarf_Attribute /*attr*/, /* inflexible! */ - Dwarf_Locdesc** /*llbuf*/, - Dwarf_Signed * /*locCount*/, - Dwarf_Error* /*error*/); - -/* Extracts a dwarf expression from an expression byte stream. - Useful to get expressions from DW_CFA_def_cfa_expression - DW_CFA_expression DW_CFA_val_expression expression bytes. - 27 April 2009: dwarf_loclist_from_expr() interface with - no addr_size is obsolete but supported, - use dwarf_loclist_from_expr_a() instead. -*/ -int dwarf_loclist_from_expr(Dwarf_Debug dbg, - Dwarf_Ptr expression_in, - Dwarf_Unsigned expression_length, - Dwarf_Locdesc ** llbuf, - Dwarf_Signed * listlen, Dwarf_Error * error); - -/* dwarf_loclist_from_expr_a() new 27 Apr 2009: added addr_size argument. */ -int dwarf_loclist_from_expr_a(Dwarf_Debug dbg, - Dwarf_Ptr expression_in, - Dwarf_Unsigned expression_length, - Dwarf_Half addr_size, - Dwarf_Locdesc ** llbuf, - Dwarf_Signed * listlen, Dwarf_Error * error); - -/* Unimplemented */ -int dwarf_stringlen(Dwarf_Die /*die*/, - Dwarf_Locdesc ** /*returned_locdesc*/, - Dwarf_Error* /*error*/); - -/* Unimplemented */ -int dwarf_subscrcnt(Dwarf_Die /*die*/, - Dwarf_Signed * /*returned_count*/, - Dwarf_Error* /*error*/); - -/* Unimplemented */ -int dwarf_nthsubscr(Dwarf_Die /*die*/, - Dwarf_Unsigned /*ssndx*/, - Dwarf_Die * /*returned_die*/, - Dwarf_Error* /*error*/); - -int dwarf_lowpc(Dwarf_Die /*die*/, - Dwarf_Addr * /*returned_addr*/, - Dwarf_Error* /*error*/); - -int dwarf_highpc(Dwarf_Die /*die*/, - Dwarf_Addr * /*returned_addr*/, - Dwarf_Error* /*error*/); - -int dwarf_bytesize(Dwarf_Die /*die*/, - Dwarf_Unsigned * /*returned_size*/, - Dwarf_Error* /*error*/); - -/* Unimplemented */ -int dwarf_isbitfield(Dwarf_Die /*die*/, - Dwarf_Bool * /*returned_bool*/, - Dwarf_Error* /*error*/); - -int dwarf_bitsize(Dwarf_Die /*die*/, - Dwarf_Unsigned * /*returned_size*/, - Dwarf_Error* /*error*/); - -int dwarf_bitoffset(Dwarf_Die /*die*/, - Dwarf_Unsigned * /*returned_offset*/, - Dwarf_Error* /*error*/); - -int dwarf_srclang(Dwarf_Die /*die*/, - Dwarf_Unsigned * /*returned_lang*/, - Dwarf_Error* /*error*/); - -int dwarf_arrayorder(Dwarf_Die /*die*/, - Dwarf_Unsigned * /*returned_order*/, - Dwarf_Error* /*error*/); - -/* end of convenience function list */ - -/* this is the main interface to attributes of a DIE */ -int dwarf_attrlist(Dwarf_Die /*die*/, - Dwarf_Attribute** /*attrbuf*/, - Dwarf_Signed * /*attrcount*/, - Dwarf_Error* /*error*/); - -/* query operations for attributes */ -int dwarf_hasform(Dwarf_Attribute /*attr*/, - Dwarf_Half /*form*/, - Dwarf_Bool * /*returned_bool*/, - Dwarf_Error* /*error*/); - -int dwarf_whatform(Dwarf_Attribute /*attr*/, - Dwarf_Half * /*returned_form*/, - Dwarf_Error* /*error*/); - -int dwarf_whatform_direct(Dwarf_Attribute /*attr*/, - Dwarf_Half * /*returned_form*/, - Dwarf_Error* /*error*/); - -int dwarf_whatattr(Dwarf_Attribute /*attr*/, - Dwarf_Half * /*returned_attr_num*/, - Dwarf_Error* /*error*/); - -/* - The following are concerned with the Primary Interface: getting - the actual data values. One function per 'kind' of FORM. -*/ -/* dwarf_formref returns, thru return_offset, a CU-relative offset - and does not allow DW_FORM_ref_addr*/ -int dwarf_formref(Dwarf_Attribute /*attr*/, - Dwarf_Off* /*return_offset*/, - Dwarf_Error* /*error*/); -/* dwarf_global_formref returns, thru return_offset, - a debug_info-relative offset and does allow all reference forms*/ -int dwarf_global_formref(Dwarf_Attribute /*attr*/, - Dwarf_Off* /*return_offset*/, - Dwarf_Error* /*error*/); - -/* dwarf_formsig8 returns in the caller-provided 8 byte area - the 8 bytes of a DW_FORM_ref_sig8. Not a string. */ -int dwarf_formsig8(Dwarf_Attribute /*attr*/, - Dwarf_Sig8 * /*returned sig bytes*/, - Dwarf_Error* /*error*/); - -int dwarf_formaddr(Dwarf_Attribute /*attr*/, - Dwarf_Addr * /*returned_addr*/, - Dwarf_Error* /*error*/); - -int dwarf_formflag(Dwarf_Attribute /*attr*/, - Dwarf_Bool * /*returned_bool*/, - Dwarf_Error* /*error*/); - -int dwarf_formudata(Dwarf_Attribute /*attr*/, - Dwarf_Unsigned * /*returned_val*/, - Dwarf_Error* /*error*/); - -int dwarf_formsdata(Dwarf_Attribute /*attr*/, - Dwarf_Signed * /*returned_val*/, - Dwarf_Error* /*error*/); - -int dwarf_formblock(Dwarf_Attribute /*attr*/, - Dwarf_Block ** /*returned_block*/, - Dwarf_Error* /*error*/); - -int dwarf_formstring(Dwarf_Attribute /*attr*/, - char ** /*returned_string*/, - Dwarf_Error* /*error*/); - -int dwarf_formexprloc(Dwarf_Attribute /*attr*/, - Dwarf_Unsigned * /*return_exprlen*/, - Dwarf_Ptr * /*block_ptr*/, - Dwarf_Error * /*error*/); - - -/* end attribute query operations. */ - -/* line number operations */ -/* dwarf_srclines is the normal interface */ -int dwarf_srclines(Dwarf_Die /*die*/, - Dwarf_Line** /*linebuf*/, - Dwarf_Signed * /*linecount*/, - Dwarf_Error* /*error*/); - -/* dwarf_srclines_dealloc, created July 2005, is the new - method for deallocating what dwarf_srclines returns. - More complete free than using dwarf_dealloc directly. */ -void dwarf_srclines_dealloc(Dwarf_Debug /*dbg*/, - Dwarf_Line* /*linebuf*/, - Dwarf_Signed /*count */); - - -int dwarf_srcfiles(Dwarf_Die /*die*/, - char*** /*srcfiles*/, - Dwarf_Signed * /*filecount*/, - Dwarf_Error* /*error*/); - -/* Unimplemented. */ -int dwarf_dieline(Dwarf_Die /*die*/, - Dwarf_Line * /*returned_line*/, - Dwarf_Error * /*error*/); - -int dwarf_linebeginstatement(Dwarf_Line /*line*/, - Dwarf_Bool * /*returned_bool*/, - Dwarf_Error* /*error*/); - -int dwarf_lineendsequence(Dwarf_Line /*line*/, - Dwarf_Bool * /*returned_bool*/, - Dwarf_Error* /*error*/); - -int dwarf_lineno(Dwarf_Line /*line*/, - Dwarf_Unsigned * /*returned_lineno*/, - Dwarf_Error* /*error*/); - -int dwarf_line_srcfileno(Dwarf_Line /*line*/, - Dwarf_Unsigned * /*ret_fileno*/, - Dwarf_Error * /*error*/); - -int dwarf_lineaddr(Dwarf_Line /*line*/, - Dwarf_Addr * /*returned_addr*/, - Dwarf_Error* /*error*/); - -int dwarf_lineoff(Dwarf_Line /*line*/, - Dwarf_Signed * /*returned_lineoffset*/, - Dwarf_Error* /*error*/); - -int dwarf_linesrc(Dwarf_Line /*line*/, - char ** /*returned_name*/, - Dwarf_Error* /*error*/); - -int dwarf_lineblock(Dwarf_Line /*line*/, - Dwarf_Bool * /*returned_bool*/, - Dwarf_Error* /*error*/); - -/* tertiary interface to line info */ -/* Unimplemented */ -int dwarf_pclines(Dwarf_Debug /*dbg*/, - Dwarf_Addr /*pc*/, - Dwarf_Line** /*linebuf*/, - Dwarf_Signed * /*linecount*/, - Dwarf_Signed /*slide*/, - Dwarf_Error* /*error*/); -/* end line number operations */ - -/* global name space operations (.debug_pubnames access) */ -int dwarf_get_globals(Dwarf_Debug /*dbg*/, - Dwarf_Global** /*globals*/, - Dwarf_Signed * /*number_of_globals*/, - Dwarf_Error* /*error*/); -void dwarf_globals_dealloc(Dwarf_Debug /*dbg*/, - Dwarf_Global* /*globals*/, - Dwarf_Signed /*number_of_globals*/); - -int dwarf_globname(Dwarf_Global /*glob*/, - char ** /*returned_name*/, - Dwarf_Error* /*error*/); - -int dwarf_global_die_offset(Dwarf_Global /*global*/, - Dwarf_Off* /*return_offset*/, - Dwarf_Error * /*error*/); - -/* This returns the CU die global offset if one knows the - CU header global offset. - See also dwarf_CU_dieoffset_given_die(). */ -int dwarf_get_cu_die_offset_given_cu_header_offset( - Dwarf_Debug /*dbg*/, - Dwarf_Off /*in_cu_header_offset*/, - Dwarf_Off * /*out_cu_die_offset*/, - Dwarf_Error * /*err*/); -#ifdef __sgi /* pragma is sgi MIPS only */ -#pragma optional dwarf_get_cu_die_offset_given_cu_header_offset -#endif - -int dwarf_global_cu_offset(Dwarf_Global /*global*/, - Dwarf_Off* /*return_offset*/, - Dwarf_Error* /*error*/); - -int dwarf_global_name_offsets(Dwarf_Global /*global*/, - char ** /*returned_name*/, - Dwarf_Off* /*die_offset*/, - Dwarf_Off* /*cu_offset*/, - Dwarf_Error* /*error*/); - -/* Static function name operations. */ -int dwarf_get_funcs(Dwarf_Debug /*dbg*/, - Dwarf_Func** /*funcs*/, - Dwarf_Signed * /*number_of_funcs*/, - Dwarf_Error* /*error*/); -void dwarf_funcs_dealloc(Dwarf_Debug /*dbg*/, - Dwarf_Func* /*funcs*/, - Dwarf_Signed /*number_of_funcs*/); - -int dwarf_funcname(Dwarf_Func /*func*/, - char ** /*returned_name*/, - Dwarf_Error* /*error*/); - -int dwarf_func_die_offset(Dwarf_Func /*func*/, - Dwarf_Off* /*return_offset*/, - Dwarf_Error* /*error*/); - -int dwarf_func_cu_offset(Dwarf_Func /*func*/, - Dwarf_Off* /*return_offset*/, - Dwarf_Error* /*error*/); - -int dwarf_func_name_offsets(Dwarf_Func /*func*/, - char ** /*returned_name*/, - Dwarf_Off* /*die_offset*/, - Dwarf_Off* /*cu_offset*/, - Dwarf_Error* /*error*/); - -/* User-defined type name operations, SGI IRIX .debug_typenames section. - Same content as DWARF3 .debug_pubtypes, but defined years before - .debug_pubtypes was defined. SGI IRIX only. */ -int dwarf_get_types(Dwarf_Debug /*dbg*/, - Dwarf_Type** /*types*/, - Dwarf_Signed * /*number_of_types*/, - Dwarf_Error* /*error*/); -void dwarf_types_dealloc(Dwarf_Debug /*dbg*/, - Dwarf_Type* /*types*/, - Dwarf_Signed /*number_of_types*/); - - -int dwarf_typename(Dwarf_Type /*type*/, - char ** /*returned_name*/, - Dwarf_Error* /*error*/); - -int dwarf_type_die_offset(Dwarf_Type /*type*/, - Dwarf_Off* /*return_offset*/, - Dwarf_Error* /*error*/); - -int dwarf_type_cu_offset(Dwarf_Type /*type*/, - Dwarf_Off* /*return_offset*/, - Dwarf_Error* /*error*/); - -int dwarf_type_name_offsets(Dwarf_Type /*type*/, - char ** /*returned_name*/, - Dwarf_Off* /*die_offset*/, - Dwarf_Off* /*cu_offset*/, - Dwarf_Error* /*error*/); - -/* User-defined type name operations, DWARF3 .debug_pubtypes section. -*/ -int dwarf_get_pubtypes(Dwarf_Debug /*dbg*/, - Dwarf_Type** /*types*/, - Dwarf_Signed * /*number_of_types*/, - Dwarf_Error* /*error*/); -void dwarf_pubtypes_dealloc(Dwarf_Debug /*dbg*/, - Dwarf_Type* /*pubtypes*/, - Dwarf_Signed /*number_of_pubtypes*/); - - -int dwarf_pubtypename(Dwarf_Type /*type*/, - char ** /*returned_name*/, - Dwarf_Error* /*error*/); - -int dwarf_pubtype_die_offset(Dwarf_Type /*type*/, - Dwarf_Off* /*return_offset*/, - Dwarf_Error* /*error*/); - -int dwarf_pubtype_cu_offset(Dwarf_Type /*type*/, - Dwarf_Off* /*return_offset*/, - Dwarf_Error* /*error*/); - -int dwarf_pubtype_name_offsets(Dwarf_Type /*type*/, - char ** /*returned_name*/, - Dwarf_Off* /*die_offset*/, - Dwarf_Off* /*cu_offset*/, - Dwarf_Error* /*error*/); - -/* File-scope static variable name operations. */ -int dwarf_get_vars(Dwarf_Debug /*dbg*/, - Dwarf_Var** /*vars*/, - Dwarf_Signed * /*number_of_vars*/, - Dwarf_Error* /*error*/); -void dwarf_vars_dealloc(Dwarf_Debug /*dbg*/, - Dwarf_Var* /*vars*/, - Dwarf_Signed /*number_of_vars*/); - - -int dwarf_varname(Dwarf_Var /*var*/, - char ** /*returned_name*/, - Dwarf_Error* /*error*/); - -int dwarf_var_die_offset(Dwarf_Var /*var*/, - Dwarf_Off* /*return_offset*/, - Dwarf_Error* /*error*/); - -int dwarf_var_cu_offset(Dwarf_Var /*var*/, - Dwarf_Off* /*return_offset*/, - Dwarf_Error* /*error*/); - -int dwarf_var_name_offsets(Dwarf_Var /*var*/, - char ** /*returned_name*/, - Dwarf_Off* /*die_offset*/, - Dwarf_Off* /*cu_offset*/, - Dwarf_Error* /*error*/); - -/* weak name operations. */ -int dwarf_get_weaks(Dwarf_Debug /*dbg*/, - Dwarf_Weak** /*weaks*/, - Dwarf_Signed * /*number_of_weaks*/, - Dwarf_Error* /*error*/); -void dwarf_weaks_dealloc(Dwarf_Debug /*dbg*/, - Dwarf_Weak* /*weaks*/, - Dwarf_Signed /*number_of_weaks*/); - - -int dwarf_weakname(Dwarf_Weak /*weak*/, - char ** /*returned_name*/, - Dwarf_Error* /*error*/); - -int dwarf_weak_die_offset(Dwarf_Weak /*weak*/, - Dwarf_Off* /*return_offset*/, - Dwarf_Error* /*error*/); - -int dwarf_weak_cu_offset(Dwarf_Weak /*weak*/, - Dwarf_Off* /*return_offset*/, - Dwarf_Error* /*error*/); - -int dwarf_weak_name_offsets(Dwarf_Weak /*weak*/, - char ** /*returned_name*/, - Dwarf_Off* /*die_offset*/, - Dwarf_Off* /*cu_offset*/, - Dwarf_Error* /*error*/); - -/* location list section operation. (.debug_loc access) */ -int dwarf_get_loclist_entry(Dwarf_Debug /*dbg*/, - Dwarf_Unsigned /*offset*/, - Dwarf_Addr* /*hipc*/, - Dwarf_Addr* /*lopc*/, - Dwarf_Ptr* /*data*/, - Dwarf_Unsigned* /*entry_len*/, - Dwarf_Unsigned* /*next_entry*/, - Dwarf_Error* /*error*/); - -/* abbreviation section operations */ -int dwarf_get_abbrev(Dwarf_Debug /*dbg*/, - Dwarf_Unsigned /*offset*/, - Dwarf_Abbrev * /*returned_abbrev*/, - Dwarf_Unsigned* /*length*/, - Dwarf_Unsigned* /*attr_count*/, - Dwarf_Error* /*error*/); - -int dwarf_get_abbrev_tag(Dwarf_Abbrev /*abbrev*/, - Dwarf_Half* /*return_tag_number*/, - Dwarf_Error* /*error*/); -int dwarf_get_abbrev_code(Dwarf_Abbrev /*abbrev*/, - Dwarf_Unsigned* /*return_code_number*/, - Dwarf_Error* /*error*/); - -int dwarf_get_abbrev_children_flag(Dwarf_Abbrev /*abbrev*/, - Dwarf_Signed* /*return_flag*/, - Dwarf_Error* /*error*/); - -int dwarf_get_abbrev_entry(Dwarf_Abbrev /*abbrev*/, - Dwarf_Signed /*index*/, - Dwarf_Half * /*returned_attr_num*/, - Dwarf_Signed* /*form*/, - Dwarf_Off* /*offset*/, - Dwarf_Error* /*error*/); - -/* consumer string section operation */ -int dwarf_get_str(Dwarf_Debug /*dbg*/, - Dwarf_Off /*offset*/, - char** /*string*/, - Dwarf_Signed * /*strlen_of_string*/, - Dwarf_Error* /*error*/); - -/* Consumer op on gnu .eh_frame info */ -int dwarf_get_fde_list_eh( - Dwarf_Debug /*dbg*/, - Dwarf_Cie** /*cie_data*/, - Dwarf_Signed* /*cie_element_count*/, - Dwarf_Fde** /*fde_data*/, - Dwarf_Signed* /*fde_element_count*/, - Dwarf_Error* /*error*/); - - -/* consumer operations on frame info: .debug_frame */ -int dwarf_get_fde_list(Dwarf_Debug /*dbg*/, - Dwarf_Cie** /*cie_data*/, - Dwarf_Signed* /*cie_element_count*/, - Dwarf_Fde** /*fde_data*/, - Dwarf_Signed* /*fde_element_count*/, - Dwarf_Error* /*error*/); - -/* Release storage gotten by dwarf_get_fde_list_eh() or - dwarf_get_fde_list() */ -void dwarf_fde_cie_list_dealloc(Dwarf_Debug dbg, - Dwarf_Cie *cie_data, - Dwarf_Signed cie_element_count, - Dwarf_Fde *fde_data, - Dwarf_Signed fde_element_count); - - - -int dwarf_get_fde_range(Dwarf_Fde /*fde*/, - Dwarf_Addr* /*low_pc*/, - Dwarf_Unsigned* /*func_length*/, - Dwarf_Ptr* /*fde_bytes*/, - Dwarf_Unsigned* /*fde_byte_length*/, - Dwarf_Off* /*cie_offset*/, - Dwarf_Signed* /*cie_index*/, - Dwarf_Off* /*fde_offset*/, - Dwarf_Error* /*error*/); - -/* Useful for IRIX only: see dwarf_get_cie_augmentation_data() - dwarf_get_fde_augmentation_data() for GNU .eh_frame. */ -int dwarf_get_fde_exception_info(Dwarf_Fde /*fde*/, - Dwarf_Signed* /* offset_into_exception_tables */, - Dwarf_Error* /*error*/); - - -int dwarf_get_cie_of_fde(Dwarf_Fde /*fde*/, - Dwarf_Cie * /*cie_returned*/, - Dwarf_Error* /*error*/); - -int dwarf_get_cie_info(Dwarf_Cie /*cie*/, - Dwarf_Unsigned * /*bytes_in_cie*/, - Dwarf_Small* /*version*/, - char ** /*augmenter*/, - Dwarf_Unsigned* /*code_alignment_factor*/, - Dwarf_Signed* /*data_alignment_factor*/, - Dwarf_Half* /*return_address_register_rule*/, - Dwarf_Ptr* /*initial_instructions*/, - Dwarf_Unsigned* /*initial_instructions_length*/, - Dwarf_Error* /*error*/); - -/* dwarf_get_cie_index new September 2009. */ -int dwarf_get_cie_index( - Dwarf_Cie /*cie*/, - Dwarf_Signed* /*index*/, - Dwarf_Error* /*error*/ ); - - -int dwarf_get_fde_instr_bytes(Dwarf_Fde /*fde*/, - Dwarf_Ptr * /*outinstrs*/, Dwarf_Unsigned * /*outlen*/, - Dwarf_Error * /*error*/); - -int dwarf_get_fde_info_for_all_regs(Dwarf_Fde /*fde*/, - Dwarf_Addr /*pc_requested*/, - Dwarf_Regtable* /*reg_table*/, - Dwarf_Addr* /*row_pc*/, - Dwarf_Error* /*error*/); - -int dwarf_get_fde_info_for_all_regs3(Dwarf_Fde /*fde*/, - Dwarf_Addr /*pc_requested*/, - Dwarf_Regtable3* /*reg_table*/, - Dwarf_Addr* /*row_pc*/, - Dwarf_Error* /*error*/); - -/* In this older interface DW_FRAME_CFA_COL is a meaningful - column (which does not work well with DWARF3 or - non-MIPS architectures). */ -int dwarf_get_fde_info_for_reg(Dwarf_Fde /*fde*/, - Dwarf_Half /*table_column*/, - Dwarf_Addr /*pc_requested*/, - Dwarf_Signed* /*offset_relevant*/, - Dwarf_Signed* /*register*/, - Dwarf_Signed* /*offset*/, - Dwarf_Addr* /*row_pc*/, - Dwarf_Error* /*error*/); - -/* See discussion of dw_value_type, libdwarf.h. - Use of DW_FRAME_CFA_COL is not meaningful in this interface. - See dwarf_get_fde_info_for_cfa_reg3(). -*/ -/* dwarf_get_fde_info_for_reg3 is useful on a single column, but - it is inefficient to iterate across all table_columns using this - function. Instead call dwarf_get_fde_info_for_all_regs3() and index - into the table it fills in. */ -int dwarf_get_fde_info_for_reg3(Dwarf_Fde /*fde*/, - Dwarf_Half /*table_column*/, - Dwarf_Addr /*pc_requested*/, - Dwarf_Small * /*value_type*/, - Dwarf_Signed * /*offset_relevant*/, - Dwarf_Signed* /*register*/, - Dwarf_Signed* /*offset_or_block_len*/, - Dwarf_Ptr * /*block_ptr */, - Dwarf_Addr* /*row_pc_out*/, - Dwarf_Error* /*error*/); - -/* Use this to get the cfa. */ -int dwarf_get_fde_info_for_cfa_reg3(Dwarf_Fde /*fde*/, - Dwarf_Addr /*pc_requested*/, - Dwarf_Small * /*value_type*/, - Dwarf_Signed * /*offset_relevant*/, - Dwarf_Signed* /*register*/, - Dwarf_Signed* /*offset_or_block_len*/, - Dwarf_Ptr * /*block_ptr */, - Dwarf_Addr* /*row_pc_out*/, - Dwarf_Error* /*error*/); - -int dwarf_get_fde_for_die(Dwarf_Debug /*dbg*/, - Dwarf_Die /*subr_die */, - Dwarf_Fde * /*returned_fde*/, - Dwarf_Error* /*error*/); - -int dwarf_get_fde_n(Dwarf_Fde* /*fde_data*/, - Dwarf_Unsigned /*fde_index*/, - Dwarf_Fde * /*returned_fde*/, - Dwarf_Error* /*error*/); - -int dwarf_get_fde_at_pc(Dwarf_Fde* /*fde_data*/, - Dwarf_Addr /*pc_of_interest*/, - Dwarf_Fde * /*returned_fde*/, - Dwarf_Addr* /*lopc*/, - Dwarf_Addr* /*hipc*/, - Dwarf_Error* /*error*/); - -/* GNU .eh_frame augmentation information, raw form, see - Linux Standard Base Core Specification version 3.0 . */ -int dwarf_get_cie_augmentation_data(Dwarf_Cie /* cie*/, - Dwarf_Small ** /* augdata */, - Dwarf_Unsigned * /* augdata_len */, - Dwarf_Error* /*error*/); -/* GNU .eh_frame augmentation information, raw form, see - Linux Standard Base Core Specification version 3.0 . */ -int dwarf_get_fde_augmentation_data(Dwarf_Fde /* fde*/, - Dwarf_Small ** /* augdata */, - Dwarf_Unsigned * /* augdata_len */, - Dwarf_Error* /*error*/); - -int dwarf_expand_frame_instructions(Dwarf_Cie /*cie*/, - Dwarf_Ptr /*instruction*/, - Dwarf_Unsigned /*i_length*/, - Dwarf_Frame_Op** /*returned_op_list*/, - Dwarf_Signed* /*op_count*/, - Dwarf_Error* /*error*/); - -/* Operations on .debug_aranges. */ -int dwarf_get_aranges(Dwarf_Debug /*dbg*/, - Dwarf_Arange** /*aranges*/, - Dwarf_Signed * /*arange_count*/, - Dwarf_Error* /*error*/); - - - -int dwarf_get_arange( - Dwarf_Arange* /*aranges*/, - Dwarf_Unsigned /*arange_count*/, - Dwarf_Addr /*address*/, - Dwarf_Arange * /*returned_arange*/, - Dwarf_Error* /*error*/); - -int dwarf_get_cu_die_offset( - Dwarf_Arange /*arange*/, - Dwarf_Off* /*return_offset*/, - Dwarf_Error* /*error*/); - -int dwarf_get_arange_cu_header_offset( - Dwarf_Arange /*arange*/, - Dwarf_Off* /*return_cu_header_offset*/, - Dwarf_Error* /*error*/); -#ifdef __sgi /* pragma is sgi MIPS only */ -#pragma optional dwarf_get_arange_cu_header_offset -#endif - -/* DWARF2,3 interface. No longer really adequate (it was never - right for segmented address spaces, please switch - to using dwarf_get_arange_info_b instead. - There is no effective difference between these - functions if the address space - of the target is not segmented. */ -int dwarf_get_arange_info( - Dwarf_Arange /*arange*/, - Dwarf_Addr* /*start*/, - Dwarf_Unsigned* /*length*/, - Dwarf_Off* /*cu_die_offset*/, - Dwarf_Error* /*error*/ ); - -/* New for DWARF4, entries may have segment information. - *segment is only meaningful if *segment_entry_size is non-zero. */ -int dwarf_get_arange_info_b( - Dwarf_Arange /*arange*/, - Dwarf_Unsigned* /*segment*/, - Dwarf_Unsigned* /*segment_entry_size*/, - Dwarf_Addr * /*start*/, - Dwarf_Unsigned* /*length*/, - Dwarf_Off * /*cu_die_offset*/, - Dwarf_Error * /*error*/ ); - - -/* consumer .debug_macinfo information interface. -*/ -struct Dwarf_Macro_Details_s { - Dwarf_Off dmd_offset; /* offset, in the section, - of this macro info */ - Dwarf_Small dmd_type; /* the type, DW_MACINFO_define etc*/ - Dwarf_Signed dmd_lineno; /* the source line number where - applicable and vend_def # if - vendor_extension op - */ - - Dwarf_Signed dmd_fileindex;/* the source file index: - applies to define undef start_file - */ - char * dmd_macro; /* macro name (with value for defineop) - string from vendor ext - */ -}; - -/* dwarf_print_lines is for use by dwarfdump: it prints - line info to stdout. - The _dwarf name is obsolete. Use dwarf_ instead. - Added extra argnument 2/2009 for better checking. -*/ -int _dwarf_print_lines(Dwarf_Die /*cu_die*/,Dwarf_Error * /*error*/); -int dwarf_print_lines(Dwarf_Die /*cu_die*/,Dwarf_Error * /*error*/, - int * /*error_count_out */); - -/* dwarf_check_lineheader lets dwarfdump get detailed messages - about some compiler errors we detect. - We return the count of detected errors throught the - pointer. -*/ -void dwarf_check_lineheader(Dwarf_Die /*cu_die*/,int *errcount_out); - -/* dwarf_ld_sort_lines helps SGI IRIX ld - rearrange lines in .debug_line in a .o created with a text - section per function. - -OPT:procedure_reorder=ON - where ld-cord (cord(1)ing by ld, - not by cord(1)) may have changed the function order. - The _dwarf name is obsolete. Use dwarf_ instead. -*/ -int _dwarf_ld_sort_lines( - void * /*orig_buffer*/, - unsigned long /* buffer_len*/, - int /*is_64_bit*/, - int * /*any_change*/, - int * /*err_code*/); -int dwarf_ld_sort_lines( - void * /*orig_buffer*/, - unsigned long /*buffer_len*/, - int /*is_64_bit*/, - int * /*any_change*/, - int * /*err_code*/); - -/* Used by dwarfdump -v to print fde offsets from debugging - info. - The _dwarf name is obsolete. Use dwarf_ instead. -*/ -int _dwarf_fde_section_offset(Dwarf_Debug dbg, - Dwarf_Fde /*in_fde*/, - Dwarf_Off * /*fde_off*/, - Dwarf_Off * /*cie_off*/, - Dwarf_Error * /*err*/); -int dwarf_fde_section_offset(Dwarf_Debug dbg, - Dwarf_Fde /*in_fde*/, - Dwarf_Off * /*fde_off*/, - Dwarf_Off * /*cie_off*/, - Dwarf_Error * /*err*/); - -/* Used by dwarfdump -v to print cie offsets from debugging - info. - The _dwarf name is obsolete. Use dwarf_ instead. -*/ -int dwarf_cie_section_offset(Dwarf_Debug /*dbg*/, - Dwarf_Cie /*in_cie*/, - Dwarf_Off * /*cie_off */, - Dwarf_Error * /*err*/); -int _dwarf_cie_section_offset(Dwarf_Debug /*dbg*/, - Dwarf_Cie /*in_cie*/, - Dwarf_Off * /*cie_off*/, - Dwarf_Error * /*err*/); - -typedef struct Dwarf_Macro_Details_s Dwarf_Macro_Details; - -int dwarf_get_macro(Dwarf_Debug /*dbg*/, - char * /*requested_macro_name*/, - Dwarf_Addr /*pc_of_request*/, - char ** /*returned_macro_value*/, - Dwarf_Error * /*error*/); - -int dwarf_get_all_defined_macros(Dwarf_Debug /*dbg*/, - Dwarf_Addr /*pc_of_request*/, - Dwarf_Signed * /*returned_count*/, - char *** /*returned_pointers_to_macros*/, - Dwarf_Error * /*error*/); - -char *dwarf_find_macro_value_start(char * /*macro_string*/); - -int dwarf_get_macro_details(Dwarf_Debug /*dbg*/, - Dwarf_Off /*macro_offset*/, - Dwarf_Unsigned /*maximum_count*/, - Dwarf_Signed * /*entry_count*/, - Dwarf_Macro_Details ** /*details*/, - Dwarf_Error * /*err*/); - - -int dwarf_get_address_size(Dwarf_Debug /*dbg*/, - Dwarf_Half * /*addr_size*/, - Dwarf_Error * /*error*/); -int dwarf_get_die_address_size(Dwarf_Die /*die*/, - Dwarf_Half * /*addr_size*/, - Dwarf_Error * /*error*/); - -/* The dwarf specification separates FORMs into -different classes. To do the seperation properly -requires 4 pieces of data as of DWARF4 (thus the -function arguments listed here). -The DWARF4 specification class definition suffices to -describe all DWARF versions. -See section 7.5.4, Attribute Encodings. -A return of DW_FORM_CLASS_UNKNOWN means we could not properly figure -out what form-class it is. - - DW_FORM_CLASS_FRAMEPTR is MIPS/IRIX only, and refers - to the DW_AT_MIPS_fde attribute (a reference to the - .debug_frame section). -*/ -enum Dwarf_Form_Class { - DW_FORM_CLASS_UNKNOWN, DW_FORM_CLASS_ADDRESS, - DW_FORM_CLASS_BLOCK, DW_FORM_CLASS_CONSTANT, - DW_FORM_CLASS_EXPRLOC, DW_FORM_CLASS_FLAG, - DW_FORM_CLASS_LINEPTR, DW_FORM_CLASS_LOCLISTPTR, - DW_FORM_CLASS_MACPTR, DW_FORM_CLASS_RANGELISTPTR, - DW_FORM_CLASS_REFERENCE, DW_FORM_CLASS_STRING, - DW_FORM_CLASS_FRAMEPTR -}; - -enum Dwarf_Form_Class dwarf_get_form_class( - Dwarf_Half /* dwversion */, - Dwarf_Half /* attrnum */, - Dwarf_Half /*offset_size */, - Dwarf_Half /*form*/); - -/* utility operations */ -Dwarf_Unsigned dwarf_errno(Dwarf_Error /*error*/); - -char* dwarf_errmsg(Dwarf_Error /*error*/); - -/* stringcheck zero is default and means do all -** string length validity checks. -** Call with parameter value 1 to turn off many such checks (and -** increase performance). -** Call with zero for safest running. -** Actual value saved and returned is only 8 bits! Upper bits -** ignored by libdwarf (and zero on return). -** Returns previous value. -*/ -int dwarf_set_stringcheck(int /*stringcheck*/); - -/* 'apply' defaults to 1 and means do all - * 'rela' relocations on reading in a dwarf object section with - * such relocations. - * Call with parameter value 0 to turn off application of - * such relocations. - * Since the static linker leaves 'bogus' data in object sections - * with a 'rela' relocation section such data cannot be read - * sensibly without processing the relocations. Such relocations - * do not exist in executables and shared objects (.so), the - * relocations only exist in plain .o relocatable object files. - * Actual value saved and returned is only 8 bits! Upper bits - * ignored by libdwarf (and zero on return). - * Returns previous value. - * */ -int dwarf_set_reloc_application(int /*apply*/); - - -/* Unimplemented */ -Dwarf_Handler dwarf_seterrhand(Dwarf_Debug /*dbg*/, Dwarf_Handler /*errhand*/); - -/* Unimplemented */ -Dwarf_Ptr dwarf_seterrarg(Dwarf_Debug /*dbg*/, Dwarf_Ptr /*errarg*/); - -void dwarf_dealloc(Dwarf_Debug /*dbg*/, void* /*space*/, - Dwarf_Unsigned /*type*/); - -/* DWARF Producer Interface */ - -typedef int (*Dwarf_Callback_Func)( - char* /*name*/, - int /*size*/, - Dwarf_Unsigned /*type*/, - Dwarf_Unsigned /*flags*/, - Dwarf_Unsigned /*link*/, - Dwarf_Unsigned /*info*/, - int* /*sect name index*/, - int* /*error*/); - -Dwarf_P_Debug dwarf_producer_init( - Dwarf_Unsigned /*creation_flags*/, - Dwarf_Callback_Func /*func*/, - Dwarf_Handler /*errhand*/, - Dwarf_Ptr /*errarg*/, - Dwarf_Error* /*error*/); - -typedef int (*Dwarf_Callback_Func_b)( - char* /*name*/, - int /*size*/, - Dwarf_Unsigned /*type*/, - Dwarf_Unsigned /*flags*/, - Dwarf_Unsigned /*link*/, - Dwarf_Unsigned /*info*/, - Dwarf_Unsigned* /*sect_name_index*/, - int* /*error*/); - - -Dwarf_P_Debug dwarf_producer_init_b( - Dwarf_Unsigned /*flags*/, - Dwarf_Callback_Func_b /*func*/, - Dwarf_Handler /*errhand*/, - Dwarf_Ptr /*errarg*/, - Dwarf_Error * /*error*/); - - -Dwarf_Signed dwarf_transform_to_disk_form(Dwarf_P_Debug /*dbg*/, - Dwarf_Error* /*error*/); - -Dwarf_Ptr dwarf_get_section_bytes(Dwarf_P_Debug /*dbg*/, - Dwarf_Signed /*dwarf_section*/, - Dwarf_Signed* /*elf_section_index*/, - Dwarf_Unsigned* /*length*/, - Dwarf_Error* /*error*/); - -int dwarf_get_relocation_info_count( - Dwarf_P_Debug /*dbg*/, - Dwarf_Unsigned * /*count_of_relocation_sections*/, - int * /*drd_buffer_version*/, - Dwarf_Error* /*error*/); - -int dwarf_get_relocation_info( - Dwarf_P_Debug /*dbg*/, - Dwarf_Signed * /*elf_section_index*/, - Dwarf_Signed * /*elf_section_index_link*/, - Dwarf_Unsigned * /*relocation_buffer_count*/, - Dwarf_Relocation_Data * /*reldata_buffer*/, - Dwarf_Error* /*error*/); - -/* v1: no drd_length field, enum explicit */ -/* v2: has the drd_length field, enum value in uchar member */ -#define DWARF_DRD_BUFFER_VERSION 2 - -/* Markers are not written to DWARF2/3/4, they are user - defined and may be used for any purpose. -*/ -Dwarf_Signed dwarf_get_die_markers( - Dwarf_P_Debug /*dbg*/, - Dwarf_P_Marker * /*marker_list*/, - Dwarf_Unsigned * /*marker_count*/, - Dwarf_Error * /*error*/); - -int dwarf_get_string_attributes_count(Dwarf_P_Debug, - Dwarf_Unsigned *, - int *, - Dwarf_Error *); - -int dwarf_get_string_attributes_info(Dwarf_P_Debug, - Dwarf_Signed *, - Dwarf_Unsigned *, - Dwarf_P_String_Attr *, - Dwarf_Error *); - -void dwarf_reset_section_bytes(Dwarf_P_Debug /*dbg*/); - -Dwarf_Unsigned dwarf_producer_finish(Dwarf_P_Debug /*dbg*/, - Dwarf_Error* /*error*/); - -/* Producer attribute addition functions. */ -Dwarf_P_Attribute dwarf_add_AT_targ_address(Dwarf_P_Debug /*dbg*/, - Dwarf_P_Die /*ownerdie*/, - Dwarf_Half /*attr*/, - Dwarf_Unsigned /*pc_value*/, - Dwarf_Signed /*sym_index*/, - Dwarf_Error* /*error*/); - -Dwarf_P_Attribute dwarf_add_AT_block(Dwarf_P_Debug /*dbg*/, - Dwarf_P_Die /*ownerdie*/, - Dwarf_Half /*attr*/, - Dwarf_Small* /*block_data*/, - Dwarf_Unsigned /*block_len*/, - Dwarf_Error* /*error*/); - -Dwarf_P_Attribute dwarf_add_AT_targ_address_b(Dwarf_P_Debug /*dbg*/, - Dwarf_P_Die /*ownerdie*/, - Dwarf_Half /*attr*/, - Dwarf_Unsigned /*pc_value*/, - Dwarf_Unsigned /*sym_index*/, - Dwarf_Error* /*error*/); - -Dwarf_P_Attribute dwarf_add_AT_ref_address(Dwarf_P_Debug /*dbg*/, - Dwarf_P_Die /*ownerdie*/, - Dwarf_Half /*attr*/, - Dwarf_Unsigned /*pc_value*/, - Dwarf_Unsigned /*sym_index*/, - Dwarf_Error* /*error*/); - -Dwarf_P_Attribute dwarf_add_AT_unsigned_const(Dwarf_P_Debug /*dbg*/, - Dwarf_P_Die /*ownerdie*/, - Dwarf_Half /*attr*/, - Dwarf_Unsigned /*value*/, - Dwarf_Error* /*error*/); - -Dwarf_P_Attribute dwarf_add_AT_signed_const(Dwarf_P_Debug /*dbg*/, - Dwarf_P_Die /*ownerdie*/, - Dwarf_Half /*attr*/, - Dwarf_Signed /*value*/, - Dwarf_Error* /*error*/); - -Dwarf_P_Attribute dwarf_add_AT_reference(Dwarf_P_Debug /*dbg*/, - Dwarf_P_Die /*ownerdie*/, - Dwarf_Half /*attr*/, - Dwarf_P_Die /*otherdie*/, - Dwarf_Error* /*error*/); - -Dwarf_P_Attribute dwarf_add_AT_dataref( - Dwarf_P_Debug /* dbg*/, - Dwarf_P_Die /*ownerdie*/, - Dwarf_Half /*attr*/, - Dwarf_Unsigned /*pcvalue*/, - Dwarf_Unsigned /*sym_index*/, - Dwarf_Error* /*error*/); - -Dwarf_P_Attribute dwarf_add_AT_const_value_string(Dwarf_P_Die /*ownerdie*/, - char* /*string_value*/, - Dwarf_Error* /*error*/); - -Dwarf_P_Attribute dwarf_add_AT_location_expr(Dwarf_P_Debug /*dbg*/, - Dwarf_P_Die /*ownerdie*/, - Dwarf_Half /*attr*/, - Dwarf_P_Expr /*loc_expr*/, - Dwarf_Error* /*error*/); - -Dwarf_P_Attribute dwarf_add_AT_string(Dwarf_P_Debug /*dbg*/, - Dwarf_P_Die /*ownerdie*/, - Dwarf_Half /*attr*/, - char* /*string*/, - Dwarf_Error* /*error*/); - -Dwarf_P_Attribute dwarf_add_AT_flag(Dwarf_P_Debug /*dbg*/, - Dwarf_P_Die /*ownerdie*/, - Dwarf_Half /*attr*/, - Dwarf_Small /*flag*/, - Dwarf_Error* /*error*/); - -Dwarf_P_Attribute dwarf_add_AT_producer(Dwarf_P_Die /*ownerdie*/, - char* /*producer_string*/, - Dwarf_Error* /*error*/); - -Dwarf_P_Attribute dwarf_add_AT_const_value_signedint(Dwarf_P_Die /*ownerdie*/, - Dwarf_Signed /*signed_value*/, - Dwarf_Error* /*error*/); - -Dwarf_P_Attribute dwarf_add_AT_const_value_unsignedint( - Dwarf_P_Die /*ownerdie*/, - Dwarf_Unsigned /*unsigned_value*/, - Dwarf_Error* /*error*/); - -Dwarf_P_Attribute dwarf_add_AT_comp_dir(Dwarf_P_Die /*ownerdie*/, - char* /*current_working_directory*/, - Dwarf_Error* /*error*/); - -Dwarf_P_Attribute dwarf_add_AT_name(Dwarf_P_Die /*die*/, - char* /*name*/, - Dwarf_Error* /*error*/); - -/* Producer line creation functions (.debug_line) */ -Dwarf_Unsigned dwarf_add_directory_decl(Dwarf_P_Debug /*dbg*/, - char* /*name*/, - Dwarf_Error* /*error*/); - -Dwarf_Unsigned dwarf_add_file_decl(Dwarf_P_Debug /*dbg*/, - char* /*name*/, - Dwarf_Unsigned /*dir_index*/, - Dwarf_Unsigned /*time_last_modified*/, - Dwarf_Unsigned /*length*/, - Dwarf_Error* /*error*/); - -Dwarf_Unsigned dwarf_add_line_entry(Dwarf_P_Debug /*dbg*/, - Dwarf_Unsigned /*file_index*/, - Dwarf_Addr /*code_address*/, - Dwarf_Unsigned /*lineno*/, - Dwarf_Signed /*column_number*/, - Dwarf_Bool /*is_source_stmt_begin*/, - Dwarf_Bool /*is_basic_block_begin*/, - Dwarf_Error* /*error*/); - -Dwarf_Unsigned dwarf_lne_set_address(Dwarf_P_Debug /*dbg*/, - Dwarf_Unsigned /*offset*/, - Dwarf_Unsigned /*symbol_index*/, - Dwarf_Error* /*error*/); - -Dwarf_Unsigned dwarf_lne_end_sequence(Dwarf_P_Debug /*dbg*/, - Dwarf_Addr /*end_address*/, - Dwarf_Error* /*error*/); - -/* Producer .debug_frame functions */ -Dwarf_Unsigned dwarf_add_frame_cie(Dwarf_P_Debug /*dbg*/, - char* /*augmenter*/, - Dwarf_Small /*code_alignent_factor*/, - Dwarf_Small /*data_alignment_factor*/, - Dwarf_Small /*return_address_reg*/, - Dwarf_Ptr /*initialization_bytes*/, - Dwarf_Unsigned /*init_byte_len*/, - Dwarf_Error* /*error*/); - -Dwarf_Unsigned dwarf_add_frame_fde( - Dwarf_P_Debug /*dbg*/, - Dwarf_P_Fde /*fde*/, - Dwarf_P_Die /*corresponding subprogram die*/, - Dwarf_Unsigned /*cie_to_use*/, - Dwarf_Unsigned /*virt_addr_of_described_code*/, - Dwarf_Unsigned /*length_of_code*/, - Dwarf_Unsigned /*symbol_index*/, - Dwarf_Error* /*error*/); - -Dwarf_Unsigned dwarf_add_frame_fde_b( - Dwarf_P_Debug /*dbg*/, - Dwarf_P_Fde /*fde*/, - Dwarf_P_Die /*die*/, - Dwarf_Unsigned /*cie*/, - Dwarf_Addr /*virt_addr*/, - Dwarf_Unsigned /*code_len*/, - Dwarf_Unsigned /*sym_idx*/, - Dwarf_Unsigned /*sym_idx_of_end*/, - Dwarf_Addr /*offset_from_end_sym*/, - Dwarf_Error* /*error*/); - -Dwarf_Unsigned dwarf_add_frame_info_b( - Dwarf_P_Debug dbg /*dbg*/, - Dwarf_P_Fde /*fde*/, - Dwarf_P_Die /*die*/, - Dwarf_Unsigned /*cie*/, - Dwarf_Addr /*virt_addr*/, - Dwarf_Unsigned /*code_len*/, - Dwarf_Unsigned /*symidx*/, - Dwarf_Unsigned /*end_symbol */, - Dwarf_Addr /*offset_from_end_symbol */, - Dwarf_Signed /*offset_into_exception_tables*/, - Dwarf_Unsigned /*exception_table_symbol*/, - Dwarf_Error* /*error*/); - -Dwarf_Unsigned dwarf_add_frame_info( - Dwarf_P_Debug dbg /*dbg*/, - Dwarf_P_Fde /*fde*/, - Dwarf_P_Die /*die*/, - Dwarf_Unsigned /*cie*/, - Dwarf_Addr /*virt_addr*/, - Dwarf_Unsigned /*code_len*/, - Dwarf_Unsigned /*symidx*/, - Dwarf_Signed /*offset_into_exception_tables*/, - Dwarf_Unsigned /*exception_table_symbol*/, - Dwarf_Error* /*error*/); - -Dwarf_P_Fde dwarf_add_fde_inst( - Dwarf_P_Fde /*fde*/, - Dwarf_Small /*op*/, - Dwarf_Unsigned /*val1*/, - Dwarf_Unsigned /*val2*/, - Dwarf_Error* /*error*/); - -/* New September 17, 2009 */ -int dwarf_insert_fde_inst_bytes( - Dwarf_P_Debug /*dbg*/, - Dwarf_P_Fde /*fde*/, - Dwarf_Unsigned /*len*/, - Dwarf_Ptr /*ibytes*/, - Dwarf_Error* /*error*/); - - -Dwarf_P_Fde dwarf_new_fde(Dwarf_P_Debug /*dbg*/, Dwarf_Error* /*error*/); - -Dwarf_P_Fde dwarf_fde_cfa_offset( - Dwarf_P_Fde /*fde*/, - Dwarf_Unsigned /*register_number*/, - Dwarf_Signed /*offset*/, - Dwarf_Error* /*error*/); - -/* die creation & addition routines */ -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*/); - -Dwarf_Unsigned dwarf_add_die_to_debug( - Dwarf_P_Debug /*dbg*/, - Dwarf_P_Die /*die*/, - Dwarf_Error* /*error*/); - -/* Markers are not written to DWARF2/3/4, they are user - defined and may be used for any purpose. -*/ -Dwarf_Unsigned dwarf_add_die_marker( - Dwarf_P_Debug /*dbg*/, - Dwarf_P_Die /*die*/, - Dwarf_Unsigned /*marker*/, - Dwarf_Error * /*error*/); - -Dwarf_Unsigned dwarf_get_die_marker( - Dwarf_P_Debug /*dbg*/, - Dwarf_P_Die /*die*/, - Dwarf_Unsigned * /*marker*/, - Dwarf_Error * /*error*/); - -Dwarf_P_Die dwarf_die_link( - Dwarf_P_Die /*die*/, - Dwarf_P_Die /*parent*/, - Dwarf_P_Die /*child*/, - Dwarf_P_Die /*left*/, - Dwarf_P_Die /*right*/, - Dwarf_Error* /*error*/); - -void dwarf_dealloc_compressed_block( - Dwarf_P_Debug, - void * -); - -/* Call this passing in return value from dwarf_uncompress_integer_block() - * to free the space the decompression allocated. */ -void dwarf_dealloc_uncompressed_block( - Dwarf_Debug, - void * -); - -void * dwarf_compress_integer_block( - Dwarf_P_Debug, /* dbg */ - Dwarf_Bool, /* signed==true (or unsigned) */ - Dwarf_Small, /* size of integer units: 8, 16, 32, 64 */ - void*, /* data */ - Dwarf_Unsigned, /* number of elements */ - Dwarf_Unsigned*, /* number of bytes in output block */ - Dwarf_Error* /* error */ -); - -/* Decode an array of signed leb integers (so of course the - * array is not composed of fixed length values, but is instead - * a sequence of sleb values). - * Returns a DW_DLV_BADADDR on error. - * Otherwise returns a pointer to an array of 32bit integers. - * The signed argument must be non-zero (the decode - * assumes sleb integers in the input data) at this time. - * Size of integer units must be 32 (32 bits each) at this time. - * Number of bytes in block is a byte count (not array count). - * Returns number of units in output block (ie, number of elements - * of the array that the return value points to) thru the argument. - */ -void * dwarf_uncompress_integer_block( - Dwarf_Debug, /* dbg */ - Dwarf_Bool, /* signed==true (or unsigned) */ - Dwarf_Small, /* size of integer units: 8, 16, 32, 64 */ - void*, /* input data */ - Dwarf_Unsigned, /* number of bytes in input */ - Dwarf_Unsigned*, /* number of units in output block */ - Dwarf_Error* /* error */ -); - -/* Operations to create location expressions. */ -Dwarf_P_Expr dwarf_new_expr(Dwarf_P_Debug /*dbg*/, Dwarf_Error* /*error*/); - -void dwarf_expr_reset( - Dwarf_P_Expr /*expr*/, - Dwarf_Error* /*error*/); - -Dwarf_Unsigned dwarf_add_expr_gen( - Dwarf_P_Expr /*expr*/, - Dwarf_Small /*opcode*/, - Dwarf_Unsigned /*val1*/, - Dwarf_Unsigned /*val2*/, - Dwarf_Error* /*error*/); - -Dwarf_Unsigned dwarf_add_expr_addr( - Dwarf_P_Expr /*expr*/, - Dwarf_Unsigned /*addr*/, - Dwarf_Signed /*sym_index*/, - Dwarf_Error* /*error*/); - -Dwarf_Unsigned dwarf_add_expr_addr_b( - Dwarf_P_Expr /*expr*/, - Dwarf_Unsigned /*addr*/, - Dwarf_Unsigned /*sym_index*/, - Dwarf_Error* /*error*/); - -Dwarf_Unsigned dwarf_expr_current_offset( - Dwarf_P_Expr /*expr*/, - Dwarf_Error* /*error*/); - -Dwarf_Addr dwarf_expr_into_block( - Dwarf_P_Expr /*expr*/, - Dwarf_Unsigned* /*length*/, - Dwarf_Error* /*error*/); - -Dwarf_Unsigned dwarf_add_arange(Dwarf_P_Debug /*dbg*/, - Dwarf_Addr /*begin_address*/, - Dwarf_Unsigned /*length*/, - Dwarf_Signed /*symbol_index*/, - Dwarf_Error* /*error*/); - -Dwarf_Unsigned dwarf_add_arange_b( - Dwarf_P_Debug /*dbg*/, - Dwarf_Addr /*begin_address*/, - Dwarf_Unsigned /*length*/, - Dwarf_Unsigned /*symbol_index*/, - Dwarf_Unsigned /*end_symbol_index*/, - Dwarf_Addr /*offset_from_end_symbol*/, - Dwarf_Error * /*error*/); - -Dwarf_Unsigned dwarf_add_pubname( - Dwarf_P_Debug /*dbg*/, - Dwarf_P_Die /*die*/, - char* /*pubname_name*/, - Dwarf_Error* /*error*/); - -Dwarf_Unsigned dwarf_add_funcname( - Dwarf_P_Debug /*dbg*/, - Dwarf_P_Die /*die*/, - char* /*func_name*/, - Dwarf_Error* /*error*/); - -Dwarf_Unsigned dwarf_add_typename( - Dwarf_P_Debug /*dbg*/, - Dwarf_P_Die /*die*/, - char* /*type_name*/, - Dwarf_Error* /*error*/); - -Dwarf_Unsigned dwarf_add_varname( - Dwarf_P_Debug /*dbg*/, - Dwarf_P_Die /*die*/, - char* /*var_name*/, - Dwarf_Error* /*error*/); - -Dwarf_Unsigned dwarf_add_weakname( - Dwarf_P_Debug /*dbg*/, - Dwarf_P_Die /*die*/, - char* /*weak_name*/, - Dwarf_Error* /*error*/); - -/* .debug_macinfo producer functions - Functions must be called in right order: the section is output - In the order these are presented. -*/ -int dwarf_def_macro(Dwarf_P_Debug /*dbg*/, - Dwarf_Unsigned /*line*/, - char * /*macname, with (arglist), no space before (*/, - char * /*macvalue*/, - Dwarf_Error* /*error*/); - -int dwarf_undef_macro(Dwarf_P_Debug /*dbg*/, - Dwarf_Unsigned /*line*/, - char * /*macname, no arglist, of course*/, - Dwarf_Error* /*error*/); - -int dwarf_start_macro_file(Dwarf_P_Debug /*dbg*/, - Dwarf_Unsigned /*fileindex*/, - Dwarf_Unsigned /*linenumber*/, - Dwarf_Error* /*error*/); - -int dwarf_end_macro_file(Dwarf_P_Debug /*dbg*/, - Dwarf_Error* /*error*/); - -int dwarf_vendor_ext(Dwarf_P_Debug /*dbg*/, - Dwarf_Unsigned /*constant*/, - char * /*string*/, - Dwarf_Error* /*error*/); - -/* end macinfo producer functions */ - -int dwarf_attr_offset(Dwarf_Die /*die*/, - Dwarf_Attribute /*attr of above die*/, - Dwarf_Off * /*returns offset thru this ptr */, - Dwarf_Error * /*error*/); - -/* This is a hack so clients can verify offsets. - Added April 2005 so that debugger can detect broken offsets - (which happened in an IRIX executable larger than 2GB - with MIPSpro 7.3.1.3 toolchain.). -*/ -int -dwarf_get_section_max_offsets(Dwarf_Debug /*dbg*/, - Dwarf_Unsigned * /*debug_info_size*/, - Dwarf_Unsigned * /*debug_abbrev_size*/, - Dwarf_Unsigned * /*debug_line_size*/, - Dwarf_Unsigned * /*debug_loc_size*/, - Dwarf_Unsigned * /*debug_aranges_size*/, - Dwarf_Unsigned * /*debug_macinfo_size*/, - Dwarf_Unsigned * /*debug_pubnames_size*/, - Dwarf_Unsigned * /*debug_str_size*/, - Dwarf_Unsigned * /*debug_frame_size*/, - Dwarf_Unsigned * /*debug_ranges_size*/, - Dwarf_Unsigned * /*debug_pubtypes_size*/); - -/* Multiple releases spelled 'initial' as 'inital' . - The 'inital' spelling should not be used. */ -Dwarf_Half dwarf_set_frame_rule_inital_value(Dwarf_Debug /*dbg*/, - Dwarf_Half /*value*/); -/* Additional interface with correct 'initial' spelling. */ -/* It is likely you will want to call the following 5 functions - before accessing any frame information. All are useful - to tailor handling of pseudo-registers needed to turn - frame operation references into simpler forms and to - reflect ABI specific data. Of course altering libdwarf.h - and dwarf.h allow the same capabilities, but such header changes - do not let one change these values at runtime. */ -Dwarf_Half dwarf_set_frame_rule_initial_value(Dwarf_Debug /*dbg*/, - Dwarf_Half /*value*/); -Dwarf_Half dwarf_set_frame_rule_table_size(Dwarf_Debug /*dbg*/, - Dwarf_Half /*value*/); -Dwarf_Half dwarf_set_frame_cfa_value(Dwarf_Debug /*dbg*/, - Dwarf_Half /*value*/); -Dwarf_Half dwarf_set_frame_same_value(Dwarf_Debug /*dbg*/, - Dwarf_Half /*value*/); -Dwarf_Half dwarf_set_frame_undefined_value(Dwarf_Debug /*dbg*/, - Dwarf_Half /*value*/); - -/* As of April 27, 2009, this version with no diepointer is - obsolete though supported. Use dwarf_get_ranges_a() instead. */ -int dwarf_get_ranges(Dwarf_Debug /*dbg*/, - Dwarf_Off /*rangesoffset*/, - Dwarf_Ranges ** /*rangesbuf*/, - Dwarf_Signed * /*listlen*/, - Dwarf_Unsigned * /*bytecount*/, - Dwarf_Error * /*error*/); - -/* This adds the address_size argument. New April 27, 2009 */ -int dwarf_get_ranges_a(Dwarf_Debug /*dbg*/, - Dwarf_Off /*rangesoffset*/, - Dwarf_Die /* diepointer */, - Dwarf_Ranges ** /*rangesbuf*/, - Dwarf_Signed * /*listlen*/, - Dwarf_Unsigned * /*bytecount*/, - Dwarf_Error * /*error*/); - -void dwarf_ranges_dealloc(Dwarf_Debug /*dbg*/, - Dwarf_Ranges * /*rangesbuf*/, - Dwarf_Signed /*rangecount*/); - -/* The harmless error list is a circular buffer of - errors we note but which do not stop us from processing - the object. Created so dwarfdump or other tools - can report such inconsequential errors without causing - anything to stop early. */ -#define DW_HARMLESS_ERROR_CIRCULAR_LIST_DEFAULT_SIZE 4 -#define DW_HARMLESS_ERROR_MSG_STRING_SIZE 200 -/* User code supplies size of array of pointers errmsg_ptrs_array - in count and the array of pointers (the pointers themselves - need not be initialized). - The pointers returned in the array of pointers - are invalidated by ANY call to libdwarf. - Use them before making another libdwarf call! - The array of string pointers passed in always has - a final null pointer, so if there are N pointers the - and M actual strings, then MIN(M,N-1) pointers are - set to point to error strings. The array of pointers - to strings always terminates with a NULL pointer. - If 'count' is passed in zero then errmsg_ptrs_array - is not touched. - - The function returns DW_DLV_NO_ENTRY if no harmless errors - were noted so far. Returns DW_DLV_OK if there are errors. - Never returns DW_DLV_ERROR. - - Each call empties the error list (discarding all current entries). - If newerr_count is non-NULL the count of harmless errors - since the last call is returned through the pointer - (some may have been discarded or not returned, it is a circular - list...). - If DW_DLV_NO_ENTRY is returned none of the arguments - here are touched or used. - */ -int dwarf_get_harmless_error_list(Dwarf_Debug /*dbg*/, - unsigned /*count*/, - const char ** /*errmsg_ptrs_array*/, - unsigned * /*newerr_count*/); - -/* Insertion is only for testing the harmless error code, it is not - necessarily useful otherwise. */ -void dwarf_insert_harmless_error(Dwarf_Debug /*dbg*/, - char * /*newerror*/); - -/* The size of the circular list of strings may be set - and reset as needed. If it is shortened excess - messages are simply dropped. It returns the previous - size. If zero passed in the size is unchanged - and it simply returns the current size */ -unsigned dwarf_set_harmless_error_list_size(Dwarf_Debug /*dbg*/, - unsigned /*maxcount*/); -/* The harmless error strings (if any) are freed when the dbg - is dwarf_finish()ed. */ - -/* When the val_in is known these dwarf_get_TAG_name (etc) - functions return the string corresponding to the val_in passed in - through the pointer s_out and the value returned is DW_DLV_OK. - The strings are in static storage - and must not be freed. - If DW_DLV_NO_ENTRY is returned the val_in is not known and - *s_out is not set. DW_DLV_ERROR is never returned.*/ - -extern int dwarf_get_TAG_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_children_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_FORM_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_AT_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_OP_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_ATE_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_DS_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_END_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_ATCF_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_ACCESS_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_VIS_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_VIRTUALITY_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_LANG_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_ID_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_CC_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_INL_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_ORD_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_DSC_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_LNS_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_LNE_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_MACINFO_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_CFA_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_EH_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_FRAME_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_CHILDREN_name(unsigned int /*val_in*/, const char ** /*s_out */); -extern int dwarf_get_ADDR_name(unsigned int /*val_in*/, const char ** /*s_out */); - -#ifdef __cplusplus -} -#endif -#endif /* _LIBDWARF_H */ - - diff --git a/usr/src/tools/ctf/dwarf/common/libdwarfdefs.h b/usr/src/tools/ctf/dwarf/common/libdwarfdefs.h deleted file mode 100644 index a564655b23..0000000000 --- a/usr/src/tools/ctf/dwarf/common/libdwarfdefs.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - -/* libdwarfdefs.h -*/ - -#ifndef LIBDWARFDEFS_H -#define LIBDWARFDEFS_H - -/* We want __uint32_t and __uint64_t and __int32_t __int64_t - properly defined but not duplicated, since duplicate typedefs - are not legal C. -*/ -/* - HAVE___UINT32_T - HAVE___UINT64_T will be set by configure if - our 4 types are predefined in compiler -*/ - - -#if (!defined(HAVE___UINT32_T)) && defined(HAVE___UINT32_T_IN_SGIDEFS_H) -#include /* sgidefs.h defines them */ -#define HAVE___UINT32_T 1 -#endif - -#if (!defined(HAVE___UINT64_T)) && defined(HAVE___UINT64_T_IN_SGIDEFS_H) -#include /* sgidefs.h defines them */ -#define HAVE___UINT64_T 1 -#endif - - -#if (!defined(HAVE___UINT32_T)) && \ - defined(HAVE_SYS_TYPES_H) && \ - defined(HAVE___UINT32_T_IN_SYS_TYPES_H) -# include -#define HAVE___UINT32_T 1 -#endif - -#if (!defined(HAVE___UINT64_T)) && \ - defined(HAVE_SYS_TYPES_H) && \ - defined(HAVE___UINT64_T_IN_SYS_TYPES_H) -# include -#define HAVE___UINT64_T 1 -#endif - -#ifndef HAVE___UINT32_T -typedef int __int32_t; -typedef unsigned __uint32_t; -#define HAVE___UINT32_T 1 -#endif - -#ifndef HAVE___UINT64_T -typedef long long __int64_t; -typedef unsigned long long __uint64_t; -#define HAVE___UINT64_T 1 -#endif - -#endif /* LIBDWARFDEFS_H */ diff --git a/usr/src/tools/ctf/dwarf/common/malloc_check.c b/usr/src/tools/ctf/dwarf/common/malloc_check.c deleted file mode 100644 index 1c6e7738e4..0000000000 --- a/usr/src/tools/ctf/dwarf/common/malloc_check.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - - Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -/* malloc_check.c For checking dealloc completeness. - - This code is as simple as possible and works ok for - reasonable size allocation counts. - - It treats allocation as global, and so will not - work very well if an application opens more than one - Dwarf_Debug. - -*/ - -#include -#include /* for exit() and various malloc - prototypes */ -#include "config.h" -#include "dwarf_incl.h" -#include "malloc_check.h" -#ifdef WANT_LIBBDWARF_MALLOC_CHECK - -/* To turn off printing every entry, just change the define - to set PRINT_MALLOC_DETAILS 0. -*/ -#define PRINT_MALLOC_DETAILS 0 - -#define MC_TYPE_UNKNOWN 0 -#define MC_TYPE_ALLOC 1 -#define MC_TYPE_DEALLOC 2 - -struct mc_data_s { - struct mc_data_s *mc_prev; - unsigned long mc_address; /* Assumes this is large enough to hold - a pointer! */ - - long mc_alloc_number; /* Assigned in order by when record - created. */ - unsigned char mc_alloc_code; /* Allocation code, libdwarf. */ - unsigned char mc_type; - unsigned char mc_dealloc_noted; /* Used on an ALLOC node. */ - unsigned char mc_dealloc_noted_count; /* Used on an ALLOC - node. */ -}; - -/* - - -*/ -#define HASH_TABLE_SIZE 10501 -static struct mc_data_s *mc_data_hash[HASH_TABLE_SIZE]; -static long mc_data_list_size = 0; - -static char *alloc_type_name[MAX_DW_DLA + 1] = { - "", - "DW_DLA_STRING", - "DW_DLA_LOC", - "DW_DLA_LOCDESC", - "DW_DLA_ELLIST", - "DW_DLA_BOUNDS", - "DW_DLA_BLOCK", - "DW_DLA_DEBUG", - "DW_DLA_DIE", - "DW_DLA_LINE", - "DW_DLA_ATTR", - "DW_DLA_TYPE", - "DW_DLA_SUBSCR", - "DW_DLA_GLOBAL", - "DW_DLA_ERROR", - "DW_DLA_LIST", - "DW_DLA_LINEBUF", - "DW_DLA_ARANGE", - "DW_DLA_ABBREV", - "DW_DLA_FRAME_OP", - "DW_DLA_CIE", - "DW_DLA_FDE", - "DW_DLA_LOC_BLOCK", - "DW_DLA_FRAME_BLOCK", - "DW_DLA_FUNC", - "DW_DLA_TYPENAME", - "DW_DLA_VAR", - "DW_DLA_WEAK", - "DW_DLA_ADDR", - "DW_DLA_ABBREV_LIST", - "DW_DLA_CHAIN", - "DW_DLA_CU_CONTEXT", - "DW_DLA_FRAME", - "DW_DLA_GLOBAL_CONTEXT", - "DW_DLA_FILE_ENTRY", - "DW_DLA_LINE_CONTEXT", - "DW_DLA_LOC_CHAIN", - "DW_DLA_HASH_TABLE", - "DW_DLA_FUNC_CONTEXT", - "DW_DLA_TYPENAME_CONTEXT", - "DW_DLA_VAR_CONTEXT", - "DW_DLA_WEAK_CONTEXT", - "DW_DLA_PUBTYPES_CONTEXT" - /* Don't forget to expand this list if the list of codes - expands. */ -}; - -static unsigned -hash_address(unsigned long addr) -{ - unsigned long a = addr >> 2; - - return a % HASH_TABLE_SIZE; -} - -#if PRINT_MALLOC_DETAILS -static void -print_alloc_dealloc_detail(unsigned long addr, - int code, char *whichisit) -{ - fprintf(stderr, - "%s addr 0x%lx code %d (%s) entry %ld\n", - whichisit, addr, code, alloc_type_name[code], - mc_data_list_size); -} -#else -#define print_alloc_dealloc_detail(a,b,c) /* nothing */ -#endif - -/* Create a zeroed struct or die. */ -static void * -newone(void) -{ - struct mc_data_s *newd = malloc(sizeof(struct mc_data_s)); - - if (newd == 0) { - fprintf(stderr, "out of memory , # %ld\n", mc_data_list_size); - exit(1); - } - memset(newd, 0, sizeof(struct mc_data_s)); - return newd; -} - -/* Notify checker that get_alloc has allocated user data. */ -void -dwarf_malloc_check_alloc_data(void *addr_in, unsigned char code) -{ - struct mc_data_s *newd = newone(); - unsigned long addr = (unsigned long) addr_in; - struct mc_data_s **base = &mc_data_hash[hash_address(addr)]; - - print_alloc_dealloc_detail(addr, code, "alloc "); - newd->mc_address = addr; - newd->mc_alloc_code = code; - newd->mc_type = MC_TYPE_ALLOC; - newd->mc_alloc_number = mc_data_list_size; - newd->mc_prev = *base; - *base = newd; - newd->mc_alloc_number = mc_data_list_size; - mc_data_list_size += 1; -} - -static void -print_entry(char *msg, struct mc_data_s *data) -{ - fprintf(stderr, - "%s: 0x%08lx code %2d (%s) type %s dealloc noted %u ct %u\n", - msg, - (long) data->mc_address, - data->mc_alloc_code, - alloc_type_name[data->mc_alloc_code], - (data->mc_type == MC_TYPE_ALLOC) ? "alloc " : - (data->mc_type == MC_TYPE_DEALLOC) ? "dealloc" : "unknown", - (unsigned) data->mc_dealloc_noted, - (unsigned) data->mc_dealloc_noted_count); -} - -/* newd is a 'dealloc'. -*/ -static long -balanced_by_alloc_p(struct mc_data_s *newd, - long *addr_match_num, - struct mc_data_s **addr_match, - struct mc_data_s *base) -{ - struct mc_data_s *cur = base; - - for (; cur; cur = cur->mc_prev) { - if (cur->mc_address == newd->mc_address) { - if (cur->mc_type == MC_TYPE_ALLOC) { - if (cur->mc_alloc_code == newd->mc_alloc_code) { - *addr_match = cur; - *addr_match_num = cur->mc_alloc_number; - return cur->mc_alloc_number; - } else { - /* code mismatch */ - *addr_match = cur; - *addr_match_num = cur->mc_alloc_number; - return -1; - } - } else { - /* Unbalanced new/del */ - *addr_match = cur; - *addr_match_num = cur->mc_alloc_number; - return -1; - } - } - } - return -1; -} - -/* A dealloc is to take place. Ensure it balances an alloc. -*/ -void -dwarf_malloc_check_dealloc_data(void *addr_in, unsigned char code) -{ - struct mc_data_s *newd = newone(); - long prev; - long addr_match_num = -1; - struct mc_data_s *addr_match = 0; - unsigned long addr = (unsigned long) addr_in; - struct mc_data_s **base = &mc_data_hash[hash_address(addr)]; - - - print_alloc_dealloc_detail(addr, code, "dealloc "); - newd->mc_address = (unsigned long) addr; - newd->mc_alloc_code = code; - newd->mc_type = MC_TYPE_DEALLOC; - newd->mc_prev = *base; - prev = - balanced_by_alloc_p(newd, &addr_match_num, &addr_match, *base); - if (prev < 0) { - fprintf(stderr, - "Unbalanced dealloc at index %ld\n", mc_data_list_size); - print_entry("new", newd); - fprintf(stderr, "addr-match_num? %ld\n", addr_match_num); - if (addr_match) { - print_entry("prev entry", addr_match); - if (addr_match->mc_dealloc_noted > 1) { - fprintf(stderr, "Above is Duplicate dealloc!\n"); - } - } - abort(); - exit(3); - } - addr_match->mc_dealloc_noted = 1; - addr_match->mc_dealloc_noted_count += 1; - if (addr_match->mc_dealloc_noted_count > 1) { - fprintf(stderr, "Double dealloc entry %ld\n", addr_match_num); - print_entry("new dealloc entry", newd); - print_entry("bad alloc entry", addr_match); - } - *base = newd; - mc_data_list_size += 1; -} - -/* Final check for leaks. -*/ -void -dwarf_malloc_check_complete(char *msg) -{ - long i = 0; - long total = mc_data_list_size; - long hash_slots_used = 0; - long max_chain_length = 0; - - fprintf(stderr, "Run complete, %s. %ld entries\n", msg, total); - for (; i < HASH_TABLE_SIZE; ++i) { - struct mc_data_s *cur = mc_data_hash[i]; - long cur_chain_length = 0; - - if (cur == 0) - continue; - ++hash_slots_used; - for (; cur; cur = cur->mc_prev) { - ++cur_chain_length; - if (cur->mc_type == MC_TYPE_ALLOC) { - if (cur->mc_dealloc_noted) { - if (cur->mc_dealloc_noted > 1) { - fprintf(stderr, - " Duplicate dealloc! entry %ld\n", - cur->mc_alloc_number); - print_entry("duplicate dealloc", cur); - - } - continue; - } else { - fprintf(stderr, "malloc no dealloc, entry %ld\n", - cur->mc_alloc_number); - print_entry("dangle", cur); - } - } else { - /* mc_type is MC_TYPE_DEALLOC, already checked */ - - } - } - if (cur_chain_length > max_chain_length) { - max_chain_length = cur_chain_length; - } - } - fprintf(stderr, "mc hash table slots=%ld, " - "used=%ld, maxchain=%ld\n", - (long) HASH_TABLE_SIZE, hash_slots_used, max_chain_length); - return; -} - -#else - -extern void *libdwarf_an_unused_function_so_not_empty_c_file(); - -#endif /* WANT_LIBBDWARF_MALLOC_CHECK */ diff --git a/usr/src/tools/ctf/dwarf/common/malloc_check.h b/usr/src/tools/ctf/dwarf/common/malloc_check.h deleted file mode 100644 index ba1ad3da71..0000000000 --- a/usr/src/tools/ctf/dwarf/common/malloc_check.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - - Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved. - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - -/* malloc_check.h */ - -/* A simple libdwarf-aware malloc checker. - define WANT_LIBBDWARF_MALLOC_CHECK and rebuild libdwarf - do make a checking-for-alloc-mistakes libdwarf. - NOT recommended for production use. - - When defined, also add malloc_check.c to the list of - files in Makefile. -*/ - -#undef WANT_LIBBDWARF_MALLOC_CHECK -/*#define WANT_LIBBDWARF_MALLOC_CHECK 1 */ - -#ifdef WANT_LIBBDWARF_MALLOC_CHECK - -void dwarf_malloc_check_alloc_data(void * addr,unsigned char code); -void dwarf_malloc_check_dealloc_data(void * addr,unsigned char code); -void dwarf_malloc_check_complete(char *wheremsg); /* called at exit of app */ - -#else /* !WANT_LIBBDWARF_MALLOC_CHECK */ - -#define dwarf_malloc_check_alloc_data(a,b) /* nothing */ -#define dwarf_malloc_check_dealloc_data(a,b) /* nothing */ -#define dwarf_malloc_check_complete(a) /* nothing */ - -#endif /* WANT_LIBBDWARF_MALLOC_CHECK */ diff --git a/usr/src/tools/ctf/dwarf/common/mapfile-vers b/usr/src/tools/ctf/dwarf/common/mapfile-vers deleted file mode 100644 index c1a652a591..0000000000 --- a/usr/src/tools/ctf/dwarf/common/mapfile-vers +++ /dev/null @@ -1,302 +0,0 @@ -# -# This file and its contents are supplied under the terms of the -# Common Development and Distribution License ("CDDL"), version 1.0. -# You may only use this file in accordance with the terms of version -# 1.0 of the CDDL. -# -# A full copy of the text of the CDDL should have accompanied this -# source. A copy of the CDDL is also available via the Internet at -# http://www.illumos.org/license/CDDL. -# - -# -# Copyright 2011, Richard Lowe. -# - -# -# MAPFILE HEADER START -# -# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. -# Object versioning must comply with the rules detailed in -# -# usr/src/lib/README.mapfiles -# -# You should not be making modifications here until you've read the most current -# copy of that file. If you need help, contact a gatekeeper for guidance. -# -# MAPFILE HEADER END -# - -$mapfile_version 2 - -SYMBOL_VERSION ILLUMOSprivate_1.1 { - global: - dwarf_add_arange; - dwarf_add_arange_b; - dwarf_add_AT_block; - dwarf_add_AT_comp_dir; - dwarf_add_AT_const_value_signedint; - dwarf_add_AT_const_value_string; - dwarf_add_AT_const_value_unsignedint; - dwarf_add_AT_dataref; - dwarf_add_AT_flag; - dwarf_add_AT_location_expr; - dwarf_add_AT_name; - dwarf_add_AT_producer; - dwarf_add_AT_ref_address; - dwarf_add_AT_reference; - dwarf_add_AT_signed_const; - dwarf_add_AT_string; - dwarf_add_AT_targ_address; - dwarf_add_AT_targ_address_b; - dwarf_add_AT_unsigned_const; - dwarf_add_die_marker; - dwarf_add_die_to_debug; - dwarf_add_directory_decl; - dwarf_add_expr_addr; - dwarf_add_expr_addr_b; - dwarf_add_expr_gen; - dwarf_add_fde_inst; - dwarf_add_file_decl; - dwarf_add_frame_cie; - dwarf_add_frame_fde; - dwarf_add_frame_fde_b; - dwarf_add_frame_info; - dwarf_add_frame_info_b; - dwarf_add_funcname; - dwarf_add_line_entry; - dwarf_add_pubname; - dwarf_add_typename; - dwarf_add_varname; - dwarf_add_weakname; - dwarf_arrayorder; - dwarf_attr; - dwarf_attr_offset; - dwarf_attrlist; - dwarf_bitoffset; - dwarf_bitsize; - dwarf_bytesize; - dwarf_check_lineheader; - dwarf_child; - dwarf_cie_section_offset; - dwarf_compress_integer_block; - dwarf_create_cie_from_after_start; - dwarf_create_fde_from_after_start; - dwarf_CU_dieoffset_given_die; - dwarf_dealloc; - dwarf_dealloc_compressed_block; - dwarf_dealloc_uncompressed_block; - dwarf_def_macro; - dwarf_die_abbrev_code; - dwarf_die_CU_offset; - dwarf_die_CU_offset_range; - dwarf_die_link; - dwarf_diename; - dwarf_dieoffset; - dwarf_elf_init; - dwarf_elf_object_access_finish; - dwarf_elf_object_access_init; - dwarf_end_macro_file; - dwarf_errmsg; - dwarf_errno; - dwarf_expand_frame_instructions; - dwarf_expr_current_offset; - dwarf_expr_into_block; - dwarf_expr_reset; - dwarf_fde_cfa_offset; - dwarf_fde_cie_list_dealloc; - dwarf_fde_section_offset; - dwarf_find_macro_value_start; - dwarf_finish; - dwarf_formaddr; - dwarf_formblock; - dwarf_formexprloc; - dwarf_formflag; - dwarf_formref; - dwarf_formsdata; - dwarf_formsig8; - dwarf_formstring; - dwarf_formudata; - dwarf_free_line_table_prefix; - dwarf_func_cu_offset; - dwarf_func_die_offset; - dwarf_func_name_offsets; - dwarf_funcname; - dwarf_funcs_dealloc; - dwarf_get_abbrev; - dwarf_get_abbrev_children_flag; - dwarf_get_abbrev_code; - dwarf_get_abbrev_entry; - dwarf_get_abbrev_tag; - dwarf_get_ACCESS_name; - dwarf_get_ADDR_name; - dwarf_get_address_size; - dwarf_get_arange; - dwarf_get_arange_cu_header_offset; - dwarf_get_arange_info; - dwarf_get_arange_info_b; - dwarf_get_aranges; - dwarf_get_AT_name; - dwarf_get_ATCF_name; - dwarf_get_ATE_name; - dwarf_get_CC_name; - dwarf_get_CFA_name; - dwarf_get_children_name; - dwarf_get_CHILDREN_name; - dwarf_get_cie_augmentation_data; - dwarf_get_cie_index; - dwarf_get_cie_info; - dwarf_get_cie_of_fde; - dwarf_get_cu_die_offset; - dwarf_get_cu_die_offset_given_cu_header_offset; - dwarf_get_die_address_size; - dwarf_get_die_marker; - dwarf_get_die_markers; - dwarf_get_DS_name; - dwarf_get_DSC_name; - dwarf_get_EH_name; - dwarf_get_elf; - dwarf_get_END_name; - dwarf_get_fde_at_pc; - dwarf_get_fde_augmentation_data; - dwarf_get_fde_exception_info; - dwarf_get_fde_for_die; - dwarf_get_fde_info_for_all_regs; - dwarf_get_fde_info_for_all_regs3; - dwarf_get_fde_info_for_cfa_reg3; - dwarf_get_fde_info_for_reg; - dwarf_get_fde_info_for_reg3; - dwarf_get_fde_instr_bytes; - dwarf_get_fde_list; - dwarf_get_fde_list_eh; - dwarf_get_fde_n; - dwarf_get_fde_range; - dwarf_get_form_class; - dwarf_get_FORM_name; - dwarf_get_FRAME_name; - dwarf_get_funcs; - dwarf_get_globals; - dwarf_get_harmless_error_list; - dwarf_get_ID_name; - dwarf_get_INL_name; - dwarf_get_ISA_name; - dwarf_get_LANG_name; - dwarf_get_LNE_name; - dwarf_get_LNS_name; - dwarf_get_loclist_entry; - dwarf_get_MACINFO_name; - dwarf_get_macro_details; - dwarf_get_OP_name; - dwarf_get_ORD_name; - dwarf_get_pubtypes; - dwarf_get_ranges; - dwarf_get_ranges_a; - dwarf_get_relocation_info; - dwarf_get_relocation_info_count; - dwarf_get_section_bytes; - dwarf_get_section_max_offsets; - dwarf_get_str; - dwarf_get_string_attributes_count; - dwarf_get_string_attributes_info; - dwarf_get_TAG_name; - dwarf_get_types; - dwarf_get_vars; - dwarf_get_VIRTUALITY_name; - dwarf_get_VIS_name; - dwarf_get_weaks; - dwarf_global_cu_offset; - dwarf_global_die_offset; - dwarf_global_formref; - dwarf_global_name_offsets; - dwarf_globals_dealloc; - dwarf_globname; - dwarf_harmless_cleanout; - dwarf_harmless_init; - dwarf_hasattr; - dwarf_hasform; - dwarf_highpc; - dwarf_init; - dwarf_init_line_table_prefix; - dwarf_insert_fde_inst_bytes; - dwarf_insert_harmless_error; - dwarf_ld_sort_lines; - dwarf_line_srcfileno; - dwarf_lineaddr; - dwarf_linebeginstatement; - dwarf_lineblock; - dwarf_lineendsequence; - dwarf_lineno; - dwarf_lineoff; - dwarf_linesrc; - dwarf_lne_end_sequence; - dwarf_lne_set_address; - dwarf_loclist; - dwarf_loclist_from_expr; - dwarf_loclist_from_expr_a; - dwarf_loclist_n; - dwarf_lowpc; - dwarf_new_die; - dwarf_new_expr; - dwarf_new_fde; - dwarf_next_cu_header; - dwarf_next_cu_header_b; - dwarf_nextglob; - dwarf_object_finish; - dwarf_object_init; - dwarf_offdie; - dwarf_p_dealloc; - dwarf_print_lines; - dwarf_print_memory_stats; - dwarf_producer_finish; - dwarf_producer_init; - dwarf_producer_init_b; - dwarf_pubtype_cu_offset; - dwarf_pubtype_name_offsets; - dwarf_pubtype_type_die_offset; - dwarf_pubtypename; - dwarf_pubtypes_dealloc; - dwarf_ranges_dealloc; - dwarf_read_cie_fde_prefix; - dwarf_read_line_table_prefix; - dwarf_reset_section_bytes; - dwarf_set_frame_cfa_value; - dwarf_set_frame_rule_inital_value; - dwarf_set_frame_rule_initial_value; - dwarf_set_frame_rule_table_size; - dwarf_set_frame_same_value; - dwarf_set_frame_undefined_value; - dwarf_set_harmless_error_list_size; - dwarf_set_reloc_application; - dwarf_set_stringcheck; - dwarf_siblingof; - dwarf_srcfiles; - dwarf_srclang; - dwarf_srclines; - dwarf_srclines_dealloc; - dwarf_start_macro_file; - dwarf_tag; - dwarf_transform_to_disk_form; - dwarf_type_cu_offset; - dwarf_type_die_offset; - dwarf_type_name_offsets; - dwarf_typename; - dwarf_types_dealloc; - dwarf_uncompress_integer_block; - dwarf_undef_macro; - dwarf_var_cu_offset; - dwarf_var_die_offset; - dwarf_var_name_offsets; - dwarf_varname; - dwarf_vars_dealloc; - dwarf_vendor_ext; - dwarf_weak_cu_offset; - dwarf_weak_die_offset; - dwarf_weak_name_offsets; - dwarf_weakname; - dwarf_weaks_dealloc; - dwarf_whatattr; - dwarf_whatform; - dwarf_whatform_direct; - local: - *; -}; diff --git a/usr/src/tools/ctf/dwarf/common/pro_alloc.c b/usr/src/tools/ctf/dwarf/common/pro_alloc.c deleted file mode 100644 index 1ca7806239..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_alloc.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "pro_incl.h" -#ifdef HAVE_STDLIB_H -#include -#endif /* HAVE_STDLIB_H */ -#ifdef HAVE_STRING_H -#include -#endif /* HAVE_STRING_H */ -#include - -/* - When each block is allocated, there is a two-word structure - allocated at the beginning so the block can go on a list. - The address returned is the address *after* the two pointers - at the start. But this allows us to be given a pointer to - a generic block, and go backwards to find the list-node. Then - we can remove this block from it's list without the need to search - through a linked list in order to remove the node. It also allows - us to 'delete' a memory block without needing the dbg structure. - We still need the dbg structure on allocation so that we know which - linked list to add the block to. - - Only the allocation of the dbg structure itself cannot use _dwarf_p_get_alloc. - That structure should be set up by hand, and the two list pointers - should be initialized to point at the node itself. That initializes - the doubly linked list. -*/ - -#define LIST_TO_BLOCK(lst) ((void*) (((char *)lst) + sizeof(memory_list_t))) -#define BLOCK_TO_LIST(blk) ((memory_list_t*) (((char*)blk) - sizeof(memory_list_t))) - - -/* - dbg should be NULL only when allocating dbg itself. In that - case we initialize it to an empty circular doubly-linked list. -*/ - -Dwarf_Ptr -_dwarf_p_get_alloc(Dwarf_P_Debug dbg, Dwarf_Unsigned size) -{ - void *sp; - memory_list_t *lp = NULL; - memory_list_t *dbglp = NULL; - memory_list_t *nextblock = NULL; - - /* alloc control struct and data block together for performance reasons */ - lp = (memory_list_t *) malloc(size + sizeof(memory_list_t)); - if (lp == NULL) { - /* should throw an error */ - return NULL; - } - - /* point to 'size' bytes just beyond lp struct */ - sp = LIST_TO_BLOCK(lp); - memset(sp, 0, size); - - if (dbg == NULL) { - lp->next = lp->prev = lp; - } else { - /* I always have to draw a picture to understand this part. */ - - dbglp = BLOCK_TO_LIST(dbg); - nextblock = dbglp->next; - - /* Insert between dbglp and nextblock */ - dbglp->next = lp; - lp->prev = dbglp; - lp->next = nextblock; - nextblock->prev = lp; - } - - return sp; -} - -/* - This routine is only here in case a caller of an older version of the - library is calling this for some reason. - We will clean up any stray blocks when the session is closed. - No need to remove this block. In theory the user might be - depending on the fact that we used to just 'free' this. - In theory they might also be - passing a block that they got from libdwarf. So we don't know if we - should try to remove this block from our global list. Safest just to - do nothing at this point. - - !!! - This function is deprecated! Don't call it inside libdwarf or outside of it. - !!! -*/ - -void -dwarf_p_dealloc(Dwarf_Small * ptr) -{ - return; -} - -/* - The dbg structure is not needed here anymore. -*/ - -void -_dwarf_p_dealloc(Dwarf_P_Debug dbg, Dwarf_Small * ptr) /* ARGSUSED */ -{ - memory_list_t *lp; - lp = BLOCK_TO_LIST(ptr); - - /* - Remove from a doubly linked, circular list. - Read carefully, use a white board if necessary. - If this is an empty list, the following statements are no-ops, and - will write to the same memory location they read from. - This should only happen when we deallocate the dbg structure itself. - */ - - lp->prev->next = lp->next; - lp->next->prev = lp->prev; - - free((void*)lp); -} - - -/* - This routine deallocates all the nodes on the dbg list, - and then deallocates the dbg structure itself. -*/ - -void -_dwarf_p_dealloc_all(Dwarf_P_Debug dbg) -{ - memory_list_t *dbglp; - - if (dbg == NULL) { - /* should throw an error */ - return; - } - - dbglp = BLOCK_TO_LIST(dbg); - while (dbglp->next != dbglp) { - _dwarf_p_dealloc(dbg, LIST_TO_BLOCK(dbglp->next)); - } - if (dbglp->next != dbglp || - dbglp->prev != dbglp) { - - /* should throw error */ - /* For some reason we couldn't free all the blocks? */ - return; - } - _dwarf_p_dealloc(NULL, (void*)dbg); -} - diff --git a/usr/src/tools/ctf/dwarf/common/pro_alloc.h b/usr/src/tools/ctf/dwarf/common/pro_alloc.h deleted file mode 100644 index b4da65325f..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_alloc.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -Dwarf_Ptr _dwarf_p_get_alloc(Dwarf_P_Debug, Dwarf_Unsigned); - -void _dwarf_p_dealloc(Dwarf_P_Debug dbg, Dwarf_Small * ptr); - -void _dwarf_p_dealloc_all(Dwarf_P_Debug dbg); diff --git a/usr/src/tools/ctf/dwarf/common/pro_arange.c b/usr/src/tools/ctf/dwarf/common/pro_arange.c deleted file mode 100644 index 4e5c37795c..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_arange.c +++ /dev/null @@ -1,337 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#include -#include -#ifdef HAVE_ELFACCESS_H -#include -#endif -#include "pro_incl.h" -#include "pro_arange.h" -#include "pro_section.h" -#include "pro_reloc.h" - - - -/* - This function adds another address range - to the list of address ranges for the - given Dwarf_P_Debug. It returns 0 on error, - and 1 otherwise. -*/ -Dwarf_Unsigned -dwarf_add_arange(Dwarf_P_Debug dbg, - Dwarf_Addr begin_address, - Dwarf_Unsigned length, - Dwarf_Signed symbol_index, Dwarf_Error * error) -{ - return dwarf_add_arange_b(dbg, begin_address, length, symbol_index, - /* end_symbol_index */ 0, - /* offset_from_end_sym */ 0, - error); -} - -/* - This function adds another address range - to the list of address ranges for the - given Dwarf_P_Debug. It returns 0 on error, - and 1 otherwise. -*/ -Dwarf_Unsigned -dwarf_add_arange_b(Dwarf_P_Debug dbg, - Dwarf_Addr begin_address, - Dwarf_Unsigned length, - Dwarf_Unsigned symbol_index, - Dwarf_Unsigned end_symbol_index, - Dwarf_Addr offset_from_end_sym, Dwarf_Error * error) -{ - Dwarf_P_Arange arange; - - if (dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return (0); - } - - arange = (Dwarf_P_Arange) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Arange_s)); - if (arange == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (0); - } - - arange->ag_begin_address = begin_address; - arange->ag_length = length; - arange->ag_symbol_index = symbol_index; - arange->ag_end_symbol_index = end_symbol_index; - arange->ag_end_symbol_offset = offset_from_end_sym; - - if (dbg->de_arange == NULL) - dbg->de_arange = dbg->de_last_arange = arange; - else { - dbg->de_last_arange->ag_next = arange; - dbg->de_last_arange = arange; - } - dbg->de_arange_count++; - - return (1); -} - - -int -_dwarf_transform_arange_to_disk(Dwarf_P_Debug dbg, Dwarf_Error * error) -{ - /* Total num of bytes in .debug_aranges section. */ - Dwarf_Unsigned arange_num_bytes; - - /* - Adjustment to align the start of the actual address ranges on a - boundary aligned with twice the address size. */ - Dwarf_Small remainder; - - /* Total number of bytes excluding the length field. */ - Dwarf_Unsigned adjusted_length; - - /* Points to first byte of .debug_aranges buffer. */ - Dwarf_Small *arange; - - /* Fills in the .debug_aranges buffer. */ - Dwarf_Small *arange_ptr; - - /* Scans the list of address ranges provided by user. */ - Dwarf_P_Arange given_arange; - - /* Used to fill in 0. */ - const Dwarf_Signed big_zero = 0; - - int extension_word_size = dbg->de_64bit_extension ? 4 : 0; - int uword_size = dbg->de_offset_size; - int upointer_size = dbg->de_pointer_size; - int res; - - - /* ***** BEGIN CODE ***** */ - - /* Size of the .debug_aranges section header. */ - arange_num_bytes = extension_word_size + uword_size + /* Size - of - length - field. - */ - sizeof(Dwarf_Half) + /* Size of version field. */ - uword_size + /* Size of .debug_info offset. */ - sizeof(Dwarf_Small) + /* Size of address size field. */ - sizeof(Dwarf_Small); /* Size of segment size field. */ - - /* - Adjust the size so that the set of aranges begins on a boundary - that aligned with twice the address size. This is a Libdwarf - requirement. */ - remainder = arange_num_bytes % (2 * upointer_size); - if (remainder != 0) - arange_num_bytes += (2 * upointer_size) - remainder; - - - /* Add the bytes for the actual address ranges. */ - arange_num_bytes += upointer_size * 2 * (dbg->de_arange_count + 1); - - GET_CHUNK(dbg, dbg->de_elf_sects[DEBUG_ARANGES], - arange, (unsigned long) arange_num_bytes, error); - arange_ptr = arange; - if (arange == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (0); - } - if (extension_word_size) { - Dwarf_Word x = DISTINGUISHED_VALUE; - - WRITE_UNALIGNED(dbg, (void *) arange_ptr, - (const void *) &x, - sizeof(x), extension_word_size); - arange_ptr += extension_word_size; - } - - /* Write the total length of .debug_aranges section. */ - adjusted_length = arange_num_bytes - uword_size - - extension_word_size; - { - Dwarf_Unsigned du = adjusted_length; - - WRITE_UNALIGNED(dbg, (void *) arange_ptr, - (const void *) &du, sizeof(du), uword_size); - arange_ptr += uword_size; - } - - /* Write the version as 2 bytes. */ - { - Dwarf_Half verstamp = CURRENT_VERSION_STAMP; - - WRITE_UNALIGNED(dbg, (void *) arange_ptr, - (const void *) &verstamp, - sizeof(verstamp), sizeof(Dwarf_Half)); - arange_ptr += sizeof(Dwarf_Half); - } - - - /* Write the .debug_info offset. This is always 0. */ - WRITE_UNALIGNED(dbg, (void *) arange_ptr, - (const void *) &big_zero, - sizeof(big_zero), uword_size); - arange_ptr += uword_size; - - { - unsigned long count = dbg->de_arange_count + 1; - int res; - - if (dbg->de_reloc_pair) { - count = (3 * dbg->de_arange_count) + 1; - } - /* the following is a small optimization: not needed for - correctness */ - res = _dwarf_pro_pre_alloc_n_reloc_slots(dbg, - DEBUG_ARANGES, count); - if (res != DW_DLV_OK) { - { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (0); - } - } - } - - /* reloc for .debug_info */ - res = dbg->de_reloc_name(dbg, - DEBUG_ARANGES, - extension_word_size + - uword_size + sizeof(Dwarf_Half), - dbg->de_sect_name_idx[DEBUG_INFO], - dwarf_drt_data_reloc, uword_size); - - /* Write the size of addresses. */ - *arange_ptr = dbg->de_pointer_size; - arange_ptr++; - - /* - Write the size of segment addresses. This is zero for MIPS - architectures. */ - *arange_ptr = 0; - arange_ptr++; - - /* - Skip over the padding to align the start of the actual address - ranges to twice the address size. */ - if (remainder != 0) - arange_ptr += (2 * upointer_size) - remainder; - - - - - - /* The arange address, length are pointer-size fields of the target - machine. */ - for (given_arange = dbg->de_arange; given_arange != NULL; - given_arange = given_arange->ag_next) { - - /* Write relocation record for beginning of address range. */ - res = dbg->de_reloc_name(dbg, DEBUG_ARANGES, arange_ptr - arange, /* r_offset - */ - (long) given_arange->ag_symbol_index, - dwarf_drt_data_reloc, upointer_size); - if (res != DW_DLV_OK) { - { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (0); - } - } - - /* Copy beginning address of range. */ - WRITE_UNALIGNED(dbg, (void *) arange_ptr, - (const void *) &given_arange->ag_begin_address, - sizeof(given_arange->ag_begin_address), - upointer_size); - arange_ptr += upointer_size; - - if (dbg->de_reloc_pair && - given_arange->ag_end_symbol_index != 0 && - given_arange->ag_length == 0) { - /* symbolic reloc, need reloc for length What if we really - know the length? If so, should use the other part of - 'if'. */ - Dwarf_Unsigned val; - - res = dbg->de_reloc_pair(dbg, DEBUG_ARANGES, arange_ptr - arange, /* r_offset - */ - given_arange->ag_symbol_index, - given_arange->ag_end_symbol_index, - dwarf_drt_first_of_length_pair, - upointer_size); - if (res != DW_DLV_OK) { - { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (0); - } - } - - /* arrange pre-calc so assem text can do .word end - begin - + val (gets val from stream) */ - val = given_arange->ag_end_symbol_offset - - given_arange->ag_begin_address; - WRITE_UNALIGNED(dbg, (void *) arange_ptr, - (const void *) &val, - sizeof(val), upointer_size); - arange_ptr += upointer_size; - - } else { - /* plain old length to copy, no relocation at all */ - WRITE_UNALIGNED(dbg, (void *) arange_ptr, - (const void *) &given_arange->ag_length, - sizeof(given_arange->ag_length), - upointer_size); - arange_ptr += upointer_size; - } - } - - WRITE_UNALIGNED(dbg, (void *) arange_ptr, - (const void *) &big_zero, - sizeof(big_zero), upointer_size); - - arange_ptr += upointer_size; - WRITE_UNALIGNED(dbg, (void *) arange_ptr, - (const void *) &big_zero, - sizeof(big_zero), upointer_size); - return (int) dbg->de_n_debug_sect; -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_arange.h b/usr/src/tools/ctf/dwarf/common/pro_arange.h deleted file mode 100644 index f0e7e84dff..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_arange.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - -/* - If ag_end_symbol_index is zero, - ag_length must be known and non-zero. - - - Deals with length being known costant or fr - assembler output, not known. - -*/ - -struct Dwarf_P_Arange_s { - Dwarf_Addr ag_begin_address; /* known address or for - symbolic assem output, - offset of symbol */ - Dwarf_Addr ag_length; /* zero or address or offset */ - Dwarf_Unsigned ag_symbol_index; - - Dwarf_P_Arange ag_next; - - Dwarf_Unsigned ag_end_symbol_index; /* zero or index/id of end - symbol */ - Dwarf_Addr ag_end_symbol_offset; /* known address or for - symbolic assem output, - offset of end symbol */ - -}; diff --git a/usr/src/tools/ctf/dwarf/common/pro_die.c b/usr/src/tools/ctf/dwarf/common/pro_die.c deleted file mode 100644 index 948b641146..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_die.c +++ /dev/null @@ -1,442 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#include -#include -#include "pro_incl.h" -#include "pro_die.h" - -#ifndef R_MIPS_NONE -#define R_MIPS_NONE 0 -#endif - -/* adds an attribute to a die */ -void _dwarf_pro_add_at_to_die(Dwarf_P_Die die, Dwarf_P_Attribute attr); - -/*---------------------------------------------------------------------------- - This function creates a new die. - tag: tag of the new die to be created - parent,child,left,right: specify neighbors of the new die. Only - one of these may be non-null ------------------------------------------------------------------------------*/ -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) -{ - Dwarf_P_Die ret_die = 0; - - Dwarf_P_Die new_die = (Dwarf_P_Die) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Die_s)); - if (new_die == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_ALLOC, - (Dwarf_P_Die) DW_DLV_BADADDR); - } - new_die->di_parent = NULL; - new_die->di_left = NULL; - new_die->di_right = NULL; - new_die->di_child = NULL; - new_die->di_last_child = NULL; - new_die->di_tag = tag; - new_die->di_dbg = dbg; - new_die->di_marker = 0; - ret_die = - dwarf_die_link(new_die, parent, child, left, right, error); - return ret_die; -} - -/*---------------------------------------------------------------------------- - This function links up a die to specified neighbors - parent,child,left,right: specify neighbors of the new die. Only - one of these may be non-null ------------------------------------------------------------------------------*/ -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) -{ - /* Count the # of non null neighbors. */ - int n_nulls = 0; - - if (parent != NULL) { - n_nulls++; - if (new_die->di_parent != NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_LINK_LOOP, - (Dwarf_P_Die) DW_DLV_BADADDR); - } - new_die->di_parent = parent; - if (parent->di_child) { - - /* di_last_child identifies the last sibling, the - die we want to attach new_die to. */ - /* ASSERT: if di_child is set so is di_last_child. */ - Dwarf_P_Die former_lastchild = parent->di_last_child; - parent->di_last_child = new_die; - /* Attach to the new die to end of the sibling list. */ - former_lastchild->di_right = new_die; - new_die->di_left = former_lastchild; - } else { - parent->di_child = new_die; - parent->di_last_child = new_die; - } - } - if (child != NULL) { - n_nulls++; - new_die->di_child = child; - new_die->di_last_child = child; - if (child->di_parent) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS, - (Dwarf_P_Die) DW_DLV_BADADDR); - } else { - child->di_parent = new_die; - } - } - if (left != NULL) { - n_nulls++; - new_die->di_left = left; - if (left->di_right) { - /* There's already a right sibling of left, - insert the new die in the list. */ - new_die->di_right = left->di_right; - left->di_right->di_left = new_die; - } - left->di_right = new_die; - if (new_die->di_parent) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS, - (Dwarf_P_Die) DW_DLV_BADADDR); - } else { - new_die->di_parent = left->di_parent; - } - } - if (right != NULL) { - n_nulls++; - new_die->di_right = right; - if (right->di_left) { - /* There is already a left sibling of the right die, - insert the new die in the list. */ - new_die->di_left = right->di_left; - right->di_left->di_right = new_die; - } - right->di_left = new_die; - if (new_die->di_parent) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS, - (Dwarf_P_Die) DW_DLV_BADADDR); - } else { - new_die->di_parent = right->di_parent; - } - } - if (n_nulls > 1) { - /* Multiple neighbors! error! */ - DWARF_P_DBG_ERROR(NULL, DW_DLE_EXTRA_NEIGHBORS, - (Dwarf_P_Die) DW_DLV_BADADDR); - } - return new_die; - -} - -Dwarf_Unsigned -dwarf_add_die_marker(Dwarf_P_Debug dbg, - Dwarf_P_Die die, - Dwarf_Unsigned marker, - Dwarf_Error * error) -{ - if (die == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, DW_DLV_NOCOUNT); - } - die->di_marker = marker; - return 0; -} - - -Dwarf_Unsigned -dwarf_get_die_marker(Dwarf_P_Debug dbg, - Dwarf_P_Die die, - Dwarf_Unsigned * marker, - Dwarf_Error * error) -{ - if (die == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, DW_DLV_NOCOUNT); - } - *marker = die->di_marker; - return 0; -} - - -/*---------------------------------------------------------------------------- - This function adds a die to dbg struct. It should be called using - the root of all the dies. ------------------------------------------------------------------------------*/ -Dwarf_Unsigned -dwarf_add_die_to_debug(Dwarf_P_Debug dbg, - Dwarf_P_Die first_die, Dwarf_Error * error) -{ - if (first_die == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, DW_DLV_NOCOUNT); - } - if (first_die->di_tag != DW_TAG_compile_unit) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_WRONG_TAG, DW_DLV_NOCOUNT); - } - dbg->de_dies = first_die; - return 0; -} - -int -_dwarf_pro_add_AT_stmt_list(Dwarf_P_Debug dbg, - Dwarf_P_Die first_die, Dwarf_Error * error) -{ - Dwarf_P_Attribute new_attr; - int uwordb_size = dbg->de_offset_size; - - /* Add AT_stmt_list attribute */ - new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); - if (new_attr == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, DW_DLV_NOCOUNT); - } - - new_attr->ar_attribute = DW_AT_stmt_list; - new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form; - new_attr->ar_rel_type = dbg->de_offset_reloc; - - new_attr->ar_nbytes = uwordb_size; - new_attr->ar_next = NULL; - new_attr->ar_reloc_len = uwordb_size; - new_attr->ar_data = (char *) - _dwarf_p_get_alloc(dbg, uwordb_size); - if (new_attr->ar_data == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT); - } - { - Dwarf_Unsigned du = 0; - - WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, - (const void *) &du, sizeof(du), uwordb_size); - } - - _dwarf_pro_add_at_to_die(first_die, new_attr); - return 0; -} - -/*----------------------------------------------------------------------------- - Add AT_name attribute to die -------------------------------------------------------------------------------*/ -Dwarf_P_Attribute -dwarf_add_AT_name(Dwarf_P_Die die, char *name, Dwarf_Error * error) -{ - Dwarf_P_Attribute new_attr; - - if (die == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, - (Dwarf_P_Attribute) DW_DLV_BADADDR); - } - new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(die->di_dbg,sizeof(struct Dwarf_P_Attribute_s)); - if (new_attr == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, - (Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - /* fill in the information */ - new_attr->ar_attribute = DW_AT_name; - /* assume that form is string, no debug_str yet */ - new_attr->ar_attribute_form = DW_FORM_string; - new_attr->ar_nbytes = strlen(name) + 1; - new_attr->ar_next = NULL; - new_attr->ar_reloc_len = 0; - new_attr->ar_data = (char *) - _dwarf_p_get_alloc(die->di_dbg, strlen(name)+1); - if (new_attr->ar_data == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_STRING_ALLOC, - (Dwarf_P_Attribute) DW_DLV_BADADDR); - } - strcpy(new_attr->ar_data, name); - - new_attr->ar_rel_type = R_MIPS_NONE; - - /* add attribute to the die */ - _dwarf_pro_add_at_to_die(die, new_attr); - return new_attr; -} - - -/*----------------------------------------------------------------------------- - Add AT_comp_dir attribute to die -------------------------------------------------------------------------------*/ -Dwarf_P_Attribute -dwarf_add_AT_comp_dir(Dwarf_P_Die ownerdie, - char *current_working_directory, - Dwarf_Error * error) -{ - Dwarf_P_Attribute new_attr; - - if (ownerdie == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, - (Dwarf_P_Attribute) DW_DLV_BADADDR); - } - new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(ownerdie->di_dbg, - sizeof(struct Dwarf_P_Attribute_s)); - if (new_attr == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, - (Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - /* fill in the information */ - new_attr->ar_attribute = DW_AT_comp_dir; - /* assume that form is string, no debug_str yet */ - new_attr->ar_attribute_form = DW_FORM_string; - new_attr->ar_nbytes = strlen(current_working_directory) + 1; - new_attr->ar_next = NULL; - new_attr->ar_reloc_len = 0; - new_attr->ar_data = (char *) - _dwarf_p_get_alloc(ownerdie->di_dbg, - strlen(current_working_directory)+1); - if (new_attr->ar_data == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_STRING_ALLOC, - (Dwarf_P_Attribute) DW_DLV_BADADDR); - } - strcpy(new_attr->ar_data, current_working_directory); - - new_attr->ar_rel_type = R_MIPS_NONE; - - /* add attribute to the die */ - _dwarf_pro_add_at_to_die(ownerdie, new_attr); - return new_attr; -} - -int -_dwarf_pro_add_AT_fde(Dwarf_P_Debug dbg, - Dwarf_P_Die die, - Dwarf_Unsigned offset, Dwarf_Error * error) -{ - Dwarf_P_Attribute new_attr; - int uwordb_size = dbg->de_offset_size; - - if (die == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, -1); - } - new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(dbg,sizeof(struct Dwarf_P_Attribute_s)); - if (new_attr == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, -1); - } - - /* fill in the information */ - new_attr->ar_attribute = DW_AT_MIPS_fde; - new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form;; - new_attr->ar_rel_type = dbg->de_offset_reloc; - new_attr->ar_nbytes = uwordb_size; - new_attr->ar_next = NULL; - new_attr->ar_reloc_len = uwordb_size; - new_attr->ar_data = (char *) - _dwarf_p_get_alloc(dbg, uwordb_size); - if (new_attr->ar_data == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT); - } - { - Dwarf_Unsigned du = offset; - - WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, - (const void *) &du, sizeof(du), uwordb_size); - } - - _dwarf_pro_add_at_to_die(die, new_attr); - - return 0; -} - -int -_dwarf_pro_add_AT_macro_info(Dwarf_P_Debug dbg, - Dwarf_P_Die die, - Dwarf_Unsigned offset, Dwarf_Error * error) -{ - Dwarf_P_Attribute new_attr; - int uwordb_size = dbg->de_offset_size; - - if (die == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, -1); - } - new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(dbg,sizeof(struct Dwarf_P_Attribute_s)); - if (new_attr == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, -1); - } - - /* fill in the information */ - new_attr->ar_attribute = DW_AT_macro_info; - new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form; - new_attr->ar_rel_type = dbg->de_offset_reloc; - - new_attr->ar_nbytes = uwordb_size; - new_attr->ar_next = NULL; - new_attr->ar_reloc_len = uwordb_size; - new_attr->ar_data = (char *) - _dwarf_p_get_alloc(dbg, uwordb_size); - if (new_attr->ar_data == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT); - } - { - Dwarf_Unsigned du = offset; - - WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, - (const void *) &du, sizeof(du), uwordb_size); - } - - _dwarf_pro_add_at_to_die(die, new_attr); - - return 0; -} - - -void -_dwarf_pro_add_at_to_die(Dwarf_P_Die die, Dwarf_P_Attribute attr) -{ - if (die->di_last_attr) { - die->di_last_attr->ar_next = attr; - die->di_last_attr = attr; - die->di_n_attr++; - } else { - die->di_n_attr = 1; - die->di_attrs = die->di_last_attr = attr; - } -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_die.h b/usr/src/tools/ctf/dwarf/common/pro_die.h deleted file mode 100644 index 01c00e79bd..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_die.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - - -/* - This struct holds the abbreviation table, before they are written - on disk. Holds a linked list of abbreviations, each consisting of - a bitmap for attributes and a bitmap for forms -*/ -typedef struct Dwarf_P_Abbrev_s *Dwarf_P_Abbrev; - -struct Dwarf_P_Abbrev_s { - Dwarf_Unsigned abb_idx; /* index of abbreviation */ - Dwarf_Tag abb_tag; /* tag of die */ - Dwarf_Ubyte abb_children; /* if children are present */ - Dwarf_ufixed *abb_attrs; /* holds names of attrs */ - Dwarf_ufixed *abb_forms; /* forms of attributes */ - int abb_n_attr; /* num of attrs = # of forms */ - Dwarf_P_Abbrev abb_next; -}; - -/* used in pro_section.c */ - -int _dwarf_pro_add_AT_fde(Dwarf_P_Debug dbg, Dwarf_P_Die die, - Dwarf_Unsigned offset, Dwarf_Error * error); - -int _dwarf_pro_add_AT_stmt_list(Dwarf_P_Debug dbg, - Dwarf_P_Die first_die, - Dwarf_Error * error); - -int _dwarf_pro_add_AT_macro_info(Dwarf_P_Debug dbg, - Dwarf_P_Die first_die, - Dwarf_Unsigned offset, - Dwarf_Error * error); diff --git a/usr/src/tools/ctf/dwarf/common/pro_encode_nm.c b/usr/src/tools/ctf/dwarf/common/pro_encode_nm.c deleted file mode 100644 index d6215dc56b..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_encode_nm.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#include -#include "pro_incl.h" - -#define MORE_BYTES 0x80 -#define DATA_MASK 0x7f -#define DIGIT_WIDTH 7 -#define SIGN_BIT 0x40 - - -/*------------------------------------------------------------- - Encode val as a leb128. This encodes it as an unsigned - number. ----------------------------------------------------------------*/ -/* return DW_DLV_ERROR or DW_DLV_OK. -** space to write leb number is provided by caller, with caller -** passing length. -** number of bytes used returned thru nbytes arg -*/ -int -_dwarf_pro_encode_leb128_nm(Dwarf_Unsigned val, int *nbytes, - char *space, int splen) -{ - char *a; - char *end = space + splen; - - a = space; - do { - unsigned char uc; - - if (a >= end) { - return DW_DLV_ERROR; - } - uc = val & DATA_MASK; - val >>= DIGIT_WIDTH; - if (val != 0) { - uc |= MORE_BYTES; - } - *a = uc; - a++; - } while (val); - *nbytes = a - space; - return DW_DLV_OK; -} - -/* return DW_DLV_ERROR or DW_DLV_OK. -** space to write leb number is provided by caller, with caller -** passing length. -** number of bytes used returned thru nbytes arg -** encodes a signed number. -*/ -int -_dwarf_pro_encode_signed_leb128_nm(Dwarf_Signed value, int *nbytes, - char *space, int splen) -{ - char *str; - Dwarf_Signed sign = -(value < 0); - int more = 1; - char *end = space + splen; - - str = space; - - do { - unsigned char byte = value & DATA_MASK; - - value >>= DIGIT_WIDTH; - - if (str >= end) { - return DW_DLV_ERROR; - } - /* - * Remaining chunks would just contain the sign bit, and this chunk - * has already captured at least one sign bit. - */ - if (value == sign && ((byte & SIGN_BIT) == (sign & SIGN_BIT))) { - more = 0; - } else { - byte |= MORE_BYTES; - } - *str = byte; - str++; - } while (more); - *nbytes = str - space; - return DW_DLV_OK; -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_encode_nm.h b/usr/src/tools/ctf/dwarf/common/pro_encode_nm.h deleted file mode 100644 index d08e4d5148..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_encode_nm.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -/* Bytes needed to encode a number. - Not a tight bound, just a reasonable bound. -*/ -#define ENCODE_SPACE_NEEDED (2*sizeof(Dwarf_Unsigned)) - - -int _dwarf_pro_encode_leb128_nm(Dwarf_Unsigned val, int *nbytes, - char *space, int splen); - -int _dwarf_pro_encode_signed_leb128_nm(Dwarf_Signed value, int *nbytes, - char *space, int splen); diff --git a/usr/src/tools/ctf/dwarf/common/pro_error.c b/usr/src/tools/ctf/dwarf/common/pro_error.c deleted file mode 100644 index d408a391e2..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_error.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - - Copyright (C) 2000,2002,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#ifdef HAVE_ELF_H -#include -#endif - -#include -#include -#include -#include -#include "pro_incl.h" - -extern char *_dwarf_errmsgs[]; - -/* - This function performs error handling as described in the - libdwarf consumer document section 3. Dbg is the Dwarf_P_debug - structure being processed. Error is a pointer to the pointer - to the error descriptor that will be returned. Errval is an - error code listed in dwarf_error.h. -*/ -void -_dwarf_p_error(Dwarf_P_Debug dbg, - Dwarf_Error * error, Dwarf_Word errval) -{ - Dwarf_Error errptr; - - /* Allow NULL dbg on entry, since sometimes that can happen and we - want to report the upper-level error, not this one. */ - if ((Dwarf_Sword) errval < 0) - printf("ERROR VALUE: %ld - %s\n", - (long) errval, _dwarf_errmsgs[-errval - 1]); - if (error != NULL) { - errptr = (Dwarf_Error) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_Error_s)); - if (errptr == NULL) { - fprintf(stderr, - "Could not allocate Dwarf_Error structure\n"); - abort(); - } - errptr->er_errval = (Dwarf_Sword) errval; - *error = errptr; - return; - } - - if (dbg != NULL && dbg->de_errhand != NULL) { - errptr = (Dwarf_Error) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_Error_s)); - if (errptr == NULL) { - fprintf(stderr, - "Could not allocate Dwarf_Error structure\n"); - abort(); - } - errptr->er_errval = (Dwarf_Sword) errval; - dbg->de_errhand(errptr, dbg->de_errarg); - return; - } - - abort(); -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_error.h b/usr/src/tools/ctf/dwarf/common/pro_error.h deleted file mode 100644 index c37035301b..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_error.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - - -/* Handle error passing in the name of the Dwarf_P_Debug - User must supply {} around the macro. - Putting the {} here leads to macro uses that don't look like C. - The error argument to dwarf_error is hard coded here as 'error' -*/ -#define DWARF_P_DBG_ERROR(dbg,errval,retval) \ - _dwarf_p_error(dbg,error,errval); return(retval); - -struct Dwarf_Error_s { - Dwarf_Sword er_errval; -}; - -void _dwarf_p_error(Dwarf_P_Debug dbg, Dwarf_Error * error, - Dwarf_Word errval); diff --git a/usr/src/tools/ctf/dwarf/common/pro_expr.c b/usr/src/tools/ctf/dwarf/common/pro_expr.c deleted file mode 100644 index ad40eb762a..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_expr.c +++ /dev/null @@ -1,597 +0,0 @@ -/* - - Copyright (C) 2000,2004,2006 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#include -#include -#include -#include "pro_incl.h" -#include "pro_expr.h" - -/* - This function creates a new expression - struct that can be used to build up a - location expression. -*/ -Dwarf_P_Expr -dwarf_new_expr(Dwarf_P_Debug dbg, Dwarf_Error * error) -{ - Dwarf_P_Expr ret_expr; - - if (dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return (NULL); - } - - ret_expr = (Dwarf_P_Expr) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Expr_s)); - if (ret_expr == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (NULL); - } - - ret_expr->ex_dbg = dbg; - - return (ret_expr); -} - - -Dwarf_Unsigned -dwarf_add_expr_gen(Dwarf_P_Expr expr, - Dwarf_Small opcode, - Dwarf_Unsigned val1, - Dwarf_Unsigned val2, Dwarf_Error * error) -{ - char encode_buffer[2 * ENCODE_SPACE_NEEDED]; /* 2* since - used to - concatenate - 2 leb's - below */ - char encode_buffer2[ENCODE_SPACE_NEEDED]; - int res; - Dwarf_P_Debug dbg = expr->ex_dbg; - - /* - Give the buffer where the operands are first going to be - assembled the largest alignment. */ - Dwarf_Unsigned operand_buffer[10]; - - /* - Size of the byte stream buffer that needs to be memcpy-ed. */ - int operand_size; - - /* - Points to the byte stream for the first operand, and finally to - the buffer that is memcp-ed into the Dwarf_P_Expr_s struct. */ - Dwarf_Small *operand; - - /* Size of the byte stream for second operand. */ - int operand2_size; - - /* Points to next byte to be written in Dwarf_P_Expr_s struct. */ - Dwarf_Small *next_byte_ptr; - - /* Offset past the last byte written into Dwarf_P_Expr_s. */ - int next_byte_offset; - - /* ***** BEGIN CODE ***** */ - - if (expr == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); - return (DW_DLV_NOCOUNT); - } - - if (expr->ex_dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_NOCOUNT); - } - - operand = NULL; - operand_size = 0; - - switch (opcode) { - case DW_OP_reg0: - case DW_OP_reg1: - case DW_OP_reg2: - case DW_OP_reg3: - case DW_OP_reg4: - case DW_OP_reg5: - case DW_OP_reg6: - case DW_OP_reg7: - case DW_OP_reg8: - case DW_OP_reg9: - case DW_OP_reg10: - case DW_OP_reg11: - case DW_OP_reg12: - case DW_OP_reg13: - case DW_OP_reg14: - case DW_OP_reg15: - case DW_OP_reg16: - case DW_OP_reg17: - case DW_OP_reg18: - case DW_OP_reg19: - case DW_OP_reg20: - case DW_OP_reg21: - case DW_OP_reg22: - case DW_OP_reg23: - case DW_OP_reg24: - case DW_OP_reg25: - case DW_OP_reg26: - case DW_OP_reg27: - case DW_OP_reg28: - case DW_OP_reg29: - case DW_OP_reg30: - case DW_OP_reg31: - break; - - case DW_OP_breg0: - case DW_OP_breg1: - case DW_OP_breg2: - case DW_OP_breg3: - case DW_OP_breg4: - case DW_OP_breg5: - case DW_OP_breg6: - case DW_OP_breg7: - case DW_OP_breg8: - case DW_OP_breg9: - case DW_OP_breg10: - case DW_OP_breg11: - case DW_OP_breg12: - case DW_OP_breg13: - case DW_OP_breg14: - case DW_OP_breg15: - case DW_OP_breg16: - case DW_OP_breg17: - case DW_OP_breg18: - case DW_OP_breg19: - case DW_OP_breg20: - case DW_OP_breg21: - case DW_OP_breg22: - case DW_OP_breg23: - case DW_OP_breg24: - case DW_OP_breg25: - case DW_OP_breg26: - case DW_OP_breg27: - case DW_OP_breg28: - case DW_OP_breg29: - case DW_OP_breg30: - case DW_OP_breg31: - res = _dwarf_pro_encode_signed_leb128_nm(val1, - &operand_size, - encode_buffer, - sizeof(encode_buffer)); - if (res != DW_DLV_OK) { - _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); - return (DW_DLV_NOCOUNT); - } - operand = (Dwarf_Small *) encode_buffer; - break; - - case DW_OP_regx: - res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, - encode_buffer, - sizeof(encode_buffer)); - if (res != DW_DLV_OK) { - _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); - return (DW_DLV_NOCOUNT); - } - operand = (Dwarf_Small *) encode_buffer; - break; - - case DW_OP_lit0: - case DW_OP_lit1: - case DW_OP_lit2: - case DW_OP_lit3: - case DW_OP_lit4: - case DW_OP_lit5: - case DW_OP_lit6: - case DW_OP_lit7: - case DW_OP_lit8: - case DW_OP_lit9: - case DW_OP_lit10: - case DW_OP_lit11: - case DW_OP_lit12: - case DW_OP_lit13: - case DW_OP_lit14: - case DW_OP_lit15: - case DW_OP_lit16: - case DW_OP_lit17: - case DW_OP_lit18: - case DW_OP_lit19: - case DW_OP_lit20: - case DW_OP_lit21: - case DW_OP_lit22: - case DW_OP_lit23: - case DW_OP_lit24: - case DW_OP_lit25: - case DW_OP_lit26: - case DW_OP_lit27: - case DW_OP_lit28: - case DW_OP_lit29: - case DW_OP_lit30: - case DW_OP_lit31: - break; - - case DW_OP_addr: - _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE); - return (DW_DLV_NOCOUNT); - - case DW_OP_const1u: - case DW_OP_const1s: - operand = (Dwarf_Small *) & operand_buffer[0]; - WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 1); - operand_size = 1; - break; - - case DW_OP_const2u: - case DW_OP_const2s: - operand = (Dwarf_Small *) & operand_buffer[0]; - WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 2); - operand_size = 2; - break; - - case DW_OP_const4u: - case DW_OP_const4s: - operand = (Dwarf_Small *) & operand_buffer[0]; - WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 4); - operand_size = 4; - break; - - case DW_OP_const8u: - case DW_OP_const8s: - operand = (Dwarf_Small *) & operand_buffer[0]; - WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 8); - operand_size = 8; - break; - - case DW_OP_constu: - res = _dwarf_pro_encode_leb128_nm(val1, - &operand_size, - encode_buffer, - sizeof(encode_buffer)); - if (res != DW_DLV_OK) { - _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); - return (DW_DLV_NOCOUNT); - } - operand = (Dwarf_Small *) encode_buffer; - break; - - case DW_OP_consts: - res = _dwarf_pro_encode_signed_leb128_nm(val1, - &operand_size, - encode_buffer, - sizeof(encode_buffer)); - if (res != DW_DLV_OK) { - _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); - return (DW_DLV_NOCOUNT); - } - operand = (Dwarf_Small *) encode_buffer; - break; - - case DW_OP_fbreg: - res = _dwarf_pro_encode_signed_leb128_nm(val1, - &operand_size, - encode_buffer, - sizeof(encode_buffer)); - if (res != DW_DLV_OK) { - _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); - return (DW_DLV_NOCOUNT); - } - operand = (Dwarf_Small *) encode_buffer; - break; - - case DW_OP_bregx: - res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, - encode_buffer, - sizeof(encode_buffer)); - if (res != DW_DLV_OK) { - _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); - return (DW_DLV_NOCOUNT); - } - operand = (Dwarf_Small *) encode_buffer; - /* put this one directly into 'operand' at tail of prev value */ - res = _dwarf_pro_encode_signed_leb128_nm(val2, &operand2_size, - ((char *) operand) + - operand_size, - sizeof - (encode_buffer2)); - if (res != DW_DLV_OK) { - _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); - return (DW_DLV_NOCOUNT); - } - operand_size += operand2_size; - - case DW_OP_dup: - case DW_OP_drop: - break; - - case DW_OP_pick: - operand = (Dwarf_Small *) & operand_buffer[0]; - WRITE_UNALIGNED(dbg, operand, (const void *) &val1, - sizeof(val1), 1); - operand_size = 1; - break; - - case DW_OP_over: - case DW_OP_swap: - case DW_OP_rot: - case DW_OP_deref: - case DW_OP_xderef: - break; - - case DW_OP_deref_size: - case DW_OP_xderef_size: - operand = (Dwarf_Small *) & operand_buffer[0]; - WRITE_UNALIGNED(dbg, operand, (const void *) &val1, - sizeof(val1), 1); - operand_size = 1; - break; - - case DW_OP_abs: - case DW_OP_and: - case DW_OP_div: - case DW_OP_minus: - case DW_OP_mod: - case DW_OP_mul: - case DW_OP_neg: - case DW_OP_not: - case DW_OP_or: - case DW_OP_plus: - break; - - case DW_OP_plus_uconst: - res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, - encode_buffer, - sizeof(encode_buffer)); - if (res != DW_DLV_OK) { - _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); - return (DW_DLV_NOCOUNT); - } - operand = (Dwarf_Small *) encode_buffer; - break; - - case DW_OP_shl: - case DW_OP_shr: - case DW_OP_shra: - case DW_OP_xor: - break; - - case DW_OP_le: - case DW_OP_ge: - case DW_OP_eq: - case DW_OP_lt: - case DW_OP_gt: - case DW_OP_ne: - break; - - case DW_OP_skip: - case DW_OP_bra: - /* FIX: unhandled! OP_bra, OP_skip! */ - _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE); - return (DW_DLV_NOCOUNT); - - case DW_OP_piece: - res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, - encode_buffer, - sizeof(encode_buffer)); - if (res != DW_DLV_OK) { - _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); - return (DW_DLV_NOCOUNT); - } - operand = (Dwarf_Small *) encode_buffer; - break; - - case DW_OP_nop: - break; - case DW_OP_push_object_address: /* DWARF3 */ - break; - case DW_OP_call2: /* DWARF3 */ - operand = (Dwarf_Small *) & operand_buffer[0]; - WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 2); - operand_size = 2; - break; - - case DW_OP_call4: /* DWARF3 */ - operand = (Dwarf_Small *) & operand_buffer[0]; - WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 4); - operand_size = 4; - break; - - case DW_OP_call_ref: /* DWARF3 */ - operand = (Dwarf_Small *) & operand_buffer[0]; - WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), - dbg->de_offset_size); - operand_size = dbg->de_offset_size; - break; - case DW_OP_form_tls_address: /* DWARF3f */ - break; - case DW_OP_call_frame_cfa: /* DWARF3f */ - break; - case DW_OP_bit_piece: /* DWARF3f */ - res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, - encode_buffer, - sizeof(encode_buffer)); - if (res != DW_DLV_OK) { - _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); - return (DW_DLV_NOCOUNT); - } - operand = (Dwarf_Small *) encode_buffer; - /* put this one directly into 'operand' at tail of prev value */ - res = _dwarf_pro_encode_leb128_nm(val2, &operand2_size, - ((char *) operand) + - operand_size, - sizeof(encode_buffer2)); - if (res != DW_DLV_OK) { - _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); - return (DW_DLV_NOCOUNT); - } - operand_size += operand2_size; - break; - - default: - _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE); - return (DW_DLV_NOCOUNT); - } - - next_byte_offset = expr->ex_next_byte_offset + operand_size + 1; - - if (next_byte_offset > MAXIMUM_LOC_EXPR_LENGTH) { - _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); - return (DW_DLV_NOCOUNT); - } - - next_byte_ptr = - &(expr->ex_byte_stream[0]) + expr->ex_next_byte_offset; - - *next_byte_ptr = opcode; - next_byte_ptr++; - memcpy(next_byte_ptr, operand, operand_size); - - expr->ex_next_byte_offset = next_byte_offset; - return (next_byte_offset); -} - -Dwarf_Unsigned -dwarf_add_expr_addr_b(Dwarf_P_Expr expr, - Dwarf_Unsigned addr, - Dwarf_Unsigned sym_index, Dwarf_Error * error) -{ - Dwarf_P_Debug dbg; - Dwarf_Small *next_byte_ptr; - Dwarf_Unsigned next_byte_offset; - int upointer_size; - - if (expr == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); - return (DW_DLV_NOCOUNT); - } - - dbg = expr->ex_dbg; - if (dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_NOCOUNT); - } - - upointer_size = dbg->de_pointer_size; - next_byte_offset = expr->ex_next_byte_offset + upointer_size + 1; - if (next_byte_offset > MAXIMUM_LOC_EXPR_LENGTH) { - _dwarf_p_error(dbg, error, DW_DLE_EXPR_LENGTH_BAD); - return (DW_DLV_NOCOUNT); - } - - next_byte_ptr = - &(expr->ex_byte_stream[0]) + expr->ex_next_byte_offset; - - *next_byte_ptr = DW_OP_addr; - next_byte_ptr++; - WRITE_UNALIGNED(dbg, next_byte_ptr, (const void *) &addr, - sizeof(addr), upointer_size); - - if (expr->ex_reloc_offset != 0) { - _dwarf_p_error(dbg, error, DW_DLE_MULTIPLE_RELOC_IN_EXPR); - return (DW_DLV_NOCOUNT); - } - - expr->ex_reloc_sym_index = sym_index; - expr->ex_reloc_offset = expr->ex_next_byte_offset + 1; - - expr->ex_next_byte_offset = next_byte_offset; - return (next_byte_offset); -} - -Dwarf_Unsigned -dwarf_add_expr_addr(Dwarf_P_Expr expr, - Dwarf_Unsigned addr, - Dwarf_Signed sym_index, Dwarf_Error * error) -{ - return - dwarf_add_expr_addr_b(expr, addr, (Dwarf_Unsigned) sym_index, - error); -} - - -Dwarf_Unsigned -dwarf_expr_current_offset(Dwarf_P_Expr expr, Dwarf_Error * error) -{ - if (expr == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); - return (DW_DLV_NOCOUNT); - } - - if (expr->ex_dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_NOCOUNT); - } - - return (expr->ex_next_byte_offset); -} - -void -dwarf_expr_reset(Dwarf_P_Expr expr, Dwarf_Error * error) -{ - if (expr == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); - return; - } - expr->ex_next_byte_offset=0; -} - - -Dwarf_Addr -dwarf_expr_into_block(Dwarf_P_Expr expr, - Dwarf_Unsigned * length, Dwarf_Error * error) -{ - if (expr == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); - return (DW_DLV_BADADDR); - } - - if (expr->ex_dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_BADADDR); - } - - if (length != NULL) - *length = expr->ex_next_byte_offset; - /* The following cast from pointer to integer is ok as long as - Dwarf_Addr is at least as large as a pointer. Which is a - requirement of libdwarf so must be satisfied (some compilers - emit a warning about the following line). */ - return ((Dwarf_Addr)(uintptr_t) &(expr->ex_byte_stream[0])); -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_expr.h b/usr/src/tools/ctf/dwarf/common/pro_expr.h deleted file mode 100644 index 202f2d30d5..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_expr.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - -#define MAXIMUM_LOC_EXPR_LENGTH 20 - -struct Dwarf_P_Expr_s { - Dwarf_Small ex_byte_stream[MAXIMUM_LOC_EXPR_LENGTH]; - Dwarf_P_Debug ex_dbg; - Dwarf_Unsigned ex_next_byte_offset; - Dwarf_Unsigned ex_reloc_sym_index; - Dwarf_Unsigned ex_reloc_offset; -}; diff --git a/usr/src/tools/ctf/dwarf/common/pro_finish.c b/usr/src/tools/ctf/dwarf/common/pro_finish.c deleted file mode 100644 index bc43a5f0f4..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_finish.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#include "pro_incl.h" - -/*--------------------------------------------------------------- - This routine deallocates all memory, and does some - finishing up ------------------------------------------------------------------*/ - /*ARGSUSED*/ Dwarf_Unsigned -dwarf_producer_finish(Dwarf_P_Debug dbg, Dwarf_Error * error) -{ - if (dbg->de_version_magic_number != PRO_VERSION_MAGIC) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, DW_DLV_NOCOUNT); - } - - /* this frees all blocks, then frees dbg. */ - _dwarf_p_dealloc_all(dbg); - return 0; -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_forms.c b/usr/src/tools/ctf/dwarf/common/pro_forms.c deleted file mode 100644 index fec9a39c60..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_forms.c +++ /dev/null @@ -1,1182 +0,0 @@ -/* - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. - Portions Copyright 2007-2010 David Anderson. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#include -#include -#include -#include "pro_incl.h" -#include "pro_expr.h" - -#ifndef R_MIPS_NONE -#define R_MIPS_NONE 0 -#endif - - - /* Indicates no relocation needed. */ -#define NO_ELF_SYM_INDEX 0 - - -/* adds an attribute to a die */ -extern void _dwarf_pro_add_at_to_die(Dwarf_P_Die die, - Dwarf_P_Attribute attr); - -/* - This function adds an attribute whose value is - a target address to the given die. The attribute - is given the name provided by attr. The address - is given in pc_value. -*/ - -static Dwarf_P_Attribute -local_add_AT_address(Dwarf_P_Debug dbg, - Dwarf_P_Die ownerdie, - Dwarf_Half attr, - Dwarf_Signed form, - Dwarf_Unsigned pc_value, - Dwarf_Unsigned sym_index, - Dwarf_Error * error); - -/* old interface */ -Dwarf_P_Attribute -dwarf_add_AT_targ_address(Dwarf_P_Debug dbg, - Dwarf_P_Die ownerdie, - Dwarf_Half attr, - Dwarf_Unsigned pc_value, - Dwarf_Signed sym_index, Dwarf_Error * error) -{ - return - dwarf_add_AT_targ_address_b(dbg, - ownerdie, - attr, - pc_value, - (Dwarf_Unsigned) sym_index, error); -} - -/* New interface, replacing dwarf_add_AT_targ_address. - Essentially just makes sym_index a Dwarf_Unsigned - so for symbolic relocations it can be a full address. -*/ -Dwarf_P_Attribute -dwarf_add_AT_targ_address_b(Dwarf_P_Debug dbg, - Dwarf_P_Die ownerdie, - Dwarf_Half attr, - Dwarf_Unsigned pc_value, - Dwarf_Unsigned sym_index, - Dwarf_Error * error) -{ - switch (attr) { - case DW_AT_low_pc: - case DW_AT_high_pc: - - /* added to support location lists */ - /* no way to check that this is a loclist-style address though */ - case DW_AT_location: - case DW_AT_string_length: - case DW_AT_return_addr: - case DW_AT_frame_base: - case DW_AT_segment: - case DW_AT_static_link: - case DW_AT_use_location: - case DW_AT_vtable_elem_location: - case DW_AT_const_value: /* Gcc can generate this as address. */ - case DW_AT_entry_pc: - break; - default: - if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) { - _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - break; - } - - return local_add_AT_address(dbg, ownerdie, attr, DW_FORM_addr, - pc_value, sym_index, error); -} - -Dwarf_P_Attribute -dwarf_add_AT_ref_address(Dwarf_P_Debug dbg, - Dwarf_P_Die ownerdie, - Dwarf_Half attr, - Dwarf_Unsigned pc_value, - Dwarf_Unsigned sym_index, - Dwarf_Error * error) -{ - switch (attr) { - case DW_AT_type: - case DW_AT_import: - break; - - default: - if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) { - _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - break; - } - - return local_add_AT_address(dbg, ownerdie, attr, DW_FORM_ref_addr, - pc_value, sym_index, error); -} - - -/* Make sure attribute types are checked before entering here. */ -static Dwarf_P_Attribute -local_add_AT_address(Dwarf_P_Debug dbg, - Dwarf_P_Die ownerdie, - Dwarf_Half attr, - Dwarf_Signed form, - Dwarf_Unsigned pc_value, - Dwarf_Unsigned sym_index, - Dwarf_Error * error) -{ - Dwarf_P_Attribute new_attr; - int upointer_size = dbg->de_pointer_size; - - if (dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - if (ownerdie == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - /* attribute types have already been checked */ - /* switch (attr) { ... } */ - - new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); - if (new_attr == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - new_attr->ar_attribute = attr; - new_attr->ar_attribute_form = form; - new_attr->ar_nbytes = upointer_size; - new_attr->ar_rel_symidx = sym_index; - new_attr->ar_reloc_len = upointer_size; - new_attr->ar_next = 0; - if (sym_index != NO_ELF_SYM_INDEX) - new_attr->ar_rel_type = dbg->de_ptr_reloc; - else - new_attr->ar_rel_type = R_MIPS_NONE; - - new_attr->ar_data = (char *) - _dwarf_p_get_alloc(dbg, upointer_size); - if (new_attr->ar_data == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - WRITE_UNALIGNED(dbg, new_attr->ar_data, - (const void *) &pc_value, - sizeof(pc_value), upointer_size); - - /* add attribute to the die */ - _dwarf_pro_add_at_to_die(ownerdie, new_attr); - return new_attr; -} - -/* - * Functions to compress and uncompress data from normal - * arrays of integral types into arrays of LEB128 numbers. - * Extend these functions as needed to handle wider input - * variety. Return values should be freed with _dwarf_p_dealloc - * after they aren't needed any more. - */ - -/* return value points to an array of LEB number */ - -void * -dwarf_compress_integer_block( - Dwarf_P_Debug dbg, - Dwarf_Bool unit_is_signed, - Dwarf_Small unit_length_in_bits, - void* input_block, - Dwarf_Unsigned input_length_in_units, - Dwarf_Unsigned* output_length_in_bytes_ptr, - Dwarf_Error* error -) -{ - Dwarf_Unsigned output_length_in_bytes = 0; - char * output_block = 0; - char encode_buffer[ENCODE_SPACE_NEEDED]; - int i = 0; - char * ptr = 0; - int remain = 0; - int result = 0; - - if (dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return((void *)DW_DLV_BADADDR); - } - - if (unit_is_signed == false || - unit_length_in_bits != 32 || - input_block == NULL || - input_length_in_units == 0 || - output_length_in_bytes_ptr == NULL) { - - _dwarf_p_error(NULL, error, DW_DLE_BADBITC); - return ((void *) DW_DLV_BADADDR); - } - - /* At this point we assume the format is: signed 32 bit */ - - /* first compress everything to find the total size. */ - - output_length_in_bytes = 0; - for (i=0; ide_ar_data_attribute_form is data4 or data8 - and dwarf4 changes the definition for such on DW_AT_high_pc. - DWARF 3: the FORM here has no defined meaning for dwarf3. - DWARF 4: the FORM here means that for DW_AT_high_pc the value - is not a high address but is instead an offset - from a (separate) DW_AT_low_pc. - The intent for DWARF4 is that this is not a relocated - address at all. Instead a simple offset. - But this should NOT be called for a simple non-relocated offset. - So do not call this with an attr of DW_AT_high_pc. - Use dwarf_add_AT_unsigned_const() (for example) instead of - dwarf_add_AT_dataref when the value is a simple offset . -*/ -Dwarf_P_Attribute -dwarf_add_AT_dataref( - Dwarf_P_Debug dbg, - Dwarf_P_Die ownerdie, - Dwarf_Half attr, - Dwarf_Unsigned pc_value, - Dwarf_Unsigned sym_index, - Dwarf_Error * error) -{ - /* TODO: Add checking here */ - return local_add_AT_address(dbg, ownerdie, attr, - dbg->de_ar_data_attribute_form, - pc_value, - sym_index, - error); -} - - - -Dwarf_P_Attribute -dwarf_add_AT_block( - Dwarf_P_Debug dbg, - Dwarf_P_Die ownerdie, - Dwarf_Half attr, - Dwarf_Small *block_data, - Dwarf_Unsigned block_size, - Dwarf_Error *error -) -{ - Dwarf_P_Attribute new_attr; - int result; - char encode_buffer[ENCODE_SPACE_NEEDED]; - int len_size; - char * attrdata; - - if (dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return((Dwarf_P_Attribute)DW_DLV_BADADDR); - } - - if (ownerdie == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); - return((Dwarf_P_Attribute)DW_DLV_BADADDR); - } - - /* I don't mess with block1, block2, block4, not worth the effort */ - - /* So, encode the length into LEB128 */ - result = _dwarf_pro_encode_leb128_nm(block_size, &len_size, - encode_buffer,sizeof(encode_buffer)); - if (result != DW_DLV_OK) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return((Dwarf_P_Attribute)DW_DLV_BADADDR); - } - - /* Allocate the new attribute */ - new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); - if (new_attr == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return((Dwarf_P_Attribute)DW_DLV_BADADDR); - } - - /* Fill in the attribute */ - new_attr->ar_attribute = attr; - new_attr->ar_attribute_form = DW_FORM_block; - new_attr->ar_nbytes = len_size + block_size; - new_attr->ar_next = 0; - - new_attr->ar_data = attrdata = (char *) - _dwarf_p_get_alloc(dbg, len_size + block_size); - if (new_attr->ar_data == NULL) { - /* free the block we got earlier */ - _dwarf_p_dealloc(dbg, (unsigned char *) new_attr); - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return((Dwarf_P_Attribute)DW_DLV_BADADDR); - } - - /* write length and data to attribute data buffer */ - memcpy(attrdata, encode_buffer, len_size); - attrdata += len_size; - memcpy(attrdata, block_data, block_size); - - /* add attribute to the die */ - _dwarf_pro_add_at_to_die(ownerdie, new_attr); - - return new_attr; -} - - -/* - This function adds attributes whose value - is an unsigned constant. It determines the - size of the value field from the value of - the constant. -*/ -Dwarf_P_Attribute -dwarf_add_AT_unsigned_const(Dwarf_P_Debug dbg, - Dwarf_P_Die ownerdie, - Dwarf_Half attr, - Dwarf_Unsigned value, Dwarf_Error * error) -{ - Dwarf_P_Attribute new_attr; - Dwarf_Half attr_form; - Dwarf_Small size; - - if (dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - if (ownerdie == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - switch (attr) { - case DW_AT_ordering: - case DW_AT_byte_size: - case DW_AT_bit_offset: - case DW_AT_bit_size: - case DW_AT_inline: - case DW_AT_language: - case DW_AT_visibility: - case DW_AT_virtuality: - case DW_AT_accessibility: - case DW_AT_address_class: - case DW_AT_calling_convention: - case DW_AT_encoding: - case DW_AT_identifier_case: - case DW_AT_MIPS_loop_unroll_factor: - case DW_AT_MIPS_software_pipeline_depth: - break; - - case DW_AT_decl_column: - case DW_AT_decl_file: - case DW_AT_decl_line: - case DW_AT_const_value: - case DW_AT_start_scope: - case DW_AT_stride_size: - case DW_AT_count: - case DW_AT_associated: - case DW_AT_allocated: - case DW_AT_upper_bound: - case DW_AT_lower_bound: - case DW_AT_call_file: - case DW_AT_call_line: - break; - - default: { - if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) { - _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - break; - } - } - - /* - Compute the number of bytes needed to hold constant. */ - if (value <= UCHAR_MAX) { - attr_form = DW_FORM_data1; - size = 1; - } else if (value <= USHRT_MAX) { - attr_form = DW_FORM_data2; - size = 2; - } else if (value <= UINT_MAX) { - attr_form = DW_FORM_data4; - size = 4; - } else { - attr_form = DW_FORM_data8; - size = 8; - } - - new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); - if (new_attr == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - new_attr->ar_attribute = attr; - new_attr->ar_attribute_form = attr_form; - new_attr->ar_rel_type = R_MIPS_NONE; - new_attr->ar_reloc_len = 0; /* irrelevant: unused with R_MIPS_NONE */ - new_attr->ar_nbytes = size; - new_attr->ar_next = 0; - - new_attr->ar_data = (char *) - _dwarf_p_get_alloc(dbg, size); - if (new_attr->ar_data == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - WRITE_UNALIGNED(dbg, new_attr->ar_data, - (const void *) &value, sizeof(value), size); - - /* add attribute to the die */ - _dwarf_pro_add_at_to_die(ownerdie, new_attr); - return new_attr; -} - - -/* - This function adds attributes whose value - is an signed constant. It determines the - size of the value field from the value of - the constant. -*/ -Dwarf_P_Attribute -dwarf_add_AT_signed_const(Dwarf_P_Debug dbg, - Dwarf_P_Die ownerdie, - Dwarf_Half attr, - Dwarf_Signed value, Dwarf_Error * error) -{ - Dwarf_P_Attribute new_attr; - Dwarf_Half attr_form; - Dwarf_Small size; - - if (dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - if (ownerdie == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - switch (attr) { - case DW_AT_lower_bound: - case DW_AT_upper_bound: - case DW_AT_const_value: - case DW_AT_bit_offset: - case DW_AT_bit_size: - case DW_AT_byte_size: - case DW_AT_count: - case DW_AT_byte_stride: - case DW_AT_bit_stride: - case DW_AT_allocated: - case DW_AT_associated: - break; - - default:{ - if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) { - _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - } - break; - } - - /* - Compute the number of bytes needed to hold constant. */ - if (value >= SCHAR_MIN && value <= SCHAR_MAX) { - attr_form = DW_FORM_data1; - size = 1; - } else if (value >= SHRT_MIN && value <= SHRT_MAX) { - attr_form = DW_FORM_data2; - size = 2; - } else if (value >= INT_MIN && value <= INT_MAX) { - attr_form = DW_FORM_data4; - size = 4; - } else { - attr_form = DW_FORM_data8; - size = 8; - } - - new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); - if (new_attr == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - new_attr->ar_attribute = attr; - new_attr->ar_attribute_form = attr_form; - new_attr->ar_rel_type = R_MIPS_NONE; - new_attr->ar_reloc_len = 0; /* irrelevant: unused with R_MIPS_NONE */ - new_attr->ar_nbytes = size; - new_attr->ar_next = 0; - - new_attr->ar_data = (char *) - _dwarf_p_get_alloc(dbg, size); - if (new_attr->ar_data == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - WRITE_UNALIGNED(dbg, new_attr->ar_data, - (const void *) &value, sizeof(value), size); - - /* add attribute to the die */ - _dwarf_pro_add_at_to_die(ownerdie, new_attr); - return new_attr; -} - - -/* - This function adds attributes whose value - is a location expression. -*/ -Dwarf_P_Attribute -dwarf_add_AT_location_expr(Dwarf_P_Debug dbg, - Dwarf_P_Die ownerdie, - Dwarf_Half attr, - Dwarf_P_Expr loc_expr, Dwarf_Error * error) -{ - char encode_buffer[ENCODE_SPACE_NEEDED]; - int res; - Dwarf_P_Attribute new_attr; - Dwarf_Half attr_form; - char *len_str = 0; - int len_size; - int block_size; - char *block_dest_ptr; - int do_len_as_int = 0; - - if (dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - if (ownerdie == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - if (loc_expr == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_EXPR_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - if (loc_expr->ex_dbg != dbg) { - _dwarf_p_error(dbg, error, DW_DLE_LOC_EXPR_BAD); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - block_size = loc_expr->ex_next_byte_offset; - - switch (attr) { - case DW_AT_location: - case DW_AT_string_length: - case DW_AT_const_value: - case DW_AT_use_location: - case DW_AT_return_addr: - case DW_AT_data_member_location: - case DW_AT_frame_base: - case DW_AT_static_link: - case DW_AT_vtable_elem_location: - case DW_AT_lower_bound: - case DW_AT_upper_bound: - case DW_AT_count: - case DW_AT_associated: - case DW_AT_allocated: - case DW_AT_data_location: - case DW_AT_byte_stride: - case DW_AT_bit_stride: - case DW_AT_byte_size: - case DW_AT_bit_size: - break; - - default: - if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) { - _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - break; - } - - /* - Compute the number of bytes needed to hold constant. */ - if (block_size <= UCHAR_MAX) { - attr_form = DW_FORM_block1; - len_size = 1; - do_len_as_int = 1; - } else if (block_size <= USHRT_MAX) { - attr_form = DW_FORM_block2; - len_size = 2; - do_len_as_int = 1; - } else if (block_size <= UINT_MAX) { - attr_form = DW_FORM_block4; - len_size = 4; - do_len_as_int = 1; - } else { - attr_form = DW_FORM_block; - res = _dwarf_pro_encode_leb128_nm(block_size, &len_size, - encode_buffer, - sizeof(encode_buffer)); - if (res != DW_DLV_OK) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - len_str = (char *) encode_buffer; - } - - new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); - if (new_attr == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - new_attr->ar_attribute = attr; - new_attr->ar_attribute_form = attr_form; - new_attr->ar_reloc_len = dbg->de_pointer_size; - if (loc_expr->ex_reloc_sym_index != NO_ELF_SYM_INDEX) { - new_attr->ar_rel_type = dbg->de_ptr_reloc; - } else { - new_attr->ar_rel_type = R_MIPS_NONE; - } - new_attr->ar_rel_symidx = loc_expr->ex_reloc_sym_index; - new_attr->ar_rel_offset = - (Dwarf_Word) loc_expr->ex_reloc_offset + len_size; - - new_attr->ar_nbytes = block_size + len_size; - - new_attr->ar_next = 0; - new_attr->ar_data = block_dest_ptr = - (char *) _dwarf_p_get_alloc(dbg, block_size + len_size); - if (new_attr->ar_data == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - if (do_len_as_int) { - WRITE_UNALIGNED(dbg, block_dest_ptr, (const void *) &block_size, - sizeof(block_size), len_size); - } else { - /* Is uleb number form, DW_FORM_block. See above. */ - memcpy(block_dest_ptr, len_str, len_size); - } - block_dest_ptr += len_size; - memcpy(block_dest_ptr, &(loc_expr->ex_byte_stream[0]), block_size); - - /* add attribute to the die */ - _dwarf_pro_add_at_to_die(ownerdie, new_attr); - return new_attr; -} - - -/* - This function adds attributes of reference class. - The references here are local CU references, - not DW_FORM_ref_addr. - The offset field is 4 bytes for 32-bit objects, - and 8-bytes for 64-bit objects. Otherdie is the - that is referenced by ownerdie. - - For reference attributes, the ar_data and ar_nbytes - are not needed. Instead, the ar_ref_die points to - the other die, and its di_offset value is used as - the reference value. -*/ -Dwarf_P_Attribute -dwarf_add_AT_reference(Dwarf_P_Debug dbg, - Dwarf_P_Die ownerdie, - Dwarf_Half attr, - Dwarf_P_Die otherdie, Dwarf_Error * error) -{ - Dwarf_P_Attribute new_attr; - - if (dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - if (ownerdie == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - if (otherdie == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - switch (attr) { - case DW_AT_specification: - case DW_AT_discr: - case DW_AT_common_reference: - case DW_AT_import: - case DW_AT_containing_type: - case DW_AT_default_value: - case DW_AT_abstract_origin: - case DW_AT_friend: - case DW_AT_priority: - case DW_AT_type: - case DW_AT_lower_bound: - case DW_AT_upper_bound: - case DW_AT_count: - case DW_AT_associated: - case DW_AT_allocated: - case DW_AT_bit_offset: - case DW_AT_bit_size: - case DW_AT_byte_size: - case DW_AT_sibling: - case DW_AT_bit_stride: - case DW_AT_byte_stride: - case DW_AT_namelist_item: - break; - - default: - if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) { - _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - break; - } - - new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); - if (new_attr == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - new_attr->ar_attribute = attr; - new_attr->ar_attribute_form = dbg->de_ar_ref_attr_form; - new_attr->ar_nbytes = dbg->de_offset_size; - new_attr->ar_reloc_len = dbg->de_offset_size; - new_attr->ar_ref_die = otherdie; - new_attr->ar_rel_type = R_MIPS_NONE; - new_attr->ar_next = 0; - - /* add attribute to the die */ - _dwarf_pro_add_at_to_die(ownerdie, new_attr); - return new_attr; -} - - -/* - This function adds attributes of the flag class. -*/ -Dwarf_P_Attribute -dwarf_add_AT_flag(Dwarf_P_Debug dbg, - Dwarf_P_Die ownerdie, - Dwarf_Half attr, - Dwarf_Small flag, Dwarf_Error * error) -{ - Dwarf_P_Attribute new_attr; - - if (dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - if (ownerdie == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - -#if 0 - switch (attr) { - case DW_AT_is_optional: - case DW_AT_artificial: - case DW_AT_declaration: - case DW_AT_external: - case DW_AT_prototyped: - case DW_AT_variable_parameter: - break; - - default: - if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) { - _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - break; - } -#endif - - new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); - if (new_attr == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - new_attr->ar_attribute = attr; - new_attr->ar_attribute_form = DW_FORM_flag; - new_attr->ar_nbytes = 1; - new_attr->ar_reloc_len = 0; /* not used */ - new_attr->ar_rel_type = R_MIPS_NONE; - new_attr->ar_next = 0; - - new_attr->ar_data = (char *) - _dwarf_p_get_alloc(dbg, 1); - if (new_attr->ar_data == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - memcpy(new_attr->ar_data, &flag, 1); - - /* add attribute to the die */ - _dwarf_pro_add_at_to_die(ownerdie, new_attr); - return new_attr; -} - - -/* - This function adds values of attributes - belonging to the string class. -*/ -Dwarf_P_Attribute -dwarf_add_AT_string(Dwarf_P_Debug dbg, - Dwarf_P_Die ownerdie, - Dwarf_Half attr, char *string, Dwarf_Error * error) -{ - Dwarf_P_Attribute new_attr; - - if (dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - if (ownerdie == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); - if (new_attr == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - switch (attr) { - case DW_AT_name: - case DW_AT_comp_dir: - case DW_AT_const_value: - case DW_AT_producer: - break; - - default: - if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) { - _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - break; - } - - new_attr->ar_attribute = attr; - new_attr->ar_attribute_form = DW_FORM_string; - new_attr->ar_nbytes = strlen(string) + 1; - new_attr->ar_next = 0; - - new_attr->ar_data = - (char *) _dwarf_p_get_alloc(dbg, strlen(string)+1); - if (new_attr->ar_data == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - strcpy(new_attr->ar_data, string); - new_attr->ar_rel_type = R_MIPS_NONE; - new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */ - - /* add attribute to the die */ - _dwarf_pro_add_at_to_die(ownerdie, new_attr); - return new_attr; -} - - -Dwarf_P_Attribute -dwarf_add_AT_const_value_string(Dwarf_P_Die ownerdie, - char *string_value, Dwarf_Error * error) -{ - Dwarf_P_Attribute new_attr; - - if (ownerdie == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s)); - if (new_attr == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - new_attr->ar_attribute = DW_AT_const_value; - new_attr->ar_attribute_form = DW_FORM_string; - new_attr->ar_nbytes = strlen(string_value) + 1; - new_attr->ar_next = 0; - - new_attr->ar_data = - (char *) _dwarf_p_get_alloc(ownerdie->di_dbg, strlen(string_value)+1); - if (new_attr->ar_data == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - strcpy(new_attr->ar_data, string_value); - new_attr->ar_rel_type = R_MIPS_NONE; - new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */ - - /* add attribute to the die */ - _dwarf_pro_add_at_to_die(ownerdie, new_attr); - return new_attr; -} - - -Dwarf_P_Attribute -dwarf_add_AT_producer(Dwarf_P_Die ownerdie, - char *producer_string, Dwarf_Error * error) -{ - Dwarf_P_Attribute new_attr; - - if (ownerdie == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s)); - if (new_attr == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - new_attr->ar_attribute = DW_AT_producer; - new_attr->ar_attribute_form = DW_FORM_string; - new_attr->ar_nbytes = strlen(producer_string) + 1; - new_attr->ar_next = 0; - - new_attr->ar_data = - (char *) _dwarf_p_get_alloc(ownerdie->di_dbg, strlen(producer_string)+1); - if (new_attr->ar_data == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - strcpy(new_attr->ar_data, producer_string); - new_attr->ar_rel_type = R_MIPS_NONE; - new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */ - - /* add attribute to the die */ - _dwarf_pro_add_at_to_die(ownerdie, new_attr); - return new_attr; -} - - -Dwarf_P_Attribute -dwarf_add_AT_const_value_signedint(Dwarf_P_Die ownerdie, - Dwarf_Signed signed_value, - Dwarf_Error * error) -{ - Dwarf_P_Attribute new_attr; - int leb_size; - char encode_buffer[ENCODE_SPACE_NEEDED]; - int res; - - if (ownerdie == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s)); - if (new_attr == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - new_attr->ar_attribute = DW_AT_const_value; - new_attr->ar_attribute_form = DW_FORM_sdata; - new_attr->ar_rel_type = R_MIPS_NONE; - new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */ - new_attr->ar_next = 0; - - res = _dwarf_pro_encode_signed_leb128_nm(signed_value, &leb_size, - encode_buffer, - sizeof(encode_buffer)); - if (res != DW_DLV_OK) { - _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - new_attr->ar_data = (char *) - _dwarf_p_get_alloc(ownerdie->di_dbg, leb_size); - if (new_attr->ar_data == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - memcpy(new_attr->ar_data, encode_buffer, leb_size); - new_attr->ar_nbytes = leb_size; - - /* add attribute to the die */ - _dwarf_pro_add_at_to_die(ownerdie, new_attr); - return new_attr; -} - - -Dwarf_P_Attribute -dwarf_add_AT_const_value_unsignedint(Dwarf_P_Die ownerdie, - Dwarf_Unsigned unsigned_value, - Dwarf_Error * error) -{ - Dwarf_P_Attribute new_attr; - int leb_size; - char encode_buffer[ENCODE_SPACE_NEEDED]; - int res; - - if (ownerdie == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s)); - if (new_attr == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - - new_attr->ar_attribute = DW_AT_const_value; - new_attr->ar_attribute_form = DW_FORM_udata; - new_attr->ar_rel_type = R_MIPS_NONE; - new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */ - new_attr->ar_next = 0; - - res = _dwarf_pro_encode_leb128_nm(unsigned_value, &leb_size, - encode_buffer, - sizeof(encode_buffer)); - if (res != DW_DLV_OK) { - _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - new_attr->ar_data = (char *) - _dwarf_p_get_alloc(ownerdie->di_dbg, leb_size); - if (new_attr->ar_data == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); - return ((Dwarf_P_Attribute) DW_DLV_BADADDR); - } - memcpy(new_attr->ar_data, encode_buffer, leb_size); - new_attr->ar_nbytes = leb_size; - - /* add attribute to the die */ - _dwarf_pro_add_at_to_die(ownerdie, new_attr); - return new_attr; -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_frame.c b/usr/src/tools/ctf/dwarf/common/pro_frame.c deleted file mode 100644 index bd1ef6a637..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_frame.c +++ /dev/null @@ -1,598 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#include -#include -#include -#include "pro_incl.h" -#include "pro_frame.h" - -static void _dwarf_pro_add_to_fde(Dwarf_P_Fde fde, - Dwarf_P_Frame_Pgm inst); - -/*------------------------------------------------------------------------- - This function adds a cie struct to the debug pointer. Its in the - form of a linked list. - augmenter: string reps augmentation (implementation defined) - code_align: alignment of code - data_align: alignment of data - init_bytes: byts having initial instructions - init_n_bytes: number of bytes of initial instructions ---------------------------------------------------------------------------*/ -Dwarf_Unsigned -dwarf_add_frame_cie(Dwarf_P_Debug dbg, - char *augmenter, - Dwarf_Small code_align, - Dwarf_Small data_align, - Dwarf_Small return_reg, - Dwarf_Ptr init_bytes, - Dwarf_Unsigned init_n_bytes, Dwarf_Error * error) -{ - Dwarf_P_Cie curcie; - - if (dbg->de_frame_cies == NULL) { - dbg->de_frame_cies = (Dwarf_P_Cie) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s)); - if (dbg->de_frame_cies == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_NOCOUNT); - } - curcie = dbg->de_frame_cies; - dbg->de_n_cie = 1; - dbg->de_last_cie = curcie; - } else { - curcie = dbg->de_last_cie; - curcie->cie_next = (Dwarf_P_Cie) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s)); - if (curcie->cie_next == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_NOCOUNT); - } - curcie = curcie->cie_next; - dbg->de_n_cie++; - dbg->de_last_cie = curcie; - } - curcie->cie_version = DW_CIE_VERSION; - curcie->cie_aug = augmenter; - curcie->cie_code_align = code_align; - curcie->cie_data_align = data_align; - curcie->cie_ret_reg = return_reg; - curcie->cie_inst = (char *) init_bytes; - curcie->cie_inst_bytes = (long) init_n_bytes; - curcie->cie_next = NULL; - return dbg->de_n_cie; -} - - -/*------------------------------------------------------------------------- - This functions adds a fde struct to the debug pointer. Its in the - form of a linked list. - die: subprogram/function die corresponding to this fde - cie: cie referred to by this fde, obtained from call to - add_frame_cie() routine. - virt_addr: beginning address - code_len: length of code reps by the fde ---------------------------------------------------------------------------*/ - /*ARGSUSED*/ /* pretend all args used */ - Dwarf_Unsigned -dwarf_add_frame_fde(Dwarf_P_Debug dbg, - Dwarf_P_Fde fde, - Dwarf_P_Die die, - Dwarf_Unsigned cie, - Dwarf_Unsigned virt_addr, - Dwarf_Unsigned code_len, - Dwarf_Unsigned symidx, Dwarf_Error * error) -{ - return dwarf_add_frame_fde_b(dbg, fde, die, cie, virt_addr, - code_len, symidx, 0, 0, error); -} - -/*ARGSUSED10*/ -Dwarf_Unsigned -dwarf_add_frame_fde_b(Dwarf_P_Debug dbg, - Dwarf_P_Fde fde, - Dwarf_P_Die die, - Dwarf_Unsigned cie, - Dwarf_Unsigned virt_addr, - Dwarf_Unsigned code_len, - Dwarf_Unsigned symidx, - Dwarf_Unsigned symidx_of_end, - Dwarf_Addr offset_from_end_sym, - Dwarf_Error * error) -{ - Dwarf_P_Fde curfde; - - fde->fde_die = die; - fde->fde_cie = (long) cie; - fde->fde_initloc = virt_addr; - fde->fde_r_symidx = symidx; - fde->fde_addr_range = code_len; - fde->fde_offset_into_exception_tables = DW_DLX_NO_EH_OFFSET; - fde->fde_exception_table_symbol = 0; - fde->fde_end_symbol_offset = offset_from_end_sym; - fde->fde_end_symbol = symidx_of_end; - fde->fde_dbg = dbg; - - curfde = dbg->de_last_fde; - if (curfde == NULL) { - dbg->de_frame_fdes = fde; - dbg->de_last_fde = fde; - dbg->de_n_fde = 1; - } else { - curfde->fde_next = fde; - dbg->de_last_fde = fde; - dbg->de_n_fde++; - } - return dbg->de_n_fde; -} - -/*------------------------------------------------------------------------- - This functions adds information to an fde. The fde is - linked into the linked list of fde's maintained in the Dwarf_P_Debug - structure. - dbg: The debug descriptor. - fde: The fde to be added. - die: subprogram/function die corresponding to this fde - cie: cie referred to by this fde, obtained from call to - add_frame_cie() routine. - virt_addr: beginning address - code_len: length of code reps by the fde - symidx: The symbol id of the symbol wrt to which relocation needs - to be performed for 'virt_addr'. - offset_into_exception_tables: The start of exception tables for - this function (indicated as an offset into the exception - tables). A value of -1 indicates that there is no exception - table entries associated with this function. - exception_table_symbol: The symbol id of the section for exception - tables wrt to which the offset_into_exception_tables will - be relocated. ---------------------------------------------------------------------------*/ -Dwarf_Unsigned -dwarf_add_frame_info(Dwarf_P_Debug dbg, - Dwarf_P_Fde fde, - Dwarf_P_Die die, - Dwarf_Unsigned cie, - Dwarf_Unsigned virt_addr, - Dwarf_Unsigned code_len, - Dwarf_Unsigned symidx, - Dwarf_Signed offset_into_exception_tables, - Dwarf_Unsigned exception_table_symbol, - Dwarf_Error * error) -{ - - return dwarf_add_frame_info_b(dbg, fde, die, cie, virt_addr, - code_len, symidx, - /* end_symbol */ 0, - /* offset_from_end */ 0, - offset_into_exception_tables, - exception_table_symbol, error); - -} - - /*ARGSUSED*/ /* pretend all args used */ -Dwarf_Unsigned -dwarf_add_frame_info_b(Dwarf_P_Debug dbg, - Dwarf_P_Fde fde, - Dwarf_P_Die die, - Dwarf_Unsigned cie, - Dwarf_Unsigned virt_addr, - Dwarf_Unsigned code_len, - Dwarf_Unsigned symidx, - Dwarf_Unsigned end_symidx, - Dwarf_Unsigned offset_from_end_symbol, - Dwarf_Signed offset_into_exception_tables, - Dwarf_Unsigned exception_table_symbol, - Dwarf_Error * error) -{ - Dwarf_P_Fde curfde; - - fde->fde_die = die; - fde->fde_cie = (long) cie; - fde->fde_initloc = virt_addr; - fde->fde_r_symidx = symidx; - fde->fde_addr_range = code_len; - fde->fde_offset_into_exception_tables = - offset_into_exception_tables; - fde->fde_exception_table_symbol = exception_table_symbol; - fde->fde_end_symbol_offset = offset_from_end_symbol; - fde->fde_end_symbol = end_symidx; - fde->fde_dbg = dbg; - - curfde = dbg->de_last_fde; - if (curfde == NULL) { - dbg->de_frame_fdes = fde; - dbg->de_last_fde = fde; - dbg->de_n_fde = 1; - } else { - curfde->fde_next = fde; - dbg->de_last_fde = fde; - dbg->de_n_fde++; - } - return dbg->de_n_fde; -} - -/* This is an alternate to inserting frame instructions - one instruction at a time. But use either this - or instruction level, not both in one fde. */ -int -dwarf_insert_fde_inst_bytes(Dwarf_P_Debug dbg, - Dwarf_P_Fde fde,Dwarf_Unsigned len, Dwarf_Ptr ibytes, - Dwarf_Error *error) -{ - if( len == 0) { - return DW_DLV_OK; - } - if(fde->fde_block || fde->fde_inst) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DUPLICATE_INST_BLOCK, - (int)DW_DLV_BADADDR); - } - fde->fde_block = (Dwarf_Ptr)_dwarf_p_get_alloc(dbg, len); - memcpy(fde->fde_block,ibytes,len); - fde->fde_inst_block_size = len; - fde->fde_n_bytes += len; - return DW_DLV_OK; -} - - - -/*------------------------------------------------------------------- - Create a new fde. ----------------------------------------------------------------------*/ -Dwarf_P_Fde -dwarf_new_fde(Dwarf_P_Debug dbg, Dwarf_Error * error) -{ - Dwarf_P_Fde fde; - - fde = (Dwarf_P_Fde) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Fde_s)); - if (fde == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_FDE_ALLOC, - (Dwarf_P_Fde) DW_DLV_BADADDR); - } - - fde->fde_uwordb_size = dbg->de_offset_size; - - return fde; -} - - -/*------------------------------------------------------------------------ - Add a cfe_offset instruction to the fde passed in. --------------------------------------------------------------------------*/ -Dwarf_P_Fde -dwarf_fde_cfa_offset(Dwarf_P_Fde fde, - Dwarf_Unsigned reg, - Dwarf_Signed offset, Dwarf_Error * error) -{ - Dwarf_Ubyte opc, regno; - char *ptr; - Dwarf_P_Frame_Pgm curinst; - int nbytes; - int res; - char buff1[ENCODE_SPACE_NEEDED]; - Dwarf_P_Debug dbg = fde->fde_dbg; - - curinst = (Dwarf_P_Frame_Pgm) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s)); - if (curinst == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_FPGM_ALLOC, - (Dwarf_P_Fde) DW_DLV_BADADDR); - } - opc = DW_CFA_offset; - regno = reg; - if (regno & 0xc0) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_REGNO_OVFL, - (Dwarf_P_Fde) DW_DLV_BADADDR); - } - opc = opc | regno; /* lower 6 bits are register number */ - curinst->dfp_opcode = opc; - res = _dwarf_pro_encode_leb128_nm(offset, &nbytes, - buff1, sizeof(buff1)); - if (res != DW_DLV_OK) { - _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); - } - ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes); - if (ptr == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); - } - memcpy(ptr, buff1, nbytes); - - curinst->dfp_args = ptr; - curinst->dfp_nbytes = nbytes; - curinst->dfp_next = NULL; - - _dwarf_pro_add_to_fde(fde, curinst); - return fde; -} - -/* - Generic routine to add opcode to fde instructions. val1 and - val2 are parameters whose interpretation depends on the 'op'. - - This does not work properly for DW_DLC_SYMBOLIC_RELOCATIONS - for DW_CFA_set_loc or DW_DVA_advance_loc* 'op', as - these ops normally are addresses or (DW_CFA_set_loc) - or code lengths (DW_DVA_advance_loc*) and such must be - represented with relocations and symbol indices for - DW_DLC_SYMBOLIC_RELOCATIONS. - - This does not treat all DW_CFA instructions yet. - - For certain operations a val? value must be - signed (though passed in as unsigned here). - - Currently this does not check that the frame - version is 3(for dwarf3) or 4 (for dwarf4) - when applying operations that are only valid for - dwarf3 or dwarf4. - -*/ -Dwarf_P_Fde -dwarf_add_fde_inst(Dwarf_P_Fde fde, - Dwarf_Small op, - Dwarf_Unsigned val1, - Dwarf_Unsigned val2, Dwarf_Error * error) -{ - Dwarf_P_Frame_Pgm curinst; - int nbytes, nbytes1, nbytes2; - Dwarf_Ubyte db; - Dwarf_Half dh; - Dwarf_Word dw; - Dwarf_Unsigned du; - char *ptr; - int res; - char buff1[ENCODE_SPACE_NEEDED]; - char buff2[ENCODE_SPACE_NEEDED]; - Dwarf_P_Debug dbg = fde->fde_dbg; - /* This is a hack telling the code when to transform - a value to a signed leb number. */ - int signed_second = 0; - int signed_first = 0; - - - nbytes = 0; - ptr = NULL; - curinst = (Dwarf_P_Frame_Pgm) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s)); - if (curinst == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_FPGM_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); - } - - switch (op) { - - case DW_CFA_advance_loc: - if (val1 <= 0x3f) { - db = val1; - op |= db; - } - /* test not portable FIX */ - else if (val1 <= UCHAR_MAX) { - op = DW_CFA_advance_loc1; - db = val1; - ptr = (char *) _dwarf_p_get_alloc(dbg, 1); - if (ptr == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); - } - memcpy((void *) ptr, (const void *) &db, 1); - nbytes = 1; - } - /* test not portable FIX */ - else if (val1 <= USHRT_MAX) { - op = DW_CFA_advance_loc2; - dh = val1; - ptr = (char *) _dwarf_p_get_alloc(dbg, 2); - if (ptr == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); - } - memcpy((void *) ptr, (const void *) &dh, 2); - nbytes = 2; - } - /* test not portable FIX */ - else if (val1 <= ULONG_MAX) { - op = DW_CFA_advance_loc4; - dw = (Dwarf_Word) val1; - ptr = (char *) _dwarf_p_get_alloc(dbg, 4); - if (ptr == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); - } - memcpy((void *) ptr, (const void *) &dw, 4); - nbytes = 4; - } else { - op = DW_CFA_MIPS_advance_loc8; - du = val1; - ptr = - (char *) _dwarf_p_get_alloc(dbg, - sizeof(Dwarf_Unsigned)); - if (ptr == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); - } - memcpy((void *) ptr, (const void *) &du, 8); - nbytes = 8; - } - break; - - case DW_CFA_offset: - if (val1 <= MAX_6_BIT_VALUE) { - db = val1; - op |= db; - res = _dwarf_pro_encode_leb128_nm(val2, &nbytes, - buff1, sizeof(buff1)); - if (res != DW_DLV_OK) { - _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); - } - ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes); - if (ptr == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); - } - memcpy(ptr, buff1, nbytes); - - } else { - op = DW_CFA_offset_extended; - goto two_leb; - } - break; - case DW_CFA_offset_extended_sf: /* DWARF3 */ - signed_second = 1; - goto two_leb; - case DW_CFA_offset_extended: - goto two_leb; - - case DW_CFA_undefined: - case DW_CFA_same_value: - goto one_leb; - - case DW_CFA_val_offset: - goto two_leb; - case DW_CFA_val_offset_sf: - signed_second = 1; - goto two_leb; - case DW_CFA_def_cfa_sf: - signed_second = 1; - goto two_leb; - case DW_CFA_register: - case DW_CFA_def_cfa: - two_leb: - res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1, - buff1, sizeof(buff1)); - if (res != DW_DLV_OK) { - _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); - } - if (!signed_second) { - res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2, - buff2, sizeof(buff2)); - } else { - Dwarf_Signed val2s = val2; - res = _dwarf_pro_encode_signed_leb128_nm(val2s, &nbytes2, - buff2, sizeof(buff2)); - } - - res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2, - buff2, sizeof(buff2)); - if (res != DW_DLV_OK) { - _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); - } - - ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes1 + nbytes2); - if (ptr == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); - } - memcpy(ptr, buff1, nbytes1); - memcpy(ptr + nbytes1, buff2, nbytes2); - nbytes = nbytes1 + nbytes2; - break; - - case DW_CFA_def_cfa_offset_sf: /* DWARF3 */ - signed_first = 1; - goto one_leb; - case DW_CFA_def_cfa_register: - case DW_CFA_def_cfa_offset: - one_leb: - if(!signed_first) { - res = _dwarf_pro_encode_leb128_nm(val1, &nbytes, - buff1, sizeof(buff1)); - } else { - Dwarf_Signed val1s = val1; - res = _dwarf_pro_encode_signed_leb128_nm(val1s, &nbytes, - buff1, sizeof(buff1)); - } - if (res != DW_DLV_OK) { - _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); - } - ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes); - if (ptr == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); - } - memcpy(ptr, buff1, nbytes); - break; - case DW_CFA_def_cfa_expression: /* DWARF3 */ - /* FIXME: argument is dwarf expr, not handled yet. */ - case DW_CFA_expression: /* DWARF3 */ - /* First arg: ULEB reg num. 2nd arg dwarf expr in form block. - FIXME: not handled yet. */ - case DW_CFA_val_expression: /* DWARF3f */ - /* First arg: ULEB reg num. 2nd arg dwarf expr in form block. - FIXME: not handled yet. */ - default: - _dwarf_p_error(dbg, error, DW_DLE_DEBUGFRAME_ERROR); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); - } - - curinst->dfp_opcode = op; - curinst->dfp_args = ptr; - curinst->dfp_nbytes = nbytes; - curinst->dfp_next = NULL; - - _dwarf_pro_add_to_fde(fde, curinst); - return fde; -} - - -/*------------------------------------------------------------------------ - Instructions are added to an fde in the form of a linked - list. This function manages the linked list. --------------------------------------------------------------------------*/ -void -_dwarf_pro_add_to_fde(Dwarf_P_Fde fde, Dwarf_P_Frame_Pgm curinst) -{ - if (fde->fde_last_inst) { - fde->fde_last_inst->dfp_next = curinst; - fde->fde_last_inst = curinst; - fde->fde_n_inst++; - fde->fde_n_bytes += - (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte)); - } else { - fde->fde_last_inst = curinst; - fde->fde_inst = curinst; - fde->fde_n_inst = 1; - fde->fde_n_bytes = - (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte)); - } -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_frame.h b/usr/src/tools/ctf/dwarf/common/pro_frame.h deleted file mode 100644 index df60d369ed..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_frame.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -/* - Largest register value that can be coded into - the opcode since there are only 6 bits in the - register field. -*/ -#define MAX_6_BIT_VALUE 0x3f - -/* - This struct holds debug_frame instructions -*/ -typedef struct Dwarf_P_Frame_Pgm_s *Dwarf_P_Frame_Pgm; - -struct Dwarf_P_Frame_Pgm_s { - Dwarf_Ubyte dfp_opcode; /* opcode - includes reg # */ - char *dfp_args; /* operands */ - int dfp_nbytes; /* number of bytes in args */ -#if 0 - Dwarf_Unsigned dfp_sym_index; /* 0 unless reloc needed */ -#endif - Dwarf_P_Frame_Pgm dfp_next; -}; - - -/* - This struct has cie related information. Used to gather data - from user program, and later to transform to disk form -*/ -struct Dwarf_P_Cie_s { - Dwarf_Ubyte cie_version; - char *cie_aug; /* augmentation */ - Dwarf_Ubyte cie_code_align; /* alignment of code */ - Dwarf_Sbyte cie_data_align; - Dwarf_Ubyte cie_ret_reg; /* return register # */ - char *cie_inst; /* initial instruction */ - long cie_inst_bytes; - /* no of init_inst */ - Dwarf_P_Cie cie_next; -}; - - -/* producer fields */ -struct Dwarf_P_Fde_s { - Dwarf_Unsigned fde_unused1; - - /* function/subr die for this fde */ - Dwarf_P_Die fde_die; - - /* index to asso. cie */ - Dwarf_Word fde_cie; - - /* Address of first location of the code this frame applies to If - fde_end_symbol non-zero, this represents the offset from the - symbol indicated by fde_r_symidx */ - Dwarf_Addr fde_initloc; - - /* Relocation symbol for address of the code this frame applies to. - */ - Dwarf_Unsigned fde_r_symidx; - - /* Bytes of instr for this fde, if known */ - Dwarf_Unsigned fde_addr_range; - - /* linked list of instructions we will put in fde. */ - Dwarf_P_Frame_Pgm fde_inst; - - /* number of instructions in fde */ - long fde_n_inst; - - /* number of bytes of inst in fde */ - long fde_n_bytes; - - /* offset into exception table for this function. */ - Dwarf_Signed fde_offset_into_exception_tables; - - /* The symbol for the exception table elf section. */ - Dwarf_Unsigned fde_exception_table_symbol; - - /* pointer to last inst */ - Dwarf_P_Frame_Pgm fde_last_inst; - - Dwarf_P_Fde fde_next; - - /* The symbol and offset of the end symbol. When fde_end_symbol is - non-zero we must represent the */ - Dwarf_Addr fde_end_symbol_offset; - Dwarf_Unsigned fde_end_symbol; - - int fde_uwordb_size; - Dwarf_P_Debug fde_dbg; - - /* If fde_block is non-null, then it is the set of instructions. - so we should use it rather than fde_inst. */ - Dwarf_Unsigned fde_inst_block_size; - void *fde_block; -}; diff --git a/usr/src/tools/ctf/dwarf/common/pro_funcs.c b/usr/src/tools/ctf/dwarf/common/pro_funcs.c deleted file mode 100644 index 8ff05500bb..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_funcs.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#include -#include -#ifdef HAVE_ELFACCESS_H -#include -#endif -#include "pro_incl.h" -#include "pro_section.h" - -/* - This function adds another function name to the - list of function names for the given Dwarf_P_Debug. - It returns 0 on error, and 1 otherwise. -*/ -Dwarf_Unsigned -dwarf_add_funcname(Dwarf_P_Debug dbg, - Dwarf_P_Die die, - char *function_name, Dwarf_Error * error) -{ - return - _dwarf_add_simple_name_entry(dbg, die, function_name, - dwarf_snk_funcname, error); - -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_incl.h b/usr/src/tools/ctf/dwarf/common/pro_incl.h deleted file mode 100644 index 10bce470c2..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_incl.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - - Copyright (C) 2000,2002,2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. - Portions Copyright 2008-2010 David Anderson. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - -#ifdef HAVE_ELF_H -#include -#elif defined(HAVE_LIBELF_H) -/* On one platform without elf.h this gets Elf32_Rel - type defined (a required type). */ -#include -#endif - -#if defined(sun) -#include -#include -#endif - -/* The target address is given: the place in the source integer - is to be determined. -*/ -#ifdef WORDS_BIGENDIAN -#define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \ - { \ - dbg->de_copy_word(dest, \ - ((char *)source) +srclength-len_out, \ - len_out) ; \ - } - - -#else /* LITTLE ENDIAN */ - -#define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \ - { \ - dbg->de_copy_word( (dest) , \ - ((char *)source) , \ - len_out) ; \ - } -#endif - - -#if defined(sparc) && defined(sun) -#define REL32 Elf32_Rela -#define REL64 Elf64_Rela -#define REL_SEC_PREFIX ".rela" -#else -#define REL32 Elf32_Rel -#define REL64 Elf64_Rel -#define REL_SEC_PREFIX ".rel" -#endif - -#include "dwarf.h" -#include "libdwarf.h" - -#include "pro_opaque.h" -#include "pro_error.h" -#include "pro_util.h" -#include "pro_encode_nm.h" -#include "pro_alloc.h" diff --git a/usr/src/tools/ctf/dwarf/common/pro_init.c b/usr/src/tools/ctf/dwarf/common/pro_init.c deleted file mode 100644 index d696113a67..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_init.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. - Portions Copyright 2008-2010 David Anderson, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#include -#include -#include "pro_incl.h" -#include "pro_section.h" /* for MAGIC_SECT_NO */ -#include "pro_reloc_symbolic.h" -#include "pro_reloc_stream.h" - - -static void common_init(Dwarf_P_Debug dbg, Dwarf_Unsigned flags); - -void *_dwarf_memcpy_swap_bytes(void *s1, const void *s2, size_t len); - -/*-------------------------------------------------------------------- - This function sets up a new dwarf producing region. - flags: Indicates type of access method, one of DW_DLC* macros - func(): Used to create a new object file, a call back function - errhand(): Error Handler provided by user - errarg: Argument to errhand() - error: returned error value ---------------------------------------------------------------------*/ - /* We want the following to have an elf section number that matches - 'nothing' */ -static struct Dwarf_P_Section_Data_s init_sect = { - MAGIC_SECT_NO, 0, 0, 0, 0 -}; - -Dwarf_P_Debug -dwarf_producer_init_b(Dwarf_Unsigned flags, - Dwarf_Callback_Func_b func, - Dwarf_Handler errhand, - Dwarf_Ptr errarg, Dwarf_Error * error) -{ - Dwarf_P_Debug dbg; - dbg = (Dwarf_P_Debug) _dwarf_p_get_alloc(NULL, - sizeof(struct - Dwarf_P_Debug_s)); - if (dbg == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, - (Dwarf_P_Debug) DW_DLV_BADADDR); - } - memset((void *) dbg, 0, sizeof(struct Dwarf_P_Debug_s)); - /* For the time being */ - if (func == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_NO_CALLBACK_FUNC, - (Dwarf_P_Debug) DW_DLV_BADADDR); - } - dbg->de_callback_func_b = func; - dbg->de_errhand = errhand; - dbg->de_errarg = errarg; - common_init(dbg, flags); - return dbg; - -} - -Dwarf_P_Debug -dwarf_producer_init(Dwarf_Unsigned flags, - Dwarf_Callback_Func func, - Dwarf_Handler errhand, - Dwarf_Ptr errarg, Dwarf_Error * error) -{ - - Dwarf_P_Debug dbg; - - - - dbg = (Dwarf_P_Debug) _dwarf_p_get_alloc(NULL, - sizeof(struct - Dwarf_P_Debug_s)); - if (dbg == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, - (Dwarf_P_Debug) DW_DLV_BADADDR); - } - memset((void *) dbg, 0, sizeof(struct Dwarf_P_Debug_s)); - /* For the time being */ - if (func == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_NO_CALLBACK_FUNC, - (Dwarf_P_Debug) DW_DLV_BADADDR); - } - dbg->de_callback_func = func; - dbg->de_errhand = errhand; - dbg->de_errarg = errarg; - common_init(dbg, flags); - return dbg; -} -static void -common_init(Dwarf_P_Debug dbg, Dwarf_Unsigned flags) -{ - unsigned int k; - - - dbg->de_version_magic_number = PRO_VERSION_MAGIC; - dbg->de_n_debug_sect = 0; - dbg->de_debug_sects = &init_sect; - dbg->de_current_active_section = &init_sect; - dbg->de_flags = flags; - - /* Now, with flags set, can use 64bit tests */ - - - -#if defined(HAVE_STRICT_DWARF2_32BIT_OFFSET) - /* This is cygnus 32bit offset, as specified in pure dwarf2 v2.0.0. - It is consistent with normal DWARF2/3 generation of always - generating 32 bit offsets. */ - dbg->de_64bit_extension = 0; - dbg->de_pointer_size = (IS_64BIT(dbg) ? 8 : 4); - dbg->de_offset_size = (IS_64BIT(dbg) ? 4 : 4); - dbg->de_ptr_reloc = - IS_64BIT(dbg) ? Get_REL64_isa(dbg) : Get_REL32_isa(dbg); - /* non-MIPS, dwarf lengths and offsets are 32 bits even for 64bit - pointer environments. */ - /* Get_REL32_isa here supports 64-bit-pointer dwarf with pure - dwarf2 v2.0.0 32bit offsets, as emitted by cygnus tools. And - pure 32 bit offset dwarf for 32bit pointer apps. */ - - dbg->de_offset_reloc = Get_REL32_isa(dbg); -#elif defined(HAVE_SGI_IRIX_OFFSETS) - /* MIPS-SGI-IRIX 32 or 64, where offsets and lengths are both 64 bit for - 64bit pointer objects and both 32 bit for 32bit pointer objects. - And a dwarf-reader must check elf info to tell which applies. */ - dbg->de_64bit_extension = 0; - dbg->de_pointer_size = (IS_64BIT(dbg) ? 8 : 4); - dbg->de_offset_size = (IS_64BIT(dbg) ? 8 : 4); - dbg->de_ptr_reloc = - IS_64BIT(dbg) ? Get_REL64_isa(dbg) : Get_REL32_isa(dbg); - dbg->de_offset_reloc = dbg->de_ptr_reloc; -#else /* HAVE_DWARF2_99_EXTENSION or default. */ - /* Revised 64 bit output, using distingushed values. Per 1999 - dwarf3. This allows run-time selection of offset size. */ - dbg->de_64bit_extension = (IS_64BIT(dbg) ? 1 : 0); - dbg->de_pointer_size = (IS_64BIT(dbg) ? 8 : 4); - if( flags & DW_DLC_OFFSET_SIZE_64 && (dbg->de_pointer_size == 8)) { - /* When it's 64 bit address, a 64bit offset is sensible. - Arguably a 32 bit address with 64 bit offset could be - sensible, but who would want that? */ - dbg->de_offset_size = 8; - dbg->de_64bit_extension = 1; - } else { - dbg->de_offset_size = 4; - dbg->de_64bit_extension = 0; - } - dbg->de_ptr_reloc = - IS_64BIT(dbg) ? Get_REL64_isa(dbg) : Get_REL32_isa(dbg); - /* Non-MIPS, dwarf lengths and offsets are 32 bits even for 64bit - pointer environments. */ - /* Get_REL??_isa here supports 64bit-offset dwarf. For 64bit, we - emit the extension bytes. */ - - dbg->de_offset_reloc = IS_64BIT(dbg) ? Get_REL64_isa(dbg) - : Get_REL32_isa(dbg); -#endif /* HAVE_DWARF2_99_EXTENSION etc. */ - - dbg->de_exc_reloc = Get_REL_SEGREL_isa(dbg); - - dbg->de_is_64bit = IS_64BIT(dbg); - - - if (flags & DW_DLC_SYMBOLIC_RELOCATIONS) { - dbg->de_relocation_record_size = - sizeof(struct Dwarf_Relocation_Data_s); - } else { - -#if HAVE_ELF64_GETEHDR - dbg->de_relocation_record_size = - IS_64BIT(dbg)? sizeof(REL64) : sizeof(REL32); -#else - dbg->de_relocation_record_size = sizeof(REL32); -#endif - - } - - if (dbg->de_offset_size == 8) { - dbg->de_ar_data_attribute_form = DW_FORM_data8; - dbg->de_ar_ref_attr_form = DW_FORM_ref8; - } else { - dbg->de_ar_data_attribute_form = DW_FORM_data4; - dbg->de_ar_ref_attr_form = DW_FORM_ref4; - } - - if (flags & DW_DLC_SYMBOLIC_RELOCATIONS) { - dbg->de_reloc_name = _dwarf_pro_reloc_name_symbolic; - dbg->de_reloc_pair = _dwarf_pro_reloc_length_symbolic; - dbg->de_transform_relocs_to_disk = - _dwarf_symbolic_relocs_to_disk; - } else { - if (IS_64BIT(dbg)) { - dbg->de_reloc_name = _dwarf_pro_reloc_name_stream64; - } else { - dbg->de_reloc_name = _dwarf_pro_reloc_name_stream32; - } - dbg->de_reloc_pair = 0; - dbg->de_transform_relocs_to_disk = _dwarf_stream_relocs_to_disk; - } - for (k = 0; k < NUM_DEBUG_SECTIONS; ++k) { - - Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[k]; - - prel->pr_slots_per_block_to_alloc = DEFAULT_SLOTS_PER_BLOCK; - } - /* First assume host, target same endianness */ - dbg->de_same_endian = 1; - dbg->de_copy_word = memcpy; -#ifdef WORDS_BIGENDIAN - /* host is big endian, so what endian is target? */ - if (flags & DW_DLC_TARGET_LITTLEENDIAN) { - dbg->de_same_endian = 0; - dbg->de_copy_word = _dwarf_memcpy_swap_bytes; - } -#else /* little endian */ - /* host is little endian, so what endian is target? */ - if (flags & DW_DLC_TARGET_BIGENDIAN) { - dbg->de_same_endian = 0; - dbg->de_copy_word = _dwarf_memcpy_swap_bytes; - } -#endif /* !WORDS_BIGENDIAN */ - - - return; - -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_line.c b/usr/src/tools/ctf/dwarf/common/pro_line.c deleted file mode 100644 index 69d3e339f0..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_line.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#include -#include -#ifdef HAVE_ELF_H -#include -#endif -#include "pro_incl.h" -#include "pro_line.h" - -Dwarf_Unsigned _dwarf_pro_add_line_entry(Dwarf_P_Debug, - Dwarf_Unsigned file_index, - Dwarf_Addr code_address, - Dwarf_Unsigned symidx, - Dwarf_Unsigned line_no, - Dwarf_Signed col_no, - Dwarf_Bool is_stmt_begin, - Dwarf_Bool is_bb_begin, - Dwarf_Ubyte opc, - Dwarf_Error * error); - -/*------------------------------------------------------------------------- - Add a entry to the line information section - file_index: index of file in file entries, obtained from - add_file_entry() call. - - This function actually calls _dwarf_pro_add_line_entry(), with - an extra parameter, the opcode. Done so that interface calls - dwarf_lne_set_address() and dwarf_lne_end_sequence() can use - this internal routine. ----------------------------------------------------------------------------*/ -Dwarf_Unsigned -dwarf_add_line_entry(Dwarf_P_Debug dbg, - Dwarf_Unsigned file_index, - Dwarf_Addr code_address, - Dwarf_Unsigned line_no, - Dwarf_Signed col_no, - Dwarf_Bool is_stmt_begin, - Dwarf_Bool is_bb_begin, Dwarf_Error * error) -{ - Dwarf_Unsigned retval; - - retval = _dwarf_pro_add_line_entry(dbg, file_index, code_address, 0, - line_no, col_no, is_stmt_begin, - is_bb_begin, 0, error); - return retval; -} - -/*------------------------------------------------------------------------ - Ask to emit DW_LNE_set_address opcode explicitly. Used by be - to emit start of a new .text section, or to force a relocated - address into debug line information entry. --------------------------------------------------------------------------*/ -Dwarf_Unsigned -dwarf_lne_set_address(Dwarf_P_Debug dbg, - Dwarf_Addr offs, - Dwarf_Unsigned symidx, Dwarf_Error * error) -{ - Dwarf_Ubyte opc; - Dwarf_Unsigned retval; - - opc = DW_LNE_set_address; - retval = - _dwarf_pro_add_line_entry(dbg, 0, offs, symidx, 0, 0, 0, 0, opc, - error); - return retval; -} - -/*------------------------------------------------------------------------ - Ask to emit end_seqence opcode. Used normally at the end of a - compilation unit. Can also be used in the middle if there - are gaps in the region described by the code address. --------------------------------------------------------------------------*/ -Dwarf_Unsigned -dwarf_lne_end_sequence(Dwarf_P_Debug dbg, - Dwarf_Addr end_address, Dwarf_Error * error) -{ - Dwarf_Ubyte opc; - Dwarf_Unsigned retval; - - opc = DW_LNE_end_sequence; - retval = - _dwarf_pro_add_line_entry(dbg, 0, end_address, 0, 0, 0, 0, 0, - opc, error); - return retval; -} - -/*---------------------------------------------------------------------------- - Add an entry in the internal list of lines mantained by producer. - Opc indicates if an opcode needs to be generated, rather than just - an entry in the matrix. During opcodes generation time, these - opcodes will be used. ------------------------------------------------------------------------------*/ -Dwarf_Unsigned -_dwarf_pro_add_line_entry(Dwarf_P_Debug dbg, - Dwarf_Unsigned file_index, - Dwarf_Addr code_address, - Dwarf_Unsigned symidx, - Dwarf_Unsigned line_no, - Dwarf_Signed col_no, - Dwarf_Bool is_stmt_begin, - Dwarf_Bool is_bb_begin, - Dwarf_Ubyte opc, Dwarf_Error * error) -{ - if (dbg->de_lines == NULL) { - dbg->de_lines = (Dwarf_P_Line) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Line_s)); - if (dbg->de_lines == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_LINE_ALLOC, DW_DLV_NOCOUNT); - } - dbg->de_last_line = dbg->de_lines; - _dwarf_pro_reg_init(dbg->de_lines); - - } else { - dbg->de_last_line->dpl_next = (Dwarf_P_Line) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Line_s)); - if (dbg->de_last_line->dpl_next == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_LINE_ALLOC, DW_DLV_NOCOUNT); - } - dbg->de_last_line = dbg->de_last_line->dpl_next; - _dwarf_pro_reg_init(dbg->de_last_line); - } - dbg->de_last_line->dpl_address = code_address; - dbg->de_last_line->dpl_file = (unsigned long) file_index; - dbg->de_last_line->dpl_line = (unsigned long) line_no; - dbg->de_last_line->dpl_column = (unsigned long) col_no; - dbg->de_last_line->dpl_is_stmt = is_stmt_begin; - dbg->de_last_line->dpl_basic_block = is_bb_begin; - dbg->de_last_line->dpl_opc = opc; - dbg->de_last_line->dpl_r_symidx = symidx; - - return (0); -} - -/*----------------------------------------------------------------------- - Add a directory declaration to the debug_line section. Stored - in linked list. -------------------------------------------------------------------------*/ -Dwarf_Unsigned -dwarf_add_directory_decl(Dwarf_P_Debug dbg, - char *name, Dwarf_Error * error) -{ - if (dbg->de_inc_dirs == NULL) { - dbg->de_inc_dirs = (Dwarf_P_Inc_Dir) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Inc_Dir_s)); - if (dbg->de_inc_dirs == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_INCDIR_ALLOC, DW_DLV_NOCOUNT); - } - dbg->de_last_inc_dir = dbg->de_inc_dirs; - dbg->de_n_inc_dirs = 1; - } else { - dbg->de_last_inc_dir->did_next = (Dwarf_P_Inc_Dir) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Inc_Dir_s)); - if (dbg->de_last_inc_dir->did_next == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_INCDIR_ALLOC, DW_DLV_NOCOUNT); - } - dbg->de_last_inc_dir = dbg->de_last_inc_dir->did_next; - dbg->de_n_inc_dirs++; - } - dbg->de_last_inc_dir->did_name = - (char *) _dwarf_p_get_alloc(dbg, strlen(name) + 1); - if (dbg->de_last_inc_dir->did_name == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_STRING_ALLOC, DW_DLV_NOCOUNT); - } - strcpy(dbg->de_last_inc_dir->did_name, name); - dbg->de_last_inc_dir->did_next = NULL; - - return dbg->de_n_inc_dirs; -} - -/*----------------------------------------------------------------------- - Add a file entry declaration to the debug_line section. Stored - in linked list. The data is immediately encodes as leb128 - and stored in Dwarf_P_F_Entry_s struct. -------------------------------------------------------------------------*/ -Dwarf_Unsigned -dwarf_add_file_decl(Dwarf_P_Debug dbg, - char *name, - Dwarf_Unsigned dir_idx, - Dwarf_Unsigned time_mod, - Dwarf_Unsigned length, Dwarf_Error * error) -{ - Dwarf_P_F_Entry cur; - char *ptr; - int nbytes_idx, nbytes_time, nbytes_len; - char buffidx[ENCODE_SPACE_NEEDED]; - char bufftime[ENCODE_SPACE_NEEDED]; - char bufflen[ENCODE_SPACE_NEEDED]; - int res; - - if (dbg->de_file_entries == NULL) { - dbg->de_file_entries = (Dwarf_P_F_Entry) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_F_Entry_s)); - if (dbg->de_file_entries == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_FILE_ENTRY_ALLOC, - DW_DLV_NOCOUNT); - } - cur = dbg->de_file_entries; - dbg->de_last_file_entry = cur; - dbg->de_n_file_entries = 1; - } else { - cur = dbg->de_last_file_entry; - cur->dfe_next = (Dwarf_P_F_Entry) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_F_Entry_s)); - if (cur->dfe_next == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_FILE_ENTRY_ALLOC, - DW_DLV_NOCOUNT); - } - cur = cur->dfe_next; - dbg->de_last_file_entry = cur; - dbg->de_n_file_entries++; - } - cur->dfe_name = (char *) _dwarf_p_get_alloc(dbg, strlen(name) + 1); - if (cur->dfe_name == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT); - } - strcpy((char *) cur->dfe_name, name); - res = _dwarf_pro_encode_leb128_nm(dir_idx, &nbytes_idx, - buffidx, sizeof(buffidx)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT); - } - res = _dwarf_pro_encode_leb128_nm(time_mod, &nbytes_time, - bufftime, sizeof(bufftime)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT); - } - res = _dwarf_pro_encode_leb128_nm(length, &nbytes_len, - bufflen, sizeof(bufflen)); - cur->dfe_args = (char *) - _dwarf_p_get_alloc(dbg, nbytes_idx + nbytes_time + nbytes_len); - if (cur->dfe_args == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT); - } - ptr = cur->dfe_args; - memcpy((void *) ptr, buffidx, nbytes_idx); - ptr += nbytes_idx; - memcpy((void *) ptr, bufftime, nbytes_time); - ptr += nbytes_time; - memcpy((void *) ptr, bufflen, nbytes_len); - ptr += nbytes_len; - cur->dfe_nbytes = nbytes_idx + nbytes_time + nbytes_len; - cur->dfe_next = NULL; - - return dbg->de_n_file_entries; -} - - -/*--------------------------------------------------------------------- - Initialize a row of the matrix for line numbers, meaning - initialize the struct corresponding to it -----------------------------------------------------------------------*/ -void -_dwarf_pro_reg_init(Dwarf_P_Line cur_line) -{ - cur_line->dpl_address = 0; - cur_line->dpl_file = 1; - cur_line->dpl_line = 1; - cur_line->dpl_column = 0; - cur_line->dpl_is_stmt = DEFAULT_IS_STMT; - cur_line->dpl_basic_block = false; - cur_line->dpl_next = NULL; -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_line.h b/usr/src/tools/ctf/dwarf/common/pro_line.h deleted file mode 100644 index eed941239d..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_line.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#define VERSION 2 -#ifdef __i386 -#define MIN_INST_LENGTH 1 -#else -#define MIN_INST_LENGTH 4 -#endif -#define DEFAULT_IS_STMT false - /* line base and range are temporarily defines. - They need to be calculated later */ -#define LINE_BASE -1 -#define LINE_RANGE 4 - -#define OPCODE_BASE 10 -#define MAX_OPCODE 255 - - -/* - This struct is used to hold entries in the include directories - part of statement prologue. -*/ -struct Dwarf_P_Inc_Dir_s { - char *did_name; /* name of directory */ - Dwarf_P_Inc_Dir did_next; -}; - - -/* - This struct holds file entries for the statement prologue. - Defined in pro_line.h -*/ -struct Dwarf_P_F_Entry_s { - char *dfe_name; - char *dfe_args; /* has dir index, time of modification, - length in bytes. Encodes as leb128 */ - int dfe_nbytes; /* number of bytes in args */ - Dwarf_P_F_Entry dfe_next; -}; - - -/* - Struct holding line number information for each of the producer - line entries -*/ -struct Dwarf_P_Line_s { - /* code address */ - Dwarf_Addr dpl_address; - - /* file index, index into file entry */ - Dwarf_Word dpl_file; - - /* line number */ - Dwarf_Word dpl_line; - - /* column number */ - Dwarf_Word dpl_column; - - /* whether its a beginning of a stmt */ - Dwarf_Ubyte dpl_is_stmt; - - /* whether its a beginning of basic blk */ - Dwarf_Ubyte dpl_basic_block; - - /* used to store opcodes set_address, and end_seq */ - Dwarf_Ubyte dpl_opc; - - /* - Used only for relocations. Has index of symbol relative to - which relocation has to be done (the S part in S + A) */ - Dwarf_Unsigned dpl_r_symidx; - - Dwarf_P_Line dpl_next; -}; - -/* - to initialize state machine registers, definition in - pro_line.c -*/ -void _dwarf_pro_reg_init(Dwarf_P_Line); diff --git a/usr/src/tools/ctf/dwarf/common/pro_macinfo.c b/usr/src/tools/ctf/dwarf/common/pro_macinfo.c deleted file mode 100644 index cfa820aee6..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_macinfo.c +++ /dev/null @@ -1,472 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#include -#include -#include "pro_incl.h" -#include "pro_section.h" -#include "pro_macinfo.h" - -/* - I don't much like the error strings this generates, since - like the rest of libdwarf they are simple strings with - no useful numbers in them. But that's not something I can - fix without more work than I have time for - right now. davea Nov 94. -*/ - -/* these are gross overestimates of the number of -** bytes needed to store a number in LEB form. -** Just estimates, and since blocks are reasonable size, -** the end-block waste is small. -** Of course the waste is NOT present on disk. -*/ - -#define COMMAND_LEN ENCODE_SPACE_NEEDED -#define LINE_LEN ENCODE_SPACE_NEEDED -#define BASE_MACINFO_MALLOC_LEN 2048 - -static int -libdwarf_compose_begin(Dwarf_P_Debug dbg, int code, - size_t maxlen, int *compose_error_type) -{ - unsigned char *nextchar; - struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo; - - if (curblk == 0) { - struct dw_macinfo_block_s *newb; - size_t len; - - /* initial allocation */ - size_t blen = BASE_MACINFO_MALLOC_LEN; - - if (blen < maxlen) { - blen = 2 * maxlen; - } - len = sizeof(struct dw_macinfo_block_s) + blen; - newb = - (struct dw_macinfo_block_s *) _dwarf_p_get_alloc(dbg, len); - if (!newb) { - *compose_error_type = DW_DLE_MACINFO_MALLOC_FAIL; - return DW_DLV_ERROR; - } - newb->mb_data = - (char *) newb + sizeof(struct dw_macinfo_block_s); - newb->mb_avail_len = blen; - newb->mb_used_len = 0; - newb->mb_macinfo_data_space_len = blen; - dbg->de_first_macinfo = newb; - dbg->de_current_macinfo = newb; - curblk = newb; - } else if (curblk->mb_avail_len < maxlen) { - struct dw_macinfo_block_s *newb; - size_t len; - - /* no space left in block: allocate a new block */ - size_t blen = - dbg->de_current_macinfo->mb_macinfo_data_space_len * 2; - if (blen < maxlen) { - blen = 2 * maxlen; - } - len = sizeof(struct dw_macinfo_block_s) + blen; - newb = - (struct dw_macinfo_block_s *) _dwarf_p_get_alloc(dbg, len); - if (!newb) { - *compose_error_type = DW_DLE_MACINFO_MALLOC_FAIL; - return DW_DLV_ERROR; - } - newb->mb_data = - (char *) newb + sizeof(struct dw_macinfo_block_s); - newb->mb_avail_len = blen; - newb->mb_used_len = 0; - newb->mb_macinfo_data_space_len = blen; - dbg->de_first_macinfo->mb_next = newb; - dbg->de_current_macinfo = newb; - curblk = newb; - } - /* now curblk has enough room */ - dbg->de_compose_avail = curblk->mb_avail_len; - dbg->de_compose_used_len = curblk->mb_used_len; - nextchar = - (unsigned char *) (curblk->mb_data + dbg->de_compose_used_len); - *nextchar = code; - dbg->de_compose_avail--; - ++dbg->de_compose_used_len; - return DW_DLV_OK; -} - - - -static void -libdwarf_compose_add_string(Dwarf_P_Debug dbg, char *string, size_t len) -{ - struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo; - unsigned char *nextchar; - - nextchar = - (unsigned char *) (curblk->mb_data + dbg->de_compose_used_len); - - len += 1; /* count the null terminator */ - - memcpy(nextchar, string, len); - dbg->de_compose_avail -= len; - dbg->de_compose_used_len += len; - return; - -} -static int -libdwarf_compose_add_line(Dwarf_P_Debug dbg, - Dwarf_Unsigned line, int *compose_error_type) -{ - struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo; - unsigned char *nextchar; - int res; - int nbytes; - - nextchar = - (unsigned char *) (curblk->mb_data + dbg->de_compose_used_len); - - /* Put the created leb number directly into the macro buffer If - dbg->de_compose_avail is > INT_MAX this will not work as the - 'int' will look negative to _dwarf_pro_encode_leb128_nm! */ - - res = _dwarf_pro_encode_leb128_nm(line, &nbytes, - (char *) nextchar, - (int) dbg->de_compose_avail); - if (res != DW_DLV_OK) { - *compose_error_type = DW_DLE_MACINFO_INTERNAL_ERROR_SPACE; - return DW_DLV_ERROR; - } - - dbg->de_compose_avail -= nbytes; - dbg->de_compose_used_len += nbytes; - return DW_DLV_OK; -} - -/* - This function actually 'commits' the space used by the - preceeding calls. -*/ -static int -libdwarf_compose_complete(Dwarf_P_Debug dbg, int *compose_error_type) -{ - struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo; - - if (dbg->de_compose_used_len > curblk->mb_macinfo_data_space_len) { - *compose_error_type = DW_DLE_MACINFO_INTERNAL_ERROR_SPACE; - return DW_DLV_ERROR; - } - curblk->mb_avail_len = dbg->de_compose_avail; - curblk->mb_used_len = dbg->de_compose_used_len; - return DW_DLV_OK; -} - - - -int -dwarf_def_macro(Dwarf_P_Debug dbg, - Dwarf_Unsigned line, - char *macname, char *macvalue, Dwarf_Error * error) -{ - size_t len; - size_t len2; - size_t length_est; - int res; - int compose_error_type; - - if (dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - if (macname == 0) { - _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL); - return (DW_DLV_ERROR); - } - len = strlen(macname) + 1; - if (len == 0) { - _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY); - return (DW_DLV_ERROR); - } - if (macvalue) { - len2 = strlen(macvalue) + 1; - } else { - len2 = 0; - } - length_est = COMMAND_LEN + LINE_LEN + len + len2 + 1; /* 1 - for - space - character - we - add */ - res = libdwarf_compose_begin(dbg, DW_MACINFO_define, length_est, - &compose_error_type); - if (res != DW_DLV_OK) { - _dwarf_p_error(NULL, error, compose_error_type); - return (DW_DLV_ERROR); - } - res = libdwarf_compose_add_line(dbg, line, &compose_error_type); - if (res != DW_DLV_OK) { - _dwarf_p_error(NULL, error, compose_error_type); - return (DW_DLV_ERROR); - } - libdwarf_compose_add_string(dbg, macname, len); - libdwarf_compose_add_string(dbg, " ", 1); - if (macvalue) { - libdwarf_compose_add_string(dbg, " ", 1); - libdwarf_compose_add_string(dbg, macvalue, len2); - } - res = libdwarf_compose_complete(dbg, &compose_error_type); - if (res != DW_DLV_OK) { - _dwarf_p_error(NULL, error, compose_error_type); - return (DW_DLV_ERROR); - } - return DW_DLV_OK; -} - -int -dwarf_undef_macro(Dwarf_P_Debug dbg, - Dwarf_Unsigned line, - char *macname, Dwarf_Error * error) -{ - - size_t len; - size_t length_est; - int res; - int compose_error_type; - - if (dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - if (macname == 0) { - _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL); - return (DW_DLV_ERROR); - } - len = strlen(macname) + 1; - if (len == 0) { - _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY); - return (DW_DLV_ERROR); - } - length_est = COMMAND_LEN + LINE_LEN + len; - res = libdwarf_compose_begin(dbg, DW_MACINFO_undef, length_est, - &compose_error_type); - if (res != DW_DLV_OK) { - _dwarf_p_error(NULL, error, compose_error_type); - return (DW_DLV_ERROR); - } - res = libdwarf_compose_add_line(dbg, line, &compose_error_type); - if (res != DW_DLV_OK) { - _dwarf_p_error(NULL, error, compose_error_type); - return (DW_DLV_ERROR); - } - libdwarf_compose_add_string(dbg, macname, len); - res = libdwarf_compose_complete(dbg, &compose_error_type); - if (res != DW_DLV_OK) { - _dwarf_p_error(NULL, error, compose_error_type); - return (DW_DLV_ERROR); - } - return DW_DLV_OK; -} - -int -dwarf_start_macro_file(Dwarf_P_Debug dbg, - Dwarf_Unsigned fileindex, - Dwarf_Unsigned linenumber, Dwarf_Error * error) -{ - size_t length_est; - int res; - int compose_error_type; - - if (dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - length_est = COMMAND_LEN + LINE_LEN + LINE_LEN; - res = libdwarf_compose_begin(dbg, DW_MACINFO_start_file, length_est, - &compose_error_type); - if (res != DW_DLV_OK) { - _dwarf_p_error(NULL, error, compose_error_type); - return (DW_DLV_ERROR); - } - res = libdwarf_compose_add_line(dbg, fileindex, - &compose_error_type); - if (res != DW_DLV_OK) { - _dwarf_p_error(NULL, error, compose_error_type); - return (DW_DLV_ERROR); - } - res = libdwarf_compose_add_line(dbg, linenumber, - &compose_error_type); - if (res != DW_DLV_OK) { - _dwarf_p_error(NULL, error, compose_error_type); - return (DW_DLV_ERROR); - } - return DW_DLV_OK; -} - -int -dwarf_end_macro_file(Dwarf_P_Debug dbg, Dwarf_Error * error) -{ - size_t length_est; - int res; - int compose_error_type; - - if (dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - length_est = COMMAND_LEN; - res = libdwarf_compose_begin(dbg, DW_MACINFO_end_file, length_est, - &compose_error_type); - if (res != DW_DLV_OK) { - _dwarf_p_error(NULL, error, compose_error_type); - return (DW_DLV_ERROR); - } - res = libdwarf_compose_complete(dbg, &compose_error_type); - if (res != DW_DLV_OK) { - _dwarf_p_error(NULL, error, compose_error_type); - return (DW_DLV_ERROR); - } - return DW_DLV_OK; -} - -int -dwarf_vendor_ext(Dwarf_P_Debug dbg, - Dwarf_Unsigned constant, - char *string, Dwarf_Error * error) -{ - size_t len; - size_t length_est; - int res; - int compose_error_type; - - if (dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - if (string == 0) { - _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL); - return (DW_DLV_ERROR); - } - len = strlen(string) + 1; - if (len == 0) { - _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY); - return (DW_DLV_ERROR); - } - length_est = COMMAND_LEN + LINE_LEN + len; - res = libdwarf_compose_begin(dbg, DW_MACINFO_vendor_ext, length_est, - &compose_error_type); - if (res != DW_DLV_OK) { - _dwarf_p_error(NULL, error, compose_error_type); - return (DW_DLV_ERROR); - } - res = libdwarf_compose_add_line(dbg, constant, &compose_error_type); - if (res != DW_DLV_OK) { - _dwarf_p_error(NULL, error, compose_error_type); - return (DW_DLV_ERROR); - } - libdwarf_compose_add_string(dbg, string, len); - libdwarf_compose_complete(dbg, &compose_error_type); - if (res != DW_DLV_OK) { - _dwarf_p_error(NULL, error, compose_error_type); - return (DW_DLV_ERROR); - } - return DW_DLV_OK; -} - - - -int -_dwarf_pro_transform_macro_info_to_disk(Dwarf_P_Debug dbg, - Dwarf_Error * error) -{ - /* Total num of bytes in .debug_macinfo section. */ - Dwarf_Unsigned mac_num_bytes; - - /* Points to first byte of .debug_macinfo buffer. */ - Dwarf_Small *macinfo; - - /* Fills in the .debug_macinfo buffer. */ - Dwarf_Small *macinfo_ptr; - - - /* Used to scan the section data buffers. */ - struct dw_macinfo_block_s *m_prev; - struct dw_macinfo_block_s *m_sect; - - - /* Get the size of the debug_macinfo data */ - mac_num_bytes = 0; - for (m_sect = dbg->de_first_macinfo; m_sect != NULL; - m_sect = m_sect->mb_next) { - mac_num_bytes += m_sect->mb_used_len; - } - /* Tthe final entry has a type code of 0 to indicate It is final - for this CU Takes just 1 byte. */ - mac_num_bytes += 1; - - GET_CHUNK(dbg, dbg->de_elf_sects[DEBUG_MACINFO], - macinfo, (unsigned long) mac_num_bytes, error); - if (macinfo == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (0); - } - - macinfo_ptr = macinfo; - m_prev = 0; - for (m_sect = dbg->de_first_macinfo; m_sect != NULL; - m_sect = m_sect->mb_next) { - memcpy(macinfo_ptr, m_sect->mb_data, m_sect->mb_used_len); - macinfo_ptr += m_sect->mb_used_len; - if (m_prev) { - _dwarf_p_dealloc(dbg, (Dwarf_Small *) m_prev); - m_prev = 0; - } - m_prev = m_sect; - } - *macinfo_ptr = 0; /* the type code of 0 as last entry */ - if (m_prev) { - _dwarf_p_dealloc(dbg, (Dwarf_Small *) m_prev); - m_prev = 0; - } - - dbg->de_first_macinfo = NULL; - dbg->de_current_macinfo = NULL; - - return (int) dbg->de_n_debug_sect; -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_macinfo.h b/usr/src/tools/ctf/dwarf/common/pro_macinfo.h deleted file mode 100644 index 852a0cec1f..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_macinfo.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - - -int _dwarf_pro_transform_macro_info_to_disk(Dwarf_P_Debug dbg, - Dwarf_Error * error); diff --git a/usr/src/tools/ctf/dwarf/common/pro_opaque.h b/usr/src/tools/ctf/dwarf/common/pro_opaque.h deleted file mode 100644 index befc69faa6..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_opaque.h +++ /dev/null @@ -1,484 +0,0 @@ -/* - - Copyright (C) 2000,2002,2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - -#include - -/* - Sgidefs included to define __uint32_t, - a guaranteed 4-byte quantity. -*/ -#include "libdwarfdefs.h" - -#define true 1 -#define false 0 - -/* to identify a cie */ -#define DW_CIE_ID ~(0x0) -#define DW_CIE_VERSION 1 - -/*Dwarf_Word is unsigned word usable for index, count in memory */ -/*Dwarf_Sword is signed word usable for index, count in memory */ -/* The are 32 or 64 bits depending if 64 bit longs or not, which -** fits the ILP32 and LP64 models -** These work equally well with ILP64. -*/ - -typedef unsigned long Dwarf_Word; -typedef long Dwarf_Sword; - - -typedef signed char Dwarf_Sbyte; -typedef unsigned char Dwarf_Ubyte; -typedef signed short Dwarf_Shalf; - -/* - On any change that makes libdwarf producer - incompatible, increment this number. - 1->2->3 ... - -*/ -#define PRO_VERSION_MAGIC 0xdead1 - - -/* these 2 are fixed sizes which must not vary with the -** ILP32/LP64 model. These two stay at 32 bit. -*/ -typedef __uint32_t Dwarf_ufixed; -typedef __int32_t Dwarf_sfixed; - -/* - producer: - This struct is used to hold information about all - debug* sections. On creating a new section, section - names and indices are added to this struct - definition in pro_section.h -*/ -typedef struct Dwarf_P_Section_Data_s *Dwarf_P_Section_Data; - -/* - producer: - This struct is used to hold entries in the include directories - part of statement prologue. Definition in pro_line.h -*/ -typedef struct Dwarf_P_Inc_Dir_s *Dwarf_P_Inc_Dir; - -/* - producer: - This struct holds file entries for the statement prologue. - Defined in pro_line.h -*/ -typedef struct Dwarf_P_F_Entry_s *Dwarf_P_F_Entry; - -/* - producer: - This struct holds information for each cie. Defn in pro_frame.h -*/ -typedef struct Dwarf_P_Cie_s *Dwarf_P_Cie; - -/* - producer: - Struct to hold line number information, different from - Dwarf_Line opaque type. -*/ -typedef struct Dwarf_P_Line_s *Dwarf_P_Line; - -/* - producer: - Struct to hold information about address ranges. -*/ -typedef struct Dwarf_P_Simple_nameentry_s *Dwarf_P_Simple_nameentry; -typedef struct Dwarf_P_Simple_name_header_s *Dwarf_P_Simple_name_header; -typedef struct Dwarf_P_Arange_s *Dwarf_P_Arange; -typedef struct Dwarf_P_Per_Reloc_Sect_s *Dwarf_P_Per_Reloc_Sect; -typedef struct Dwarf_P_Per_Sect_String_Attrs_s *Dwarf_P_Per_Sect_String_Attrs; - -/* Defined to get at the elf section numbers and section name - indices in symtab for the dwarf sections - Must match .rel.* names in _dwarf_rel_section_names - exactly. -*/ -#define DEBUG_INFO 0 -#define DEBUG_LINE 1 -#define DEBUG_ABBREV 2 -#define DEBUG_FRAME 3 -#define DEBUG_ARANGES 4 -#define DEBUG_PUBNAMES 5 -#define DEBUG_STR 6 -#define DEBUG_FUNCNAMES 7 -#define DEBUG_TYPENAMES 8 -#define DEBUG_VARNAMES 9 -#define DEBUG_WEAKNAMES 10 -#define DEBUG_MACINFO 11 -#define DEBUG_LOC 12 - - /* number of debug_* sections not including the relocations */ -#define NUM_DEBUG_SECTIONS DEBUG_LOC + 1 - - -struct Dwarf_P_Die_s { - Dwarf_Unsigned di_offset; /* offset in debug info */ - char *di_abbrev; /* abbreviation */ - Dwarf_Word di_abbrev_nbytes; /* # of bytes in abbrev */ - Dwarf_Tag di_tag; - Dwarf_P_Die di_parent; /* parent of current die */ - Dwarf_P_Die di_child; /* first child */ - /* The last child field makes linking up children an O(1) operation, - See pro_die.c. */ - Dwarf_P_Die di_last_child; - Dwarf_P_Die di_left; /* left sibling */ - Dwarf_P_Die di_right; /* right sibling */ - Dwarf_P_Attribute di_attrs; /* list of attributes */ - Dwarf_P_Attribute di_last_attr; /* last attribute */ - int di_n_attr; /* number of attributes */ - Dwarf_P_Debug di_dbg; /* For memory management */ - Dwarf_Unsigned di_marker; /* used to attach symbols to dies */ -}; - - -/* producer fields */ -struct Dwarf_P_Attribute_s { - Dwarf_Half ar_attribute; /* Attribute Value. */ - Dwarf_Half ar_attribute_form; /* Attribute Form. */ - Dwarf_P_Die ar_ref_die; /* die pointer if form ref */ - char *ar_data; /* data, format given by form */ - Dwarf_Unsigned ar_nbytes; /* no. of bytes of data */ - Dwarf_Unsigned ar_rel_symidx; /* when attribute has a - relocatable value, holds - index of symbol in SYMTAB */ - Dwarf_Ubyte ar_rel_type; /* relocation type */ - Dwarf_Word ar_rel_offset; /* Offset of relocation within block */ - char ar_reloc_len; /* Number of bytes that relocation - applies to. 4 or 8. Unused and may - be 0 if if ar_rel_type is - R_MIPS_NONE */ - Dwarf_P_Attribute ar_next; -}; - -/* A block of .debug_macinfo data: this forms a series of blocks. -** Each macinfo input is compressed immediately and put into -** the current block if room, else a newblock allocated. -** The space allocation is such that the block and the macinfo -** data are one malloc block: free with a pointer to this and the -** mb_data is freed automatically. -** Like the struct hack, but legal ANSI C. -*/ -struct dw_macinfo_block_s { - struct dw_macinfo_block_s *mb_next; - unsigned long mb_avail_len; - unsigned long mb_used_len; - unsigned long mb_macinfo_data_space_len; - char *mb_data; /* original malloc ptr. */ -}; - -/* dwarf_sn_kind is for the array of similarly-treated - name -> cu ties -*/ -enum dwarf_sn_kind { dwarf_snk_pubname, dwarf_snk_funcname, - dwarf_snk_weakname, dwarf_snk_typename, - dwarf_snk_varname, - dwarf_snk_entrycount /* this one must be last */ -}; - - - -/* The calls to add a varname etc use a list of - these as the list. -*/ -struct Dwarf_P_Simple_nameentry_s { - Dwarf_P_Die sne_die; - char *sne_name; - int sne_name_len; - Dwarf_P_Simple_nameentry sne_next; -}; - -/* An array of these, each of which heads a list - of Dwarf_P_Simple_nameentry -*/ -struct Dwarf_P_Simple_name_header_s { - Dwarf_P_Simple_nameentry sn_head; - Dwarf_P_Simple_nameentry sn_tail; - Dwarf_Signed sn_count; - - /* length that will be generated, not counting fixed header or - trailer */ - Dwarf_Signed sn_net_len; -}; -typedef int (*_dwarf_pro_reloc_name_func_ptr) (Dwarf_P_Debug dbg, - int sec_index, - Dwarf_Unsigned offset,/* r_offset */ - Dwarf_Unsigned symidx, - enum Dwarf_Rel_Type type, - int reltarget_length); - -typedef int (*_dwarf_pro_reloc_length_func_ptr) (Dwarf_P_Debug dbg, - int sec_index, Dwarf_Unsigned offset,/* r_offset */ - Dwarf_Unsigned start_symidx, - Dwarf_Unsigned end_symidx, - enum Dwarf_Rel_Type type, - int reltarget_length); -typedef int (*_dwarf_pro_transform_relocs_func_ptr) (Dwarf_P_Debug dbg, - Dwarf_Signed * - new_sec_count); - -/* - Each slot in a block of slots could be: - a binary stream relocation entry (32 or 64bit relocation data) - a SYMBOLIC relocation entry. - During creation sometimes we create multiple chained blocks, - but sometimes we create a single long block. - Before returning reloc data to caller, - we switch to a single, long-enough, - block. - - We make counters here Dwarf_Unsigned so that we - get sufficient alignment. Since we use space after - the struct (at malloc time) for user data which - must have Dwarf_Unsigned alignment, this - struct must have that alignment too. -*/ -struct Dwarf_P_Relocation_Block_s { - Dwarf_Unsigned rb_slots_in_block; /* slots in block, as created */ - Dwarf_Unsigned rb_next_slot_to_use; /* counter, start at 0. */ - struct Dwarf_P_Relocation_Block_s *rb_next; - char *rb_where_to_add_next; /* pointer to next slot (might be past - end, depending on - rb_next_slot_to_use) */ - char *rb_data; /* data area */ -}; - -/* One of these per potential relocation section - So one per actual dwarf section. - Left zeroed when not used (some sections have - no relocations). -*/ -struct Dwarf_P_Per_Reloc_Sect_s { - unsigned long pr_reloc_total_count; /* total number of entries - across all blocks */ - - unsigned long pr_slots_per_block_to_alloc; /* at Block alloc, this - is the default number of slots to use */ - - int pr_sect_num_of_reloc_sect; /* sect number returned by - de_callback_func() or de_callback_func_b() call, this is the sect - number of the relocation section. */ - - /* singly-linked list. add at and ('last') with count of blocks */ - struct Dwarf_P_Relocation_Block_s *pr_first_block; - struct Dwarf_P_Relocation_Block_s *pr_last_block; - unsigned long pr_block_count; -}; - -#define DEFAULT_SLOTS_PER_BLOCK 3 - -typedef struct memory_list_s { - struct memory_list_s *prev; - struct memory_list_s *next; -} memory_list_t; - -struct Dwarf_P_Per_Sect_String_Attrs_s { - int sect_sa_section_number; - unsigned sect_sa_n_alloc; - unsigned sect_sa_n_used; - Dwarf_P_String_Attr sect_sa_list; -}; - -/* Fields used by producer */ -struct Dwarf_P_Debug_s { - /* used to catch dso passing dbg to another DSO with incompatible - version of libdwarf See PRO_VERSION_MAGIC */ - int de_version_magic_number; - - Dwarf_Handler de_errhand; - Dwarf_Ptr de_errarg; - - /* Call back function, used to create .debug* sections. Provided - by user. Only of these used per dbg. */ - Dwarf_Callback_Func de_callback_func; - Dwarf_Callback_Func_b de_callback_func_b; - - /* Flags from producer_init call */ - Dwarf_Unsigned de_flags; - - /* This holds information on debug section stream output, including - the stream data */ - Dwarf_P_Section_Data de_debug_sects; - - /* Pointer to the 'current active' section */ - Dwarf_P_Section_Data de_current_active_section; - - /* Number of debug data streams globs. */ - Dwarf_Word de_n_debug_sect; - - /* File entry information, null terminated singly-linked list */ - Dwarf_P_F_Entry de_file_entries; - Dwarf_P_F_Entry de_last_file_entry; - Dwarf_Unsigned de_n_file_entries; - - /* Has the directories used to search for source files */ - Dwarf_P_Inc_Dir de_inc_dirs; - Dwarf_P_Inc_Dir de_last_inc_dir; - Dwarf_Unsigned de_n_inc_dirs; - - /* Has all the line number info for the stmt program */ - Dwarf_P_Line de_lines; - Dwarf_P_Line de_last_line; - - /* List of cie's for the debug unit */ - Dwarf_P_Cie de_frame_cies; - Dwarf_P_Cie de_last_cie; - Dwarf_Unsigned de_n_cie; - - /* Singly-linked list of fde's for the debug unit */ - Dwarf_P_Fde de_frame_fdes; - Dwarf_P_Fde de_last_fde; - Dwarf_Unsigned de_n_fde; - - /* First die, leads to all others */ - Dwarf_P_Die de_dies; - - /* Pointer to list of strings */ - char *de_strings; - - /* Pointer to chain of aranges */ - Dwarf_P_Arange de_arange; - Dwarf_P_Arange de_last_arange; - Dwarf_Sword de_arange_count; - - /* macinfo controls. */ - /* first points to beginning of the list during creation */ - struct dw_macinfo_block_s *de_first_macinfo; - - /* current points to the current, unfilled, block */ - struct dw_macinfo_block_s *de_current_macinfo; - - /* Pointer to the first section, to support reset_section_bytes */ - Dwarf_P_Section_Data de_first_debug_sect; - - /* handles pubnames, weaknames, etc. See dwarf_sn_kind in - pro_opaque.h */ - struct Dwarf_P_Simple_name_header_s - de_simple_name_headers[dwarf_snk_entrycount]; - - /* relocation data. not all sections will actally have relocation - info, of course */ - struct Dwarf_P_Per_Reloc_Sect_s de_reloc_sect[NUM_DEBUG_SECTIONS]; - int de_reloc_next_to_return; /* iterator on reloc sections - (SYMBOLIC output) */ - - /* used in remembering sections */ - int de_elf_sects[NUM_DEBUG_SECTIONS]; /* elf sect number of - the section itself, DEBUG_LINE for example */ - - Dwarf_Unsigned de_sect_name_idx[NUM_DEBUG_SECTIONS]; /* section - name index or handle for the name of the symbol for - DEBUG_LINE for example */ - - int de_offset_reloc; /* offset reloc type, R_MIPS_32 for - example. Specific to the ABI being - produced. Relocates offset size - field */ - int de_exc_reloc; /* reloc type specific to exception - table relocs. */ - int de_ptr_reloc; /* standard reloc type, R_MIPS_32 for - example. Specific to the ABI being - produced. relocates pointer size - field */ - - unsigned char de_offset_size; /* section offset. Here to - avoid test of abi in macro - at run time MIPS -n32 4, - -64 8. */ - - unsigned char de_pointer_size; /* size of pointer in target. - Here to avoid test of abi in - macro at run time MIPS -n32 - 4, -64 is 8. */ - - unsigned char de_is_64bit; /* non-zero if is 64bit. Else 32 bit: - used for passing this info as a flag - */ - unsigned char de_relocation_record_size; /* reloc record size - varies by ABI and - relocation-output - method (stream or - symbolic) */ - - unsigned char de_64bit_extension; /* non-zero if creating 64 bit - offsets using dwarf2-99 - extension proposal */ - - int de_ar_data_attribute_form; /* data8, data4 abi dependent */ - int de_ar_ref_attr_form; /* ref8 ref4 , abi dependent */ - - /* simple name relocations */ - _dwarf_pro_reloc_name_func_ptr de_reloc_name; - - /* relocations for a length, requiring a pair of symbols */ - _dwarf_pro_reloc_length_func_ptr de_reloc_pair; - - _dwarf_pro_transform_relocs_func_ptr de_transform_relocs_to_disk; - - /* following used for macro buffers */ - unsigned long de_compose_avail; - unsigned long de_compose_used_len; - - unsigned char de_same_endian; - void *(*de_copy_word) (void *, const void *, size_t); - - /* Add new fields at the END of this struct to preserve some hope - of sensible behavior on dbg passing between DSOs linked with - mismatched libdwarf producer versions. */ - - Dwarf_P_Marker de_markers; /* pointer to array of markers */ - unsigned de_marker_n_alloc; - unsigned de_marker_n_used; - int de_sect_sa_next_to_return; /* Iterator on sring attrib sects */ - /* String attributes data of each section. */ - struct Dwarf_P_Per_Sect_String_Attrs_s de_sect_string_attr[NUM_DEBUG_SECTIONS]; -}; - -#define CURRENT_VERSION_STAMP 2 - -Dwarf_Unsigned _dwarf_add_simple_name_entry(Dwarf_P_Debug dbg, - Dwarf_P_Die die, - char *entry_name, - enum dwarf_sn_kind - entrykind, - Dwarf_Error * error); - - -#define DISTINGUISHED_VALUE 0xffffffff /* 64bit extension flag */ diff --git a/usr/src/tools/ctf/dwarf/common/pro_pubnames.c b/usr/src/tools/ctf/dwarf/common/pro_pubnames.c deleted file mode 100644 index e07fe35943..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_pubnames.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#include -#include -#ifdef HAVE_ELFACCESS_H -#include -#endif -#include "pro_incl.h" -#include "pro_section.h" - - -/* - This function adds another public name to the - list of public names for the given Dwarf_P_Debug. - It returns 0 on error, and 1 otherwise. -*/ - -Dwarf_Unsigned -dwarf_add_pubname(Dwarf_P_Debug dbg, - Dwarf_P_Die die, - char *pubname_name, Dwarf_Error * error) -{ - return - _dwarf_add_simple_name_entry(dbg, die, pubname_name, - dwarf_snk_pubname, error); -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_reloc.c b/usr/src/tools/ctf/dwarf/common/pro_reloc.c deleted file mode 100644 index 66f16acbd0..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_reloc.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2008-2010 David Anderson, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#include -#include -/*#include */ -#include "pro_incl.h" - - -/*Do initial alloc of newslots slots. - Fails only if malloc fails. - - Supposed to be called before any relocs allocated. - Ignored if after any allocated. - - Part of an optimization, so that for a known 'newslots' - relocations count we can preallocate the right size block. - Called from just 2 places. - - returns DW_DLV_OK or DW_DLV_ERROR -*/ -int -_dwarf_pro_pre_alloc_n_reloc_slots(Dwarf_P_Debug dbg, - int rel_sec_index, - Dwarf_Unsigned newslots) -{ - unsigned long len = 0; - struct Dwarf_P_Relocation_Block_s *data = 0; - Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[rel_sec_index]; - unsigned long slots_in_blk = (unsigned long) newslots; - unsigned long rel_rec_size = dbg->de_relocation_record_size; - - if (prel->pr_first_block) - return DW_DLV_OK; /* do nothing */ - - len = sizeof(struct Dwarf_P_Relocation_Block_s) + - slots_in_blk * rel_rec_size; - - - data = (struct Dwarf_P_Relocation_Block_s *) - _dwarf_p_get_alloc(dbg, len); - if (!data) { - return DW_DLV_ERROR; - } - data->rb_slots_in_block = slots_in_blk; /* could use default - here, as fallback in - case our origininal - estimate wrong. When - we call this we - presumably know what - we are doing, so - keep this count for - now */ - data->rb_next_slot_to_use = 0; - data->rb_where_to_add_next = - ((char *) data) + sizeof(struct Dwarf_P_Relocation_Block_s); - data->rb_data = data->rb_where_to_add_next; - - prel->pr_first_block = data; - prel->pr_last_block = data; - prel->pr_block_count = 1; - - - return DW_DLV_OK; -} - - -/*Do alloc of slots. - Fails only if malloc fails. - - Only allocator used. - - returns DW_DLV_OK or DW_DLV_ERROR -*/ -int -_dwarf_pro_alloc_reloc_slots(Dwarf_P_Debug dbg, int rel_sec_index) -{ - unsigned long len = 0; - struct Dwarf_P_Relocation_Block_s *data = 0; - Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[rel_sec_index]; - unsigned long slots_in_blk = prel->pr_slots_per_block_to_alloc; - unsigned long rel_rec_size = dbg->de_relocation_record_size; - - len = sizeof(struct Dwarf_P_Relocation_Block_s) + - slots_in_blk * rel_rec_size; - - data = (struct Dwarf_P_Relocation_Block_s *) - _dwarf_p_get_alloc(dbg, len); - if (!data) { - return DW_DLV_ERROR; - } - - if (prel->pr_first_block) { - prel->pr_last_block->rb_next = data; - prel->pr_last_block = data; - prel->pr_block_count += 1; - - } else { - - prel->pr_first_block = data; - prel->pr_last_block = data; - prel->pr_block_count = 1; - } - - data->rb_slots_in_block = slots_in_blk; - data->rb_next_slot_to_use = 0; - data->rb_where_to_add_next = - ((char *) data) + sizeof(struct Dwarf_P_Relocation_Block_s); - data->rb_data = data->rb_where_to_add_next; - - return DW_DLV_OK; - -} - -/* - Reserve a slot. return DW_DLV_OK if succeeds. - - Return DW_DLV_ERROR if fails (malloc error). - - Use the relrec_to_fill to pass back a pointer to - a slot space to use. -*/ -int -_dwarf_pro_reloc_get_a_slot(Dwarf_P_Debug dbg, - int base_sec_index, void **relrec_to_fill) -{ - struct Dwarf_P_Relocation_Block_s *data = 0; - Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[base_sec_index]; - unsigned long rel_rec_size = dbg->de_relocation_record_size; - - char *ret_addr = 0; - - data = prel->pr_last_block; - if ((data == 0) || - (data->rb_next_slot_to_use >= data->rb_slots_in_block)) { - int res; - - res = _dwarf_pro_alloc_reloc_slots(dbg, base_sec_index); - if (res != DW_DLV_OK) { - return res; - } - } - - data = prel->pr_last_block; - /* now we have an empty slot */ - ret_addr = data->rb_where_to_add_next; - - data->rb_where_to_add_next += rel_rec_size; - data->rb_next_slot_to_use += 1; - - prel->pr_reloc_total_count += 1; - - *relrec_to_fill = (void *) ret_addr; - - return DW_DLV_OK; - -} - -/* - On success returns count of - .rel.* sections that are symbolic - thru count_of_relocation_sections. - - On success, returns DW_DLV_OK. - - If this is not a 'symbolic' run, returns - DW_DLV_NO_ENTRY. - - No errors are possible. - - - - -*/ - - /*ARGSUSED*/ int -dwarf_get_relocation_info_count(Dwarf_P_Debug dbg, - Dwarf_Unsigned * - count_of_relocation_sections, - int *drd_buffer_version, - Dwarf_Error * error) -{ - if (dbg->de_flags & DW_DLC_SYMBOLIC_RELOCATIONS) { - int i; - unsigned int count = 0; - - for (i = 0; i < NUM_DEBUG_SECTIONS; ++i) { - if (dbg->de_reloc_sect[i].pr_reloc_total_count > 0) { - ++count; - } - } - *count_of_relocation_sections = (Dwarf_Unsigned) count; - *drd_buffer_version = DWARF_DRD_BUFFER_VERSION; - return DW_DLV_OK; - } - return DW_DLV_NO_ENTRY; -} - -int -dwarf_get_relocation_info(Dwarf_P_Debug dbg, - Dwarf_Signed * elf_section_index, - Dwarf_Signed * elf_section_index_link, - Dwarf_Unsigned * relocation_buffer_count, - Dwarf_Relocation_Data * reldata_buffer, - Dwarf_Error * error) -{ - int next = dbg->de_reloc_next_to_return; - - if (dbg->de_flags & DW_DLC_SYMBOLIC_RELOCATIONS) { - int i; - - for (i = next; i < NUM_DEBUG_SECTIONS; ++i) { - Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[i]; - - if (prel->pr_reloc_total_count > 0) { - dbg->de_reloc_next_to_return = i + 1; - - - /* ASSERT: prel->.pr_block_count == 1 */ - - *elf_section_index = prel->pr_sect_num_of_reloc_sect; - *elf_section_index_link = dbg->de_elf_sects[i]; - *relocation_buffer_count = prel->pr_reloc_total_count; - *reldata_buffer = (Dwarf_Relocation_Data) - (prel->pr_first_block->rb_data); - return DW_DLV_OK; - } - } - DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, DW_DLV_ERROR); - } - return DW_DLV_NO_ENTRY; -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_reloc.h b/usr/src/tools/ctf/dwarf/common/pro_reloc.h deleted file mode 100644 index d2e6c67357..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_reloc.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - - -int _dwarf_pro_pre_alloc_n_reloc_slots(Dwarf_P_Debug dbg, - int rel_sec_index, - Dwarf_Unsigned newslots); - -int _dwarf_pro_alloc_reloc_slots(Dwarf_P_Debug dbg, int rel_sec_index); - -int _dwarf_pro_reloc_get_a_slot(Dwarf_P_Debug dbg, - int base_sec_index, - void **relrec_to_fill); diff --git a/usr/src/tools/ctf/dwarf/common/pro_reloc_stream.c b/usr/src/tools/ctf/dwarf/common/pro_reloc_stream.c deleted file mode 100644 index 459779ceda..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_reloc_stream.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - - Copyright (C) 2000,2001,2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. - Portions Copyright 2008-2010 David Anderson, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#include -#include -#ifdef HAVE_ELFACCESS_H -#include -#else -/* Set r_info as defined by ELF generic ABI */ -#define Set_REL32_info(r,s,t) ((r).r_info = ELF32_R_INFO(s,t)) -#define Set_REL64_info(r,s,t) ((r).r_info = ELF64_R_INFO(s,t)) -#endif -#include "pro_incl.h" -#include "pro_section.h" -#include "pro_reloc.h" -#include "pro_reloc_stream.h" - -/* - Return DW_DLV_ERROR on malloc error or reltarget_length error. - Return DW_DLV_OK otherwise - - - -*/ - /*ARGSUSED*/ int -_dwarf_pro_reloc_name_stream64(Dwarf_P_Debug dbg, - int base_sec_index, - Dwarf_Unsigned offset, /* r_offset of reloc */ - Dwarf_Unsigned symidx, - enum Dwarf_Rel_Type type, - int reltarget_length) -{ -#if HAVE_ELF64_GETEHDR - REL64 *elf64_reloc = 0; - void *relrec_to_fill = 0; - int res = 0; - int rel_type = 0; - - res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index, - &relrec_to_fill); - if (res != DW_DLV_OK) - return res; - - - if (type == dwarf_drt_data_reloc) { - if (reltarget_length == dbg->de_offset_size) { - rel_type = dbg->de_offset_reloc; - } else if (reltarget_length == dbg->de_pointer_size) { - rel_type = dbg->de_ptr_reloc; - } else { - return DW_DLV_ERROR; - } - } else if (type == dwarf_drt_segment_rel) { - rel_type = dbg->de_exc_reloc; - } else { - /* We are in trouble: improper use of stream relocations. - Someone else will diagnose */ - rel_type = 0; - } - - elf64_reloc = (REL64 *)relrec_to_fill; - elf64_reloc->r_offset = offset; - Set_REL64_info(*elf64_reloc, symidx, rel_type); - return DW_DLV_OK; -#else /* !HAVE_ELF64_GETEHDR */ - return DW_DLV_ERROR; -#endif /* #if HAVE_ELF64_GETEHDR */ -} - -/* - Return DW_DLV_ERROR on malloc error or reltarget_length error. - Return DW_DLV_OK otherwise - a binary reloc: 32bit ABI -*/ -int -_dwarf_pro_reloc_name_stream32(Dwarf_P_Debug dbg, int base_sec_index, - Dwarf_Unsigned offset, /* r_offset of reloc */ - Dwarf_Unsigned symidx, - enum Dwarf_Rel_Type type, - int reltarget_length) -{ - REL32 *elf32_reloc = 0; - void *relrec_to_fill = 0; - int res = 0; - int rel_type = 0; - - res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index, - &relrec_to_fill); - if (res != DW_DLV_OK) - return res; - if (type == dwarf_drt_data_reloc) { - if (reltarget_length == dbg->de_offset_size) { - rel_type = dbg->de_offset_reloc; - } else if (reltarget_length == dbg->de_pointer_size) { - rel_type = dbg->de_ptr_reloc; - } else { - return DW_DLV_ERROR; - } - } else if (type == dwarf_drt_segment_rel) { - rel_type = dbg->de_exc_reloc; - } else { - /* We are in trouble: improper use of stream relocations. - Someone else will diagnose */ - rel_type = 0; - } - - elf32_reloc = (REL32*)relrec_to_fill; - elf32_reloc->r_offset = (Elf32_Addr) offset; - Set_REL32_info(*elf32_reloc, (Dwarf_Word) symidx, rel_type); - return DW_DLV_OK; - - /* get a slot, fill in the slot entry */ -} - - - -/* - Return DW_DLV_OK. - Never can really do anything: lengths cannot - be represented as end-start in a stream. - -*/ - /*ARGSUSED*/ int -_dwarf_pro_reloc_length_stream(Dwarf_P_Debug dbg, - int base_sec_index, - Dwarf_Unsigned offset, /* r_offset of reloc */ - Dwarf_Unsigned start_symidx, - Dwarf_Unsigned end_symidx, - enum Dwarf_Rel_Type type, - int reltarget_length) -{ - /* get a slot, fill in the slot entry */ - return DW_DLV_OK; -} - - -/* - Ensure each stream is a single buffer and - add that single buffer to the set of stream buffers. - - By creating a new buffer and copying if necessary. - - Free the input set of buffers if we consolidate. - Return -1 on error (malloc failure) - - - Return DW_DLV_OK on success. Any other return indicates - malloc failed. - -*/ -int -_dwarf_stream_relocs_to_disk(Dwarf_P_Debug dbg, - Dwarf_Signed * new_sec_count) -{ - unsigned long total_size = 0; - Dwarf_Small *data = 0; - int sec_index = 0; - unsigned long i = 0; - Dwarf_Error err = 0; - Dwarf_Error *error = &err; - - Dwarf_Signed sec_count = 0; - - Dwarf_P_Per_Reloc_Sect p_reloc = &dbg->de_reloc_sect[0]; - - for (i = 0; i < NUM_DEBUG_SECTIONS; ++i, ++p_reloc) { - unsigned long ct = p_reloc->pr_reloc_total_count; - unsigned len = 0; - struct Dwarf_P_Relocation_Block_s *p_blk = 0; - struct Dwarf_P_Relocation_Block_s *p_blk_last = 0; - Dwarf_P_Per_Reloc_Sect prb = 0; - - if (ct == 0) { - continue; - } - prb = &dbg->de_reloc_sect[i]; - len = dbg->de_relocation_record_size; - ++sec_count; - - total_size = ct * len; - sec_index = prb->pr_sect_num_of_reloc_sect; - if (sec_index == 0) { - /* Call de_callback_func or de_callback_func_b, getting - section number of reloc section. */ - int rel_section_index = 0; - Dwarf_Unsigned name_idx = 0; - int int_name = 0; - int err = 0; - - if (dbg->de_callback_func_b) { - rel_section_index = - dbg->de_callback_func_b(_dwarf_rel_section_names[i], - /* size */ - dbg->de_relocation_record_size, - /* type */ SHT_REL, - /* flags */ 0, - /* link to symtab, which we cannot - know */ 0, - /* info == link to sec rels apply to - */ - dbg->de_elf_sects[i], - &name_idx, &err); - } else { - rel_section_index = - dbg->de_callback_func(_dwarf_rel_section_names[i], - /* size */ - dbg->de_relocation_record_size, - /* type */ SHT_REL, - /* flags */ 0, - /* link to symtab, which we cannot - know */ 0, - /* info == link to sec rels apply to */ - dbg->de_elf_sects[i], &int_name, &err); - name_idx = int_name; - } - if (rel_section_index == -1) { - { - _dwarf_p_error(dbg, error, DW_DLE_ELF_SECT_ERR); - return (DW_DLV_ERROR); - } - - } - prb->pr_sect_num_of_reloc_sect = rel_section_index; - sec_index = rel_section_index; - } - GET_CHUNK(dbg, sec_index, data, total_size, &err); - p_blk = p_reloc->pr_first_block; - - /* following loop executes at least once. Effects the - consolidation to a single block or, if already a single - block, simply copies to the output buffer. And frees the - input block. The new block is in the de_debug_sects list. */ - while (p_blk) { - - unsigned long len = - p_blk->rb_where_to_add_next - p_blk->rb_data; - - memcpy(data, p_blk->rb_data, len); - - - data += len; - - p_blk_last = p_blk; - p_blk = p_blk->rb_next; - - _dwarf_p_dealloc(dbg, (Dwarf_Small *) p_blk_last); - } - /* ASSERT: sum of len copied == total_size */ - - /* - We have copied the input, now drop the pointers to it. For - debugging, leave the other data untouched. */ - p_reloc->pr_first_block = 0; - p_reloc->pr_last_block = 0; - } - - *new_sec_count = sec_count; - return DW_DLV_OK; -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_reloc_stream.h b/usr/src/tools/ctf/dwarf/common/pro_reloc_stream.h deleted file mode 100644 index 892ea5baf3..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_reloc_stream.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - - -int _dwarf_pro_reloc_name_stream64(Dwarf_P_Debug dbg, int base_sec_index, Dwarf_Unsigned offset, /* r_offset - of - reloc - */ - Dwarf_Unsigned symidx, - enum Dwarf_Rel_Type, - int reltarget_length); -int _dwarf_pro_reloc_name_stream32(Dwarf_P_Debug dbg, int base_sec_index, Dwarf_Unsigned offset, /* r_offset - of - reloc - */ - Dwarf_Unsigned symidx, - enum Dwarf_Rel_Type, - int reltarget_length); -int _dwarf_pro_reloc_length_stream(Dwarf_P_Debug dbg, int base_sec_index, Dwarf_Unsigned offset, /* r_offset - of - reloc - */ - Dwarf_Unsigned start_symidx, - Dwarf_Unsigned end_symidx, - enum Dwarf_Rel_Type, - int reltarget_length); - -int _dwarf_stream_relocs_to_disk(Dwarf_P_Debug dbg, - Dwarf_Signed * new_sec_count); diff --git a/usr/src/tools/ctf/dwarf/common/pro_reloc_symbolic.c b/usr/src/tools/ctf/dwarf/common/pro_reloc_symbolic.c deleted file mode 100644 index 22080a00cd..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_reloc_symbolic.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#include -#include -/*#include */ -#include "pro_incl.h" -#include "pro_section.h" -#include "pro_reloc.h" -#include "pro_reloc_symbolic.h" - -/* - Return DW_DLV_ERROR on malloc error. - Return DW_DLV_OK otherwise -*/ - -int -_dwarf_pro_reloc_name_symbolic(Dwarf_P_Debug dbg, - int base_sec_index, - Dwarf_Unsigned offset, /* r_offset of reloc */ - Dwarf_Unsigned symidx, - enum Dwarf_Rel_Type type, - int reltarget_length) -{ - /* get a slot, fill in the slot entry */ - void *relrec_to_fill = 0; - int res = 0; - struct Dwarf_Relocation_Data_s *slotp; - - res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index, - &relrec_to_fill); - if (res != DW_DLV_OK) - return res; - slotp = (struct Dwarf_Relocation_Data_s *) relrec_to_fill; - slotp->drd_type = type; - slotp->drd_length = reltarget_length; - slotp->drd_offset = offset; - slotp->drd_symbol_index = symidx; - return DW_DLV_OK; -} - - - -/* - Return DW_DLV_ERROR on malloc error. - Return DW_DLV_OK otherwise -*/ -int -_dwarf_pro_reloc_length_symbolic(Dwarf_P_Debug dbg, - int base_sec_index, - Dwarf_Unsigned offset, /* r_offset of reloc */ - Dwarf_Unsigned start_symidx, - Dwarf_Unsigned end_symidx, - enum Dwarf_Rel_Type type, - int reltarget_length) -{ - /* get a slot, fill in the slot entry */ - void *relrec_to_fill = 0; - int res = 0; - struct Dwarf_Relocation_Data_s *slotp1 = 0; - struct Dwarf_Relocation_Data_s *slotp2 = 0; - - res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index, - &relrec_to_fill); - if (res != DW_DLV_OK) - return res; - slotp1 = (struct Dwarf_Relocation_Data_s *) relrec_to_fill; - res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index, - &relrec_to_fill); - if (res != DW_DLV_OK) - return res; - slotp2 = (struct Dwarf_Relocation_Data_s *) relrec_to_fill; - - /* ASSERT: type == dwarf_drt_first_of_length_type_pair */ - slotp1->drd_type = type; - slotp1->drd_length = reltarget_length; - slotp1->drd_offset = offset; - slotp1->drd_symbol_index = start_symidx; - - slotp2->drd_type = dwarf_drt_second_of_length_pair; - slotp2->drd_length = reltarget_length; - slotp2->drd_offset = offset; - slotp2->drd_symbol_index = end_symidx; - return DW_DLV_OK; -} - -/* - Reset whatever fields of Dwarf_P_Per_Reloc_Sect_s - we must to allow adding a fresh new single - block easily (block consolidation use only). - -*/ -static void -_dwarf_reset_reloc_sect_info(struct Dwarf_P_Per_Reloc_Sect_s *pblk, - unsigned long ct) -{ - - - /* Do not zero pr_sect_num_of_reloc_sect */ - pblk->pr_reloc_total_count = 0; - pblk->pr_first_block = 0; - pblk->pr_last_block = 0; - pblk->pr_block_count = 0; - pblk->pr_slots_per_block_to_alloc = ct; -} - -/* - Ensure each stream is a single buffer and - add that single buffer to the set of stream buffers. - - By creating a new buffer and copying if necessary. - (If > 1 block, reduce to 1 block) - - Free the input set of buffers if we consolidate. - - We pass back *new_sec_count as zero because we - are not creating normal sections for a .o, but - symbolic relocations, separately counted. - - Return -1 on error (malloc failure) - - Return DW_DLV_OK on success. Any other return indicates - malloc failed. -*/ -int -_dwarf_symbolic_relocs_to_disk(Dwarf_P_Debug dbg, - Dwarf_Signed * new_sec_count) -{ - /* unsigned long total_size =0; */ - Dwarf_Small *data = 0; - int sec_index = 0; - int res = 0; - unsigned long i = 0; - Dwarf_Error error = 0; - Dwarf_Signed sec_count = 0; - Dwarf_P_Per_Reloc_Sect p_reloc = &dbg->de_reloc_sect[0]; - - for (i = 0; i < NUM_DEBUG_SECTIONS; ++i, ++p_reloc) { - unsigned long ct = p_reloc->pr_reloc_total_count; - struct Dwarf_P_Relocation_Block_s *p_blk; - struct Dwarf_P_Relocation_Block_s *p_blk_last; - int err; - if (ct == 0) { - continue; - } - - /* len = dbg->de_relocation_record_size; */ - ++sec_count; - - /* total_size = ct *len; */ - sec_index = p_reloc->pr_sect_num_of_reloc_sect; - if (sec_index == 0) { - /* Call de_callback_func or de_callback_func_b, - getting section number of reloc section. */ - int rel_section_index = 0; - int int_name = 0; - Dwarf_Unsigned name_idx = 0; - - /* - This is a bit of a fake, as we do not really have true - elf sections at all. Just the data such might contain. - But this lets the caller eventually link things - together: without this call we would not know what rel - data goes with what section when we are asked for the - real arrays. */ - - if (dbg->de_callback_func_b) { - rel_section_index = - dbg->de_callback_func_b(_dwarf_rel_section_names[i], - dbg->de_relocation_record_size, - /* type */ SHT_REL, - /* flags */ 0, - /* link to symtab, which we cannot - know */ SHN_UNDEF, - /* sec rels apply to */ - dbg->de_elf_sects[i], - &name_idx, &err); - } else { - rel_section_index = - dbg->de_callback_func(_dwarf_rel_section_names[i], - dbg->de_relocation_record_size, - /* type */ SHT_REL, - /* flags */ 0, - /* link to symtab, which we cannot - know */ SHN_UNDEF, - /* sec rels apply to, in elf, sh_info */ - dbg->de_elf_sects[i], &int_name, &err); - name_idx = int_name; - } - if (rel_section_index == -1) { - { - _dwarf_p_error(dbg, &error, DW_DLE_ELF_SECT_ERR); - return (DW_DLV_ERROR); - } - } - p_reloc->pr_sect_num_of_reloc_sect = rel_section_index; - sec_index = rel_section_index; - } - - p_blk = p_reloc->pr_first_block; - - if (p_reloc->pr_block_count > 1) { - struct Dwarf_P_Relocation_Block_s *new_blk; - - /* HACK , not normal interfaces, trashing p_reloc current - contents! */ - _dwarf_reset_reloc_sect_info(p_reloc, ct); - - /* Creating new single block for all 'ct' entries */ - res = _dwarf_pro_pre_alloc_n_reloc_slots(dbg, (int) i, ct); - if (res != DW_DLV_OK) { - return res; - } - new_blk = p_reloc->pr_first_block; - - data = (Dwarf_Small *) new_blk->rb_data; - - /* The following loop does the consolidation to a single - block and frees the input block(s). */ - do { - unsigned long len = - p_blk->rb_where_to_add_next - p_blk->rb_data; - memcpy(data, p_blk->rb_data, len); - data += len; - p_blk_last = p_blk; - p_blk = p_blk->rb_next; - _dwarf_p_dealloc(dbg, (Dwarf_Small *) p_blk_last); - } while (p_blk); - /* ASSERT: sum of len copied == total_size */ - new_blk->rb_next_slot_to_use = ct; - new_blk->rb_where_to_add_next = (char *) data; - p_reloc->pr_reloc_total_count = ct; - - /* have now created a single block, but no change in slots - used (pr_reloc_total_count) */ - } - } - *new_sec_count = 0; - return DW_DLV_OK; -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_reloc_symbolic.h b/usr/src/tools/ctf/dwarf/common/pro_reloc_symbolic.h deleted file mode 100644 index 3d03a47863..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_reloc_symbolic.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - -int _dwarf_pro_reloc_name_symbolic(Dwarf_P_Debug dbg, int base_sec_index, Dwarf_Unsigned offset, /* r_offset - of - reloc - */ - Dwarf_Unsigned symidx, - enum Dwarf_Rel_Type, - int reltarget_length); -int - _dwarf_pro_reloc_length_symbolic(Dwarf_P_Debug dbg, int base_sec_index, Dwarf_Unsigned offset, /* r_offset - of - reloc - */ - Dwarf_Unsigned start_symidx, - Dwarf_Unsigned end_symidx, - enum Dwarf_Rel_Type, - int reltarget_length); - -int _dwarf_symbolic_relocs_to_disk(Dwarf_P_Debug dbg, - Dwarf_Signed * new_sec_count); diff --git a/usr/src/tools/ctf/dwarf/common/pro_section.c b/usr/src/tools/ctf/dwarf/common/pro_section.c deleted file mode 100644 index 6503c2cf09..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_section.c +++ /dev/null @@ -1,2221 +0,0 @@ -/* - - Copyright (C) 2000,2004,2006 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. - Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* - SGI has moved from the Crittenden Lane address. -*/ - - - - - -#include "config.h" -#include "libdwarfdefs.h" -#include -#include -#ifdef HAVE_ELFACCESS_H -#include -#endif -#include "pro_incl.h" -#include "pro_section.h" -#include "pro_line.h" -#include "pro_frame.h" -#include "pro_die.h" -#include "pro_macinfo.h" -#include "pro_types.h" - -#ifndef SHF_MIPS_NOSTRIP -/* if this is not defined, we probably don't need it: just use 0 */ -#define SHF_MIPS_NOSTRIP 0 -#endif -#ifndef R_MIPS_NONE -#define R_MIPS_NONE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -/* must match up with pro_section.h defines of DEBUG_INFO etc -and sectnames (below). REL_SEC_PREFIX is either ".rel" or ".rela" -see pro_incl.h -*/ -char *_dwarf_rel_section_names[] = { - REL_SEC_PREFIX ".debug_info", - REL_SEC_PREFIX ".debug_line", - REL_SEC_PREFIX ".debug_abbrev", /* no relocations on this, really */ - REL_SEC_PREFIX ".debug_frame", - REL_SEC_PREFIX ".debug_aranges", - REL_SEC_PREFIX ".debug_pubnames", - REL_SEC_PREFIX ".debug_str", - REL_SEC_PREFIX ".debug_funcnames", /* sgi extension */ - REL_SEC_PREFIX ".debug_typenames", /* sgi extension */ - REL_SEC_PREFIX ".debug_varnames", /* sgi extension */ - REL_SEC_PREFIX ".debug_weaknames", /* sgi extension */ - REL_SEC_PREFIX ".debug_macinfo", - REL_SEC_PREFIX ".debug_loc" -}; - -/* names of sections. Ensure that it matches the defines - in pro_section.h, in the same order - Must match also _dwarf_rel_section_names above -*/ -char *_dwarf_sectnames[] = { - ".debug_info", - ".debug_line", - ".debug_abbrev", - ".debug_frame", - ".debug_aranges", - ".debug_pubnames", - ".debug_str", - ".debug_funcnames", /* sgi extension */ - ".debug_typenames", /* sgi extension */ - ".debug_varnames", /* sgi extension */ - ".debug_weaknames", /* sgi extension */ - ".debug_macinfo", - ".debug_loc" -}; - - - - -static Dwarf_Ubyte std_opcode_len[] = { 0, /* DW_LNS_copy */ - 1, /* DW_LNS_advance_pc */ - 1, /* DW_LNS_advance_line */ - 1, /* DW_LNS_set_file */ - 1, /* DW_LNS_set_column */ - 0, /* DW_LNS_negate_stmt */ - 0, /* DW_LNS_set_basic_block */ - 0, /* DW_LNS_const_add_pc */ - 1, /* DW_LNS_fixed_advance_pc */ -}; - -/* struct to hold relocation entries. Its mantained as a linked - list of relocation structs, and will then be written at as a - whole into the relocation section. Whether its 32 bit or - 64 bit will be obtained from Dwarf_Debug pointer. -*/ - -typedef struct Dwarf_P_Rel_s *Dwarf_P_Rel; -struct Dwarf_P_Rel_s { - Dwarf_P_Rel dr_next; - void *dr_rel_datap; -}; -typedef struct Dwarf_P_Rel_Head_s *Dwarf_P_Rel_Head; -struct Dwarf_P_Rel_Head_s { - struct Dwarf_P_Rel_s *drh_head; - struct Dwarf_P_Rel_s *drh_tail; -}; - -static int _dwarf_pro_generate_debugline(Dwarf_P_Debug dbg, - Dwarf_Error * error); -static int _dwarf_pro_generate_debugframe(Dwarf_P_Debug dbg, - Dwarf_Error * error); -static int _dwarf_pro_generate_debuginfo(Dwarf_P_Debug dbg, - Dwarf_Error * error); -static Dwarf_P_Abbrev _dwarf_pro_getabbrev(Dwarf_P_Die, Dwarf_P_Abbrev); -static int _dwarf_pro_match_attr - (Dwarf_P_Attribute, Dwarf_P_Abbrev, int no_attr); - -/* these macros used as return value for below functions */ -#define OPC_INCS_ZERO -1 -#define OPC_OUT_OF_RANGE -2 -#define LINE_OUT_OF_RANGE -3 -static int _dwarf_pro_get_opc(Dwarf_Unsigned addr_adv, int line_adv); - - -/* BEGIN_LEN_SIZE is the size of the 'length' field in total. - Which may be 4,8, or 12 bytes! - 4 is standard DWARF2. - 8 is non-standard MIPS-IRIX 64-bit. - 12 is standard DWARF3 for 64 bit offsets. - Used in various routines: local variable names - must match the names here. -*/ -#define BEGIN_LEN_SIZE (uwordb_size + extension_size) - -/* - Return TRUE if we need the section, FALSE otherwise - - If any of the 'line-data-related' calls were made - including file or directory entries, - produce .debug_line . - -*/ -static int -dwarf_need_debug_line_section(Dwarf_P_Debug dbg) -{ - if (dbg->de_lines == NULL && dbg->de_file_entries == NULL - && dbg->de_inc_dirs == NULL) { - return FALSE; - } - return TRUE; -} - -/* - Convert debug information to a format such that - it can be written on disk. - Called exactly once per execution. -*/ -Dwarf_Signed -dwarf_transform_to_disk_form(Dwarf_P_Debug dbg, Dwarf_Error * error) -{ - /* - Section data in written out in a number of buffers. Each - _generate_*() function returns a cumulative count of buffers for - all the sections. get_section_bytes() returns pointers to these - buffers one at a time. */ - int nbufs = 0; - int sect = 0; - int err = 0; - Dwarf_Unsigned du = 0; - - if (dbg->de_version_magic_number != PRO_VERSION_MAGIC) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, DW_DLV_NOCOUNT); - } - - /* Create dwarf section headers */ - for (sect = 0; sect < NUM_DEBUG_SECTIONS; sect++) { - long flags = 0; - - switch (sect) { - - case DEBUG_INFO: - if (dbg->de_dies == NULL) - continue; - break; - - case DEBUG_LINE: - if (dwarf_need_debug_line_section(dbg) == FALSE) { - continue; - } - break; - - case DEBUG_ABBREV: - if (dbg->de_dies == NULL) - continue; - break; - - case DEBUG_FRAME: - if (dbg->de_frame_cies == NULL) - continue; - flags = SHF_MIPS_NOSTRIP; - break; - - case DEBUG_ARANGES: - if (dbg->de_arange == NULL) - continue; - break; - - case DEBUG_PUBNAMES: - if (dbg->de_simple_name_headers[dwarf_snk_pubname]. - sn_head == NULL) - continue; - break; - - case DEBUG_STR: - if (dbg->de_strings == NULL) - continue; - break; - - case DEBUG_FUNCNAMES: - if (dbg->de_simple_name_headers[dwarf_snk_funcname]. - sn_head == NULL) - continue; - break; - - case DEBUG_TYPENAMES: - if (dbg->de_simple_name_headers[dwarf_snk_typename]. - sn_head == NULL) - continue; - break; - - case DEBUG_VARNAMES: - if (dbg->de_simple_name_headers[dwarf_snk_varname]. - sn_head == NULL) - continue; - break; - - case DEBUG_WEAKNAMES: - if (dbg->de_simple_name_headers[dwarf_snk_weakname]. - sn_head == NULL) - continue; - break; - - case DEBUG_MACINFO: - if (dbg->de_first_macinfo == NULL) - continue; - break; - case DEBUG_LOC: - /* not handled yet */ - continue; - default: - /* logic error: missing a case */ - DWARF_P_DBG_ERROR(dbg, DW_DLE_ELF_SECT_ERR, DW_DLV_NOCOUNT); - } - { - int new_base_elf_sect; - - if (dbg->de_callback_func_b) { - new_base_elf_sect = - dbg->de_callback_func_b(_dwarf_sectnames[sect], - /* rec size */ 1, - SECTION_TYPE, - flags, SHN_UNDEF, 0, &du, &err); - - } else { - int name_idx = 0; - new_base_elf_sect = dbg->de_callback_func( - _dwarf_sectnames[sect], - dbg->de_relocation_record_size, - SECTION_TYPE, flags, - SHN_UNDEF, 0, - &name_idx, &err); - du = name_idx; - } - if (new_base_elf_sect == -1) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_ELF_SECT_ERR, - DW_DLV_NOCOUNT); - } - dbg->de_elf_sects[sect] = new_base_elf_sect; - - dbg->de_sect_name_idx[sect] = du; - } - } - - nbufs = 0; - - /* - Changing the order in which the sections are generated may cause - problems because of relocations. */ - - if (dwarf_need_debug_line_section(dbg) == TRUE) { - nbufs = _dwarf_pro_generate_debugline(dbg, error); - if (nbufs < 0) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGLINE_ERROR, - DW_DLV_NOCOUNT); - } - } - - if (dbg->de_frame_cies) { - nbufs = _dwarf_pro_generate_debugframe(dbg, error); - if (nbufs < 0) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGFRAME_ERROR, - DW_DLV_NOCOUNT); - } - } - if (dbg->de_first_macinfo) { - nbufs = _dwarf_pro_transform_macro_info_to_disk(dbg, error); - if (nbufs < 0) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGMACINFO_ERROR, - DW_DLV_NOCOUNT); - } - } - - if (dbg->de_dies) { - nbufs = _dwarf_pro_generate_debuginfo(dbg, error); - if (nbufs < 0) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR, - DW_DLV_NOCOUNT); - } - } - - if (dbg->de_arange) { - nbufs = _dwarf_transform_arange_to_disk(dbg, error); - if (nbufs < 0) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR, - DW_DLV_NOCOUNT); - } - } - - if (dbg->de_simple_name_headers[dwarf_snk_pubname].sn_head) { - nbufs = _dwarf_transform_simplename_to_disk(dbg, - dwarf_snk_pubname, - DEBUG_PUBNAMES, - error); - - - if (nbufs < 0) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR, - DW_DLV_NOCOUNT); - } - } - - if (dbg->de_simple_name_headers[dwarf_snk_funcname].sn_head) { - nbufs = _dwarf_transform_simplename_to_disk(dbg, - dwarf_snk_funcname, - DEBUG_FUNCNAMES, - error); - if (nbufs < 0) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR, - DW_DLV_NOCOUNT); - } - } - - if (dbg->de_simple_name_headers[dwarf_snk_typename].sn_head) { - nbufs = _dwarf_transform_simplename_to_disk(dbg, - dwarf_snk_typename, - DEBUG_TYPENAMES, - error); - if (nbufs < 0) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR, - DW_DLV_NOCOUNT); - } - } - - if (dbg->de_simple_name_headers[dwarf_snk_varname].sn_head) { - nbufs = _dwarf_transform_simplename_to_disk(dbg, - dwarf_snk_varname, - DEBUG_VARNAMES, - error); - - if (nbufs < 0) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR, - DW_DLV_NOCOUNT); - } - } - - if (dbg->de_simple_name_headers[dwarf_snk_weakname].sn_head) { - nbufs = _dwarf_transform_simplename_to_disk(dbg, - dwarf_snk_weakname, DEBUG_WEAKNAMES, error); - if (nbufs < 0) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR, - DW_DLV_NOCOUNT); - } - } - - { - Dwarf_Signed new_secs = 0; - int res = 0; - - res = dbg->de_transform_relocs_to_disk(dbg, &new_secs); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR, - DW_DLV_NOCOUNT); - } - nbufs += new_secs; - } - return nbufs; -} - - -/*--------------------------------------------------------------- - Generate debug_line section ----------------------------------------------------------------*/ -static int -_dwarf_pro_generate_debugline(Dwarf_P_Debug dbg, Dwarf_Error * error) -{ - Dwarf_P_Inc_Dir curdir = 0; - Dwarf_P_F_Entry curentry = 0; - Dwarf_P_Line curline = 0; - Dwarf_P_Line prevline = 0; - - /* all data named cur* are used to loop thru linked lists */ - - int sum_bytes = 0; - int prolog_size = 0; - unsigned char *data = 0; /* holds disk form data */ - int elfsectno = 0; - unsigned char *start_line_sec = 0; /* pointer to the buffer at - section start */ - /* temps for memcpy */ - Dwarf_Unsigned du = 0; - Dwarf_Ubyte db = 0; - Dwarf_Half dh = 0; - int res = 0; - int uwordb_size = dbg->de_offset_size; - int extension_size = dbg->de_64bit_extension ? 4 : 0; - int upointer_size = dbg->de_pointer_size; - char buff1[ENCODE_SPACE_NEEDED]; - - - - sum_bytes = 0; - - elfsectno = dbg->de_elf_sects[DEBUG_LINE]; - - /* include directories */ - curdir = dbg->de_inc_dirs; - while (curdir) { - prolog_size += strlen(curdir->did_name) + 1; - curdir = curdir->did_next; - } - prolog_size++; /* last null following last directory - entry. */ - - /* file entries */ - curentry = dbg->de_file_entries; - while (curentry) { - prolog_size += - strlen(curentry->dfe_name) + 1 + curentry->dfe_nbytes; - curentry = curentry->dfe_next; - } - prolog_size++; /* last null byte */ - - - prolog_size += BEGIN_LEN_SIZE + sizeof_uhalf(dbg) + /* version # */ - uwordb_size + /* header length */ - sizeof_ubyte(dbg) + /* min_instr length */ - sizeof_ubyte(dbg) + /* default is_stmt */ - sizeof_ubyte(dbg) + /* linebase */ - sizeof_ubyte(dbg) + /* linerange */ - sizeof_ubyte(dbg); /* opcode base */ - - /* length of table specifying # of opnds */ - prolog_size += sizeof(std_opcode_len); - - GET_CHUNK(dbg, elfsectno, data, prolog_size, error); - start_line_sec = data; - - /* copy over the data */ - /* total_length */ - du = 0; - if (extension_size) { - Dwarf_Word x = DISTINGUISHED_VALUE; - - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &x, - sizeof(x), extension_size); - data += extension_size; - } - - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du, - sizeof(du), uwordb_size); - data += uwordb_size; - - dh = VERSION; - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &dh, - sizeof(dh), sizeof(Dwarf_Half)); - data += sizeof(Dwarf_Half); - - /* header length */ - du = prolog_size - (BEGIN_LEN_SIZE + sizeof(Dwarf_Half) + - uwordb_size); - { - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du, - sizeof(du), uwordb_size); - data += uwordb_size; - } - db = MIN_INST_LENGTH; - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - db = DEFAULT_IS_STMT; - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - db = (Dwarf_Ubyte) LINE_BASE; - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - db = LINE_RANGE; - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - db = OPCODE_BASE; - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - WRITE_UNALIGNED(dbg, (void *) data, (const void *) std_opcode_len, - sizeof(std_opcode_len), sizeof(std_opcode_len)); - data += sizeof(std_opcode_len); - - /* copy over include directories */ - curdir = dbg->de_inc_dirs; - while (curdir) { - strcpy((char *) data, curdir->did_name); - data += strlen(curdir->did_name) + 1; - curdir = curdir->did_next; - } - *data = '\0'; /* last null */ - data++; - - /* copy file entries */ - curentry = dbg->de_file_entries; - while (curentry) { - strcpy((char *) data, curentry->dfe_name); - data += strlen(curentry->dfe_name) + 1; - /* copies of leb numbers, no endian issues */ - memcpy((void *) data, - (const void *) curentry->dfe_args, curentry->dfe_nbytes); - data += curentry->dfe_nbytes; - curentry = curentry->dfe_next; - } - *data = '\0'; - data++; - - sum_bytes += prolog_size; - - curline = dbg->de_lines; - prevline = (Dwarf_P_Line) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Line_s)); - if (prevline == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_LINE_ALLOC, -1); - } - _dwarf_pro_reg_init(prevline); - /* generate opcodes for line numbers */ - while (curline) { - int nbytes; - char *arg; - int opc; - int no_lns_copy; /* if lns copy opcode doesnt need to be - generated, if special opcode or end - sequence */ - Dwarf_Unsigned addr_adv; - int line_adv; /* supposed to be a reasonably small - number, so the size should not be a - problem. ? */ - - no_lns_copy = 0; - if (curline->dpl_opc != 0) { - int inst_bytes; /* no of bytes in extended opcode */ - char *str; /* hold leb encoded inst_bytes */ - int str_nbytes; /* no of bytes in str */ - - switch (curline->dpl_opc) { - case DW_LNE_end_sequence: - - /* Advance pc to end of text section. */ - addr_adv = curline->dpl_address - prevline->dpl_address; - if (addr_adv > 0) { - db = DW_LNS_advance_pc; - res = - _dwarf_pro_encode_leb128_nm(addr_adv / - MIN_INST_LENGTH, - &nbytes, buff1, - sizeof(buff1)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); - } - GET_CHUNK(dbg, elfsectno, data, - nbytes + sizeof(Dwarf_Ubyte), error); - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &db, sizeof(db), - sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - /* leb, no endianness issue */ - memcpy((void *) data, (const void *) buff1, nbytes); - data += nbytes + sizeof(Dwarf_Ubyte); - sum_bytes += nbytes + sizeof(Dwarf_Ubyte); - prevline->dpl_address = curline->dpl_address; - } - - /* first null byte */ - db = 0; - GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte), - error); - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - sum_bytes += sizeof(Dwarf_Ubyte); - - /* write length of extended opcode */ - inst_bytes = sizeof(Dwarf_Ubyte); - res = - _dwarf_pro_encode_leb128_nm(inst_bytes, &str_nbytes, - buff1, sizeof(buff1)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); - } - GET_CHUNK(dbg, elfsectno, data, str_nbytes, error); - memcpy((void *) data, (const void *) buff1, str_nbytes); - data += str_nbytes; - sum_bytes += str_nbytes; - - /* write extended opcode */ - db = DW_LNE_end_sequence; - GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte), - error); - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - sum_bytes += sizeof(Dwarf_Ubyte); - /* reset value to original values */ - _dwarf_pro_reg_init(prevline); - no_lns_copy = 1; - /* this is set only for end_sequence, so that a - dw_lns_copy is not generated */ - break; - - case DW_LNE_set_address: - - /* first null byte */ - db = 0; - GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte), - error); - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - sum_bytes += sizeof(Dwarf_Ubyte); - - /* write length of extended opcode */ - inst_bytes = sizeof(Dwarf_Ubyte) + upointer_size; - res = - _dwarf_pro_encode_leb128_nm(inst_bytes, &str_nbytes, - buff1, sizeof(buff1)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); - } - GET_CHUNK(dbg, elfsectno, data, str_nbytes, error); - str = buff1; - /* leb number, no endian issue */ - memcpy((void *) data, (const void *) str, str_nbytes); - data += str_nbytes; - sum_bytes += str_nbytes; - - /* write extended opcode */ - db = DW_LNE_set_address; - GET_CHUNK(dbg, elfsectno, data, upointer_size + - sizeof(Dwarf_Ubyte), error); - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - sum_bytes += sizeof(Dwarf_Ubyte); - - /* reloc for address */ - res = dbg->de_reloc_name(dbg, DEBUG_LINE, - sum_bytes, /* r_offset */ - curline->dpl_r_symidx, - dwarf_drt_data_reloc, - uwordb_size); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); - } - - /* write offset (address) */ - du = curline->dpl_address; - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du, - sizeof(du), upointer_size); - data += upointer_size; - sum_bytes += upointer_size; - prevline->dpl_address = curline->dpl_address; - no_lns_copy = 1; - break; - } - } else { - if (curline->dpl_file != prevline->dpl_file) { - db = DW_LNS_set_file; - res = - _dwarf_pro_encode_leb128_nm(curline->dpl_file, - &nbytes, buff1, - sizeof(buff1)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); - } - arg = buff1; - GET_CHUNK(dbg, elfsectno, data, - nbytes + sizeof(Dwarf_Ubyte), error); - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - memcpy((void *) data, (const void *) arg, nbytes); - data += nbytes; - sum_bytes += nbytes + sizeof(Dwarf_Ubyte); - prevline->dpl_file = curline->dpl_file; - } - if (curline->dpl_column != prevline->dpl_column) { - db = DW_LNS_set_column; - res = _dwarf_pro_encode_leb128_nm(curline->dpl_column, - &nbytes, - buff1, sizeof(buff1)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); - } - - arg = buff1; - GET_CHUNK(dbg, elfsectno, data, - nbytes + sizeof(Dwarf_Ubyte), error); - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - memcpy((void *) data, (const void *) arg, nbytes); - data += nbytes; - sum_bytes += nbytes + sizeof(Dwarf_Ubyte); - prevline->dpl_column = curline->dpl_column; - } - if (curline->dpl_is_stmt != prevline->dpl_is_stmt) { - db = DW_LNS_negate_stmt; - GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte), - error); - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - sum_bytes += sizeof(Dwarf_Ubyte); - prevline->dpl_is_stmt = curline->dpl_is_stmt; - } - if (curline->dpl_basic_block == true && - prevline->dpl_basic_block == false) { - db = DW_LNS_set_basic_block; - GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte), - error); - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - sum_bytes += sizeof(Dwarf_Ubyte); - prevline->dpl_basic_block = curline->dpl_basic_block; - } - addr_adv = curline->dpl_address - prevline->dpl_address; - - line_adv = (int) (curline->dpl_line - prevline->dpl_line); - if ((addr_adv % MIN_INST_LENGTH) != 0) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_WRONG_ADDRESS, -1); - } - if ((opc = _dwarf_pro_get_opc(addr_adv, line_adv)) > 0) { - no_lns_copy = 1; - db = opc; - GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte), - error); - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - sum_bytes += sizeof(Dwarf_Ubyte); - prevline->dpl_basic_block = false; - prevline->dpl_address = curline->dpl_address; - prevline->dpl_line = curline->dpl_line; - } else { - if (addr_adv > 0) { - db = DW_LNS_advance_pc; - res = - _dwarf_pro_encode_leb128_nm(addr_adv / - MIN_INST_LENGTH, - &nbytes, buff1, - sizeof(buff1)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); - } - - arg = buff1; - GET_CHUNK(dbg, elfsectno, data, - nbytes + sizeof(Dwarf_Ubyte), error); - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - memcpy((void *) data, (const void *) arg, nbytes); - data += nbytes + sizeof(Dwarf_Ubyte); - sum_bytes += nbytes + sizeof(Dwarf_Ubyte); - prevline->dpl_basic_block = false; - prevline->dpl_address = curline->dpl_address; - } - if (line_adv != 0) { - db = DW_LNS_advance_line; - res = _dwarf_pro_encode_signed_leb128_nm(line_adv, - &nbytes, - buff1, - sizeof - (buff1)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); - } - - arg = buff1; - GET_CHUNK(dbg, elfsectno, data, - nbytes + sizeof(Dwarf_Ubyte), error); - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &db, sizeof(db), - sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - memcpy((void *) data, (const void *) arg, nbytes); - data += nbytes + sizeof(Dwarf_Ubyte); - sum_bytes += nbytes + sizeof(Dwarf_Ubyte); - prevline->dpl_basic_block = false; - prevline->dpl_line = curline->dpl_line; - } - } - } /* ends else for opc != 0 */ - if (no_lns_copy == 0) { /* if not a special or dw_lne_end_seq - generate a matrix line */ - db = DW_LNS_copy; - GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte), error); - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - sum_bytes += sizeof(Dwarf_Ubyte); - prevline->dpl_basic_block = false; - } - curline = curline->dpl_next; - } - - /* write total length field */ - du = sum_bytes - BEGIN_LEN_SIZE; - { - start_line_sec += extension_size; - WRITE_UNALIGNED(dbg, (void *) start_line_sec, - (const void *) &du, sizeof(du), uwordb_size); - } - - return (int) dbg->de_n_debug_sect; -} - -/*--------------------------------------------------------------- - Generate debug_frame section ----------------------------------------------------------------*/ -static int -_dwarf_pro_generate_debugframe(Dwarf_P_Debug dbg, Dwarf_Error * error) -{ - int elfsectno = 0; - int i = 0; - int firsttime = 1; - int pad = 0; /* Pad for padding to align cies and fdes */ - Dwarf_P_Cie curcie = 0; - Dwarf_P_Fde curfde = 0; - unsigned char *data = 0; - Dwarf_sfixed dsw = 0; - Dwarf_Unsigned du = 0; - Dwarf_Ubyte db = 0; - long *cie_offs = 0; /* Holds byte offsets for links to fde's */ - unsigned long cie_length = 0; - int cie_no = 0; - int uwordb_size = dbg->de_offset_size; - int extension_size = dbg->de_64bit_extension ? 4 : 0; - int upointer_size = dbg->de_pointer_size; - Dwarf_Unsigned cur_off = 0; /* current offset of written data, held - for relocation info */ - - elfsectno = dbg->de_elf_sects[DEBUG_FRAME]; - - curcie = dbg->de_frame_cies; - cie_length = 0; - cur_off = 0; - cie_offs = (long *) - _dwarf_p_get_alloc(dbg, sizeof(long) * dbg->de_n_cie); - if (cie_offs == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1); - } - /* Generate cie number as we go along. This writes - all CIEs first before any FDEs, which is rather - different from the order a compiler might like (which - might be each CIE followed by its FDEs then the next CIE, and - so on). */ - cie_no = 1; - while (curcie) { - char *code_al = 0; - int c_bytes = 0; - char *data_al = 0; - int d_bytes = 0; - int res = 0; - char buff1[ENCODE_SPACE_NEEDED]; - char buff2[ENCODE_SPACE_NEEDED]; - char buff3[ENCODE_SPACE_NEEDED]; - char *augmentation = 0; - char *augmented_al = 0; - long augmented_fields_length = 0; - int a_bytes = 0; - - res = _dwarf_pro_encode_leb128_nm(curcie->cie_code_align, - &c_bytes, - buff1, sizeof(buff1)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1); - } - /* Before April 1999, the following was using an unsigned - encode. That worked ok even though the decoder used the - correct signed leb read, but doing the encode correctly - (according to the dwarf spec) saves space in the output file - and is completely compatible. - - Note the actual stored amount on MIPS was 10 bytes (!) to - store the value -4. (hex)fc ffffffff ffffffff 01 The - libdwarf consumer consumed all 10 bytes too! - - old version res = - _dwarf_pro_encode_leb128_nm(curcie->cie_data_align, - - below is corrected signed version. */ - res = _dwarf_pro_encode_signed_leb128_nm(curcie->cie_data_align, - &d_bytes, - buff2, sizeof(buff2)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1); - } - code_al = buff1; - data_al = buff2; - - /* get the correct offset */ - if (firsttime) { - cie_offs[cie_no - 1] = 0; - firsttime = 0; - } else { - cie_offs[cie_no - 1] = cie_offs[cie_no - 2] + - (long) cie_length + BEGIN_LEN_SIZE; - } - cie_no++; - augmentation = curcie->cie_aug; - if (strcmp(augmentation, DW_CIE_AUGMENTER_STRING_V0) == 0) { - augmented_fields_length = 0; - res = _dwarf_pro_encode_leb128_nm(augmented_fields_length, - &a_bytes, buff3, - sizeof(buff3)); - augmented_al = buff3; - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1); - } - cie_length = uwordb_size + /* cie_id */ - sizeof(Dwarf_Ubyte) + /* cie version */ - strlen(curcie->cie_aug) + 1 + /* augmentation */ - c_bytes + /* code alignment factor */ - d_bytes + /* data alignment factor */ - sizeof(Dwarf_Ubyte) + /* return reg address */ - a_bytes + /* augmentation length */ - curcie->cie_inst_bytes; - } else { - cie_length = uwordb_size + /* cie_id */ - sizeof(Dwarf_Ubyte) + /* cie version */ - strlen(curcie->cie_aug) + 1 + /* augmentation */ - c_bytes + d_bytes + sizeof(Dwarf_Ubyte) + /* return - reg - address - */ - curcie->cie_inst_bytes; - } - pad = (int) PADDING(cie_length, upointer_size); - cie_length += pad; - GET_CHUNK(dbg, elfsectno, data, cie_length + - BEGIN_LEN_SIZE, error); - if (extension_size) { - Dwarf_Unsigned x = DISTINGUISHED_VALUE; - - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &x, - sizeof(x), extension_size); - data += extension_size; - - } - du = cie_length; - /* total length of cie */ - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &du, sizeof(du), uwordb_size); - data += uwordb_size; - - /* cie-id is a special value. */ - du = DW_CIE_ID; - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du, - sizeof(du), uwordb_size); - data += uwordb_size; - - db = curcie->cie_version; - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - strcpy((char *) data, curcie->cie_aug); - data += strlen(curcie->cie_aug) + 1; - memcpy((void *) data, (const void *) code_al, c_bytes); - data += c_bytes; - memcpy((void *) data, (const void *) data_al, d_bytes); - data += d_bytes; - db = curcie->cie_ret_reg; - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); - - if (strcmp(augmentation, DW_CIE_AUGMENTER_STRING_V0) == 0) { - memcpy((void *) data, (const void *) augmented_al, a_bytes); - data += a_bytes; - } - memcpy((void *) data, (const void *) curcie->cie_inst, - curcie->cie_inst_bytes); - data += curcie->cie_inst_bytes; - for (i = 0; i < pad; i++) { - *data = DW_CFA_nop; - data++; - } - curcie = curcie->cie_next; - } - /* calculate current offset */ - cur_off = cie_offs[cie_no - 2] + cie_length + BEGIN_LEN_SIZE; - - /* write out fde's */ - curfde = dbg->de_frame_fdes; - while (curfde) { - Dwarf_P_Frame_Pgm curinst = 0; - long fde_length = 0; - int pad = 0; - Dwarf_P_Cie cie_ptr = 0; - Dwarf_Word cie_index = 0; - Dwarf_Word index = 0; - int oet_length = 0; - int afl_length = 0; - int res = 0; - int v0_augmentation = 0; -#if 0 - unsigned char *fde_start_point = 0; -#endif - char afl_buff[ENCODE_SPACE_NEEDED]; - - /* Find the CIE associated with this fde. */ - cie_ptr = dbg->de_frame_cies; - cie_index = curfde->fde_cie; - index = 1; /* The cie_index of the first cie is 1, - not 0. */ - while (cie_ptr && index < cie_index) { - cie_ptr = cie_ptr->cie_next; - index++; - } - if (cie_ptr == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_NULL, -1); - } - - if (strcmp(cie_ptr->cie_aug, DW_CIE_AUGMENTER_STRING_V0) == 0) { - v0_augmentation = 1; - oet_length = sizeof(Dwarf_sfixed); - /* encode the length of augmented fields. */ - res = _dwarf_pro_encode_leb128_nm(oet_length, - &afl_length, afl_buff, - sizeof(afl_buff)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1); - } - - fde_length = curfde->fde_n_bytes + BEGIN_LEN_SIZE + /* cie - pointer - */ - upointer_size + /* initial loc */ - upointer_size + /* address range */ - afl_length + /* augmented field length */ - oet_length; /* exception_table offset */ - } else { - fde_length = curfde->fde_n_bytes + BEGIN_LEN_SIZE + /* cie - pointer - */ - upointer_size + /* initial loc */ - upointer_size; /* address range */ - } - - - if (curfde->fde_die) { - /* IRIX/MIPS extension: - Using fde offset, generate DW_AT_MIPS_fde attribute for the - die corresponding to this fde. */ - if(_dwarf_pro_add_AT_fde(dbg, curfde->fde_die, cur_off, - error) < 0) { - return -1; - } - } - - /* store relocation for cie pointer */ - res = dbg->de_reloc_name(dbg, DEBUG_FRAME, cur_off + - BEGIN_LEN_SIZE /* r_offset */, - dbg->de_sect_name_idx[DEBUG_FRAME], - dwarf_drt_data_reloc, uwordb_size); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); - } - - /* store relocation information for initial location */ - res = dbg->de_reloc_name(dbg, DEBUG_FRAME, - cur_off + BEGIN_LEN_SIZE + - upointer_size /* r_offset */, - curfde->fde_r_symidx, - dwarf_drt_data_reloc, upointer_size); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); - } - /* Store the relocation information for the - offset_into_exception_info field, if the offset is valid (0 - is a valid offset). */ - if (v0_augmentation && - curfde->fde_offset_into_exception_tables >= 0) { - - res = dbg->de_reloc_name(dbg, DEBUG_FRAME, - /* r_offset, where in cie this - field starts */ - cur_off + BEGIN_LEN_SIZE + - uwordb_size + 2 * upointer_size + - afl_length, - curfde->fde_exception_table_symbol, - dwarf_drt_segment_rel, - sizeof(Dwarf_sfixed)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1); - } - } - - /* adjust for padding */ - pad = (int) PADDING(fde_length, upointer_size); - fde_length += pad; - - - /* write out fde */ - GET_CHUNK(dbg, elfsectno, data, fde_length + BEGIN_LEN_SIZE, - error); -#if 0 - fde_start_point = data; -#endif - du = fde_length; - { - if (extension_size) { - Dwarf_Word x = DISTINGUISHED_VALUE; - - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &x, - sizeof(x), extension_size); - data += extension_size; - } - /* length */ - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &du, - sizeof(du), uwordb_size); - data += uwordb_size; - - /* offset to cie */ - du = cie_offs[curfde->fde_cie - 1]; - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &du, - sizeof(du), uwordb_size); - data += uwordb_size; - - du = curfde->fde_initloc; - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &du, - sizeof(du), upointer_size); - data += upointer_size; - - if (dbg->de_reloc_pair && - curfde->fde_end_symbol != 0 && - curfde->fde_addr_range == 0) { - /* symbolic reloc, need reloc for length What if we - really know the length? If so, should use the other - part of 'if'. */ - Dwarf_Unsigned val; - - res = dbg->de_reloc_pair(dbg, - /* DEBUG_ARANGES, */ - DEBUG_FRAME, cur_off + 2 * uwordb_size + upointer_size, /* r_offset - */ - curfde->fde_r_symidx, - curfde->fde_end_symbol, - dwarf_drt_first_of_length_pair, - upointer_size); - if (res != DW_DLV_OK) { - { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (0); - } - } - - /* arrange pre-calc so assem text can do .word end - - begin + val (gets val from stream) */ - val = curfde->fde_end_symbol_offset - - curfde->fde_initloc; - WRITE_UNALIGNED(dbg, data, - (const void *) &val, - sizeof(val), upointer_size); - data += upointer_size; - } else { - - du = curfde->fde_addr_range; - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &du, - sizeof(du), upointer_size); - data += upointer_size; - } - } - - if (v0_augmentation) { - /* write the encoded augmented field length. */ - memcpy((void *) data, (const void *) afl_buff, afl_length); - data += afl_length; - /* write the offset_into_exception_tables field. */ - dsw = - (Dwarf_sfixed) curfde->fde_offset_into_exception_tables; - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &dsw, - sizeof(dsw), sizeof(Dwarf_sfixed)); - data += sizeof(Dwarf_sfixed); - } - - curinst = curfde->fde_inst; - if(curfde->fde_block) { - unsigned long size = curfde->fde_inst_block_size; - memcpy((void *) data, (const void *) curfde->fde_block, size); - data += size; - } else { - while (curinst) { - db = curinst->dfp_opcode; - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - data += sizeof(Dwarf_Ubyte); -#if 0 - if (curinst->dfp_sym_index) { - int res = dbg->de_reloc_name(dbg, - DEBUG_FRAME, - /* r_offset = */ - (data - fde_start_point) + cur_off + uwordb_size, - curinst->dfp_sym_index, - dwarf_drt_data_reloc, - upointer_size); - if (res != DW_DLV_OK) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (0); - } - } -#endif - memcpy((void *) data, - (const void *) curinst->dfp_args, - curinst->dfp_nbytes); - data += curinst->dfp_nbytes; - curinst = curinst->dfp_next; - } - } - /* padding */ - for (i = 0; i < pad; i++) { - *data = DW_CFA_nop; - data++; - } - cur_off += fde_length + uwordb_size; - curfde = curfde->fde_next; - } - - - return (int) dbg->de_n_debug_sect; -} - -/* - These functions remember all the markers we see along - with the right offset in the .debug_info section so that - we can dump them all back to the user with the section info. -*/ - -static int -marker_init(Dwarf_P_Debug dbg, - unsigned count) -{ - dbg->de_marker_n_alloc = count; - dbg->de_markers = NULL; - if (count > 0) { - dbg->de_markers = _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Marker_s) * - dbg->de_marker_n_alloc); - if (dbg->de_markers == NULL) { - dbg->de_marker_n_alloc = 0; - return -1; - } - } - return 0; -} - -static int -marker_add(Dwarf_P_Debug dbg, - Dwarf_Unsigned offset, - Dwarf_Unsigned marker) -{ - if (dbg->de_marker_n_alloc >= (dbg->de_marker_n_used + 1)) { - unsigned n = dbg->de_marker_n_used++; - dbg->de_markers[n].ma_offset = offset; - dbg->de_markers[n].ma_marker = marker; - return 0; - } - - return -1; -} - -Dwarf_Signed -dwarf_get_die_markers(Dwarf_P_Debug dbg, - Dwarf_P_Marker * marker_list, /* pointer to a pointer */ - Dwarf_Unsigned * marker_count, - Dwarf_Error * error) -{ - if (marker_list == NULL || marker_count == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, DW_DLV_BADADDR); - } - if (dbg->de_marker_n_used != dbg->de_marker_n_alloc) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_MAF, DW_DLV_BADADDR); - } - - *marker_list = dbg->de_markers; - *marker_count = dbg->de_marker_n_used; - return DW_DLV_OK; -} - -/* These functions provide the offsets of DW_FORM_string - attributes in the section section_index. These information - will enable a producer app that is generating assembly - text output to easily emit those attributes in ascii form - without having to decode the byte stream. - */ -static int -string_attr_init (Dwarf_P_Debug dbg, - Dwarf_Signed section_index, - unsigned count) -{ - Dwarf_P_Per_Sect_String_Attrs sect_sa = &dbg->de_sect_string_attr[section_index]; - - sect_sa->sect_sa_n_alloc = count; - sect_sa->sect_sa_list = NULL; - if (count > 0) { - sect_sa->sect_sa_section_number = section_index; - sect_sa->sect_sa_list = _dwarf_p_get_alloc(dbg, - sizeof(struct Dwarf_P_String_Attr_s) - * sect_sa->sect_sa_n_alloc); - if (sect_sa->sect_sa_list == NULL) { - sect_sa->sect_sa_n_alloc = 0; - return -1; - } - } - return 0; -} - -static int -string_attr_add (Dwarf_P_Debug dbg, - Dwarf_Signed section_index, - Dwarf_Unsigned offset, - Dwarf_P_Attribute attr) -{ - Dwarf_P_Per_Sect_String_Attrs sect_sa = &dbg->de_sect_string_attr[section_index]; - if (sect_sa->sect_sa_n_alloc >= (sect_sa->sect_sa_n_used + 1)) { - unsigned n = sect_sa->sect_sa_n_used++; - sect_sa->sect_sa_list[n].sa_offset = offset; - sect_sa->sect_sa_list[n].sa_nbytes = attr->ar_nbytes; - return 0; - } - - return -1; -} - -int -dwarf_get_string_attributes_count(Dwarf_P_Debug dbg, - Dwarf_Unsigned * - count_of_sa_sections, - int *drd_buffer_version, - Dwarf_Error *error) -{ - int i; - unsigned int count = 0; - - for (i = 0; i < NUM_DEBUG_SECTIONS; ++i) { - if (dbg->de_sect_string_attr[i].sect_sa_n_used > 0) { - ++count; - } - } - *count_of_sa_sections = (Dwarf_Unsigned) count; - *drd_buffer_version = DWARF_DRD_BUFFER_VERSION; - - return DW_DLV_OK; -} - -int -dwarf_get_string_attributes_info(Dwarf_P_Debug dbg, - Dwarf_Signed *elf_section_index, - Dwarf_Unsigned *sect_sa_buffer_count, - Dwarf_P_String_Attr *sect_sa_buffer, - Dwarf_Error *error) -{ - int i; - int next = dbg->de_sect_sa_next_to_return; - - for (i = next; i < NUM_DEBUG_SECTIONS; ++i) { - Dwarf_P_Per_Sect_String_Attrs sect_sa = &dbg->de_sect_string_attr[i]; - if (sect_sa->sect_sa_n_used > 0) { - dbg->de_sect_sa_next_to_return = i + 1; - *elf_section_index = sect_sa->sect_sa_section_number; - *sect_sa_buffer_count = sect_sa->sect_sa_n_used; - *sect_sa_buffer = sect_sa->sect_sa_list; - return DW_DLV_OK; - } - } - return DW_DLV_NO_ENTRY; -} - - - -/*--------------------------------------------------------------- - Generate debug_info and debug_abbrev sections ----------------------------------------------------------------*/ -static int -_dwarf_pro_generate_debuginfo(Dwarf_P_Debug dbg, Dwarf_Error * error) -{ - int elfsectno_of_debug_info = 0; - int abbrevsectno = 0; - unsigned char *data = 0; - int cu_header_size = 0; - Dwarf_P_Abbrev curabbrev = 0; - Dwarf_P_Abbrev abbrev_head = 0; - Dwarf_P_Abbrev abbrev_tail = 0; - Dwarf_P_Die curdie = 0; - Dwarf_P_Die first_child = 0; - Dwarf_Word dw = 0; - Dwarf_Unsigned du = 0; - Dwarf_Half dh = 0; - Dwarf_Ubyte db = 0; - Dwarf_Half version = 0; /* Need 2 byte quantity. */ - Dwarf_Unsigned die_off = 0; /* Offset of die in debug_info. */ - int n_abbrevs = 0; - int res = 0; - unsigned marker_count = 0; - unsigned string_attr_count = 0; - unsigned string_attr_offset = 0; - - Dwarf_Small *start_info_sec = 0; - - int uwordb_size = dbg->de_offset_size; - int extension_size = dbg->de_64bit_extension ? 4 : 0; - - abbrev_head = abbrev_tail = NULL; - elfsectno_of_debug_info = dbg->de_elf_sects[DEBUG_INFO]; - - /* write cu header */ - cu_header_size = BEGIN_LEN_SIZE + sizeof(Dwarf_Half) + /* version - stamp - */ - uwordb_size + /* offset into abbrev table */ - sizeof(Dwarf_Ubyte); /* size of target address */ - GET_CHUNK(dbg, elfsectno_of_debug_info, data, cu_header_size, - error); - start_info_sec = data; - if (extension_size) { - du = DISTINGUISHED_VALUE; - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &du, sizeof(du), extension_size); - data += extension_size; - } - du = 0; /* length of debug_info, not counting - this field itself (unknown at this - point). */ - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &du, sizeof(du), uwordb_size); - data += uwordb_size; - - version = CURRENT_VERSION_STAMP; /* assume this length will not - change */ - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &version, - sizeof(version), sizeof(Dwarf_Half)); - data += sizeof(Dwarf_Half); - - du = 0; /* offset into abbrev table, not yet - known. */ - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &du, sizeof(du), uwordb_size); - data += uwordb_size; - - - db = dbg->de_pointer_size; - - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), 1); - - /* We have filled the chunk we got with GET_CHUNK. At this point we - no longer dare use "data" or "start_info_sec" as a pointer any - longer except to refer to that first small chunk for the cu - header. */ - - curdie = dbg->de_dies; - - /* create AT_macro_info if appropriate */ - if (dbg->de_first_macinfo != NULL) { - if (_dwarf_pro_add_AT_macro_info(dbg, curdie, 0, error) < 0) - return -1; - } - - /* create AT_stmt_list attribute if necessary */ - if (dwarf_need_debug_line_section(dbg) == TRUE) - if (_dwarf_pro_add_AT_stmt_list(dbg, curdie, error) < 0) - return -1; - - die_off = cu_header_size; - - /* - Relocation for abbrev offset in cu header store relocation - record in linked list */ - res = dbg->de_reloc_name(dbg, DEBUG_INFO, BEGIN_LEN_SIZE + - sizeof(Dwarf_Half), - /* r_offset */ - dbg->de_sect_name_idx[DEBUG_ABBREV], - dwarf_drt_data_reloc, uwordb_size); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1); - } - - /* pass 0: only top level dies, add at_sibling attribute to those - dies with children */ - first_child = curdie->di_child; - while (first_child && first_child->di_right) { - if (first_child->di_child) - dwarf_add_AT_reference(dbg, - first_child, - DW_AT_sibling, - first_child->di_right, error); - first_child = first_child->di_right; - } - - /* pass 1: create abbrev info, get die offsets, calc relocations */ - marker_count = 0; - string_attr_count = 0; - while (curdie != NULL) { - int nbytes = 0; - Dwarf_P_Attribute curattr; - Dwarf_P_Attribute new_first_attr; - Dwarf_P_Attribute new_last_attr; - char *space = 0; - int res = 0; - char buff1[ENCODE_SPACE_NEEDED]; - int i = 0; - - curdie->di_offset = die_off; - - if (curdie->di_marker != 0) - marker_count++; - - curabbrev = _dwarf_pro_getabbrev(curdie, abbrev_head); - if (curabbrev == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1); - } - if (abbrev_head == NULL) { - n_abbrevs = 1; - curabbrev->abb_idx = n_abbrevs; - abbrev_tail = abbrev_head = curabbrev; - } else { - /* check if its a new abbreviation, if yes, add to tail */ - if (curabbrev->abb_idx == 0) { - n_abbrevs++; - curabbrev->abb_idx = n_abbrevs; - abbrev_tail->abb_next = curabbrev; - abbrev_tail = curabbrev; - } - } - res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_idx, - &nbytes, - buff1, sizeof(buff1)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1); - } - space = _dwarf_p_get_alloc(dbg, nbytes); - if (space == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1); - } - memcpy(space, buff1, nbytes); - curdie->di_abbrev = space; - curdie->di_abbrev_nbytes = nbytes; - die_off += nbytes; - - /* Resorting the attributes!! */ - new_first_attr = new_last_attr = NULL; - curattr = curdie->di_attrs; - for (i = 0; i < (int)curabbrev->abb_n_attr; i++) { - Dwarf_P_Attribute ca; - Dwarf_P_Attribute cl; - - /* The following should always find an attribute! */ - for (ca = cl = curattr; - ca && curabbrev->abb_attrs[i] != ca->ar_attribute; - cl = ca, ca = ca->ar_next) - { - } - - if (!ca) { - DWARF_P_DBG_ERROR(dbg,DW_DLE_ABBREV_ALLOC, -1); - } - - /* Remove the attribute from the old list. */ - if (ca == curattr) { - curattr = ca->ar_next; - } else { - cl->ar_next = ca->ar_next; - } - - ca->ar_next = NULL; - - /* Add the attribute to the new list. */ - if (new_first_attr == NULL) { - new_first_attr = new_last_attr = ca; - } else { - new_last_attr->ar_next = ca; - new_last_attr = ca; - } - } - - curdie->di_attrs = new_first_attr; - - curattr = curdie->di_attrs; - - while (curattr) { - if (curattr->ar_rel_type != R_MIPS_NONE) { - switch (curattr->ar_attribute) { - case DW_AT_stmt_list: - curattr->ar_rel_symidx = - dbg->de_sect_name_idx[DEBUG_LINE]; - break; - case DW_AT_MIPS_fde: - curattr->ar_rel_symidx = - dbg->de_sect_name_idx[DEBUG_FRAME]; - break; - case DW_AT_macro_info: - curattr->ar_rel_symidx = - dbg->de_sect_name_idx[DEBUG_MACINFO]; - break; - default: - break; - } - res = dbg->de_reloc_name(dbg, DEBUG_INFO, die_off + curattr->ar_rel_offset, /* r_offset - */ - curattr->ar_rel_symidx, - dwarf_drt_data_reloc, - curattr->ar_reloc_len); - - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1); - } - - } - if (curattr->ar_attribute_form == DW_FORM_string) { - string_attr_count++; - } - die_off += curattr->ar_nbytes; - curattr = curattr->ar_next; - } - - /* depth first search */ - if (curdie->di_child) - curdie = curdie->di_child; - else { - while (curdie != NULL && curdie->di_right == NULL) { - curdie = curdie->di_parent; - die_off++; /* since we are writing a null die at - the end of each sibling chain */ - } - if (curdie != NULL) - curdie = curdie->di_right; - } - - } /* end while (curdie != NULL) */ - - res = marker_init(dbg, marker_count); - if (res == -1) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1); - } - res = string_attr_init(dbg, DEBUG_INFO, string_attr_count); - if (res == -1) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1); - } - - /* Pass 2: Write out the die information Here 'data' is a - temporary, one block for each GET_CHUNK. 'data' is overused. */ - curdie = dbg->de_dies; - while (curdie != NULL) { - Dwarf_P_Attribute curattr; - - if (curdie->di_marker != 0) { - res = marker_add(dbg, curdie->di_offset, curdie->di_marker); - if (res == -1) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1); - } - } - - /* index to abbreviation table */ - GET_CHUNK(dbg, elfsectno_of_debug_info, - data, curdie->di_abbrev_nbytes, error); - - memcpy((void *) data, - (const void *) curdie->di_abbrev, - curdie->di_abbrev_nbytes); - - /* Attribute values - need to fill in all form attributes */ - curattr = curdie->di_attrs; - string_attr_offset = curdie->di_offset + curdie->di_abbrev_nbytes; - - while (curattr) { - GET_CHUNK(dbg, elfsectno_of_debug_info, data, - (unsigned long) curattr->ar_nbytes, error); - switch (curattr->ar_attribute_form) { - case DW_FORM_ref1: - { - if (curattr->ar_ref_die->di_offset > - (unsigned) 0xff) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, -1); - } - db = curattr->ar_ref_die->di_offset; - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - break; - } - case DW_FORM_ref2: - { - if (curattr->ar_ref_die->di_offset > - (unsigned) 0xffff) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, -1); - } - dh = curattr->ar_ref_die->di_offset; - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &dh, - sizeof(dh), sizeof(Dwarf_Half)); - break; - } - case DW_FORM_ref_addr: - { - /* curattr->ar_ref_die == NULL! - * - * ref_addr doesn't take a CU-offset. - * This is different than other refs. - * This value will be set by the user of the - * producer library using a relocation. - * No need to set a value here. - */ -#if 0 - du = curattr->ar_ref_die->di_offset; - { - /* ref to offset of die */ - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &du, - sizeof(du), uwordb_size); - } -#endif - break; - - } - case DW_FORM_ref4: - { - if (curattr->ar_ref_die->di_offset > - (unsigned) 0xffffffff) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, -1); - } - dw = (Dwarf_Word) curattr->ar_ref_die->di_offset; - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &dw, - sizeof(dw), sizeof(Dwarf_ufixed)); - break; - } - case DW_FORM_ref8: - du = curattr->ar_ref_die->di_offset; - WRITE_UNALIGNED(dbg, (void *) data, - (const void *) &du, - sizeof(du), sizeof(Dwarf_Unsigned)); - break; - case DW_FORM_ref_udata: - { /* unsigned leb128 offset */ - - int nbytes; - char buff1[ENCODE_SPACE_NEEDED]; - - res = - _dwarf_pro_encode_leb128_nm(curattr-> - ar_ref_die-> - di_offset, &nbytes, - buff1, - sizeof(buff1)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1); - } - - memcpy(data, buff1, nbytes); - break; - } - default: - memcpy((void *) data, - (const void *) curattr->ar_data, - curattr->ar_nbytes); - break; - } - if (curattr->ar_attribute_form == DW_FORM_string) { - string_attr_add(dbg, DEBUG_INFO, string_attr_offset, curattr); - } - string_attr_offset += curattr->ar_nbytes; - curattr = curattr->ar_next; - } - - /* depth first search */ - if (curdie->di_child) - curdie = curdie->di_child; - else { - while (curdie != NULL && curdie->di_right == NULL) { - GET_CHUNK(dbg, elfsectno_of_debug_info, data, 1, error); - *data = '\0'; - curdie = curdie->di_parent; - } - if (curdie != NULL) - curdie = curdie->di_right; - } - } /* end while (curdir != NULL) */ - - /* Write out debug_info size */ - /* Dont include length field or extension bytes */ - du = die_off - BEGIN_LEN_SIZE; - WRITE_UNALIGNED(dbg, (void *) (start_info_sec + extension_size), - (const void *) &du, sizeof(du), uwordb_size); - - - data = 0; /* Emphasise not usable now */ - - /* Write out debug_abbrev section */ - abbrevsectno = dbg->de_elf_sects[DEBUG_ABBREV]; - - curabbrev = abbrev_head; - while (curabbrev) { - char *val; - int nbytes; - int idx; - int res; - char buff1[ENCODE_SPACE_NEEDED]; - - res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_idx, &nbytes, - buff1, sizeof(buff1)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1); - } - - GET_CHUNK(dbg, abbrevsectno, data, nbytes, error); - val = buff1; - memcpy((void *) data, (const void *) val, nbytes); - res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_tag, &nbytes, - buff1, sizeof(buff1)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1); - } - val = buff1; - GET_CHUNK(dbg, abbrevsectno, data, nbytes, error); - memcpy((void *) data, (const void *) val, nbytes); - db = curabbrev->abb_children; - GET_CHUNK(dbg, abbrevsectno, data, sizeof(Dwarf_Ubyte), error); - WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db, - sizeof(db), sizeof(Dwarf_Ubyte)); - - /* add attributes and forms */ - for (idx = 0; idx < curabbrev->abb_n_attr; idx++) { - res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_attrs[idx], - &nbytes, - buff1, sizeof(buff1)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1); - } - val = buff1; - GET_CHUNK(dbg, abbrevsectno, data, nbytes, error); - memcpy((void *) data, (const void *) val, nbytes); - res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_forms[idx], - &nbytes, - buff1, sizeof(buff1)); - if (res != DW_DLV_OK) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1); - } - val = buff1; - GET_CHUNK(dbg, abbrevsectno, data, nbytes, error); - memcpy((void *) data, (const void *) val, nbytes); - } - GET_CHUNK(dbg, abbrevsectno, data, 2, error); /* two zeros, - for last - entry, see - dwarf2 sec - 7.5.3 */ - *data = 0; - data++; - *data = 0; - - curabbrev = curabbrev->abb_next; - } - - GET_CHUNK(dbg, abbrevsectno, data, 1, error); /* one zero, - for end of - cu, see - dwarf2 sec - 7.5.3 */ - *data = 0; - - - return (int) dbg->de_n_debug_sect; -} - - -/*--------------------------------------------------------------------- - Get a buffer of section data. - section_idx is the elf-section number that this data applies to. - length shows length of returned data -----------------------------------------------------------------------*/ - /*ARGSUSED*/ /* pretend all args used */ - Dwarf_Ptr -dwarf_get_section_bytes(Dwarf_P_Debug dbg, - Dwarf_Signed dwarf_section, - Dwarf_Signed * section_idx, - Dwarf_Unsigned * length, Dwarf_Error * error) -{ - Dwarf_Ptr buf; - - if (dbg->de_version_magic_number != PRO_VERSION_MAGIC) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, NULL); - } - - if (dbg->de_debug_sects == 0) { - /* no more data !! */ - return NULL; - } - if (dbg->de_debug_sects->ds_elf_sect_no == MAGIC_SECT_NO) { - /* no data ever entered !! */ - return NULL; - } - *section_idx = dbg->de_debug_sects->ds_elf_sect_no; - *length = dbg->de_debug_sects->ds_nbytes; - - buf = (Dwarf_Ptr *) dbg->de_debug_sects->ds_data; - - dbg->de_debug_sects = dbg->de_debug_sects->ds_next; - - /* We may want to call the section stuff more than once: see - dwarf_reset_section_bytes() do not do: dbg->de_n_debug_sect--; */ - - return buf; -} - -/* - No errors possible. -*/ -void -dwarf_reset_section_bytes(Dwarf_P_Debug dbg) -{ - dbg->de_debug_sects = dbg->de_first_debug_sect; - /* No need to reset; commented out decrement. dbg->de_n_debug_sect - = ???; */ - dbg->de_reloc_next_to_return = 0; - dbg->de_sect_sa_next_to_return = 0; -} - -/* - Storage handler. Gets either a new chunk of memory, or - a pointer in existing memory, from the linked list attached - to dbg at de_debug_sects, depending on size of nbytes - - Assume dbg not null, checked in top level routine - - Returns a pointer to the allocated buffer space for the - lib to fill in, predincrements next-to-use count so the - space requested is already counted 'used' - when this returns (ie, reserved). - -*/ -Dwarf_Small * -_dwarf_pro_buffer(Dwarf_P_Debug dbg, - int elfsectno, unsigned long nbytes) -{ - Dwarf_P_Section_Data cursect; - - - cursect = dbg->de_current_active_section; - /* By using MAGIC_SECT_NO we allow the following MAGIC_SECT_NO must - not match any legit section number. test to have just two - clauses (no NULL pointer test) See dwarf_producer_init(). */ - if ((cursect->ds_elf_sect_no != elfsectno) || - ((cursect->ds_nbytes + nbytes) > cursect->ds_orig_alloc) - ) { - - /* Either the elf section has changed or there is not enough - space in the current section. - - Create a new Dwarf_P_Section_Data_s for the chunk. and have - space 'on the end' for the buffer itself so we just do one - malloc (not two). - - */ - unsigned long space = nbytes; - - if (nbytes < CHUNK_SIZE) - space = CHUNK_SIZE; - - cursect = (Dwarf_P_Section_Data) - _dwarf_p_get_alloc(dbg, - sizeof(struct Dwarf_P_Section_Data_s) - + space); - - - if (cursect == NULL) - return (NULL); - - /* _dwarf_p_get_alloc zeroes the space... */ - - cursect->ds_data = (char *) cursect + - sizeof(struct Dwarf_P_Section_Data_s); - cursect->ds_orig_alloc = space; - cursect->ds_elf_sect_no = elfsectno; - cursect->ds_nbytes = nbytes; /* reserve this number of bytes - of space for caller to fill - in */ - - /* Now link on the end of the list, and mark this one as the - current one */ - - if (dbg->de_debug_sects->ds_elf_sect_no == MAGIC_SECT_NO) { - /* the only entry is the special one for 'no entry' so - delete that phony one while adding this initial real - one. */ - dbg->de_debug_sects = cursect; - dbg->de_current_active_section = cursect; - dbg->de_first_debug_sect = cursect; - } else { - dbg->de_current_active_section->ds_next = cursect; - dbg->de_current_active_section = cursect; - } - dbg->de_n_debug_sect++; - - return ((Dwarf_Small *) cursect->ds_data); - } - - /* There is enough space in the current buffer */ - { - Dwarf_Small *space_for_caller = (Dwarf_Small *) - (cursect->ds_data + cursect->ds_nbytes); - - cursect->ds_nbytes += nbytes; - return space_for_caller; - } -} - - -/*------------------------------------------------------------ - Given address advance and line advance, it gives - either special opcode, or a number < 0 -------------------------------------------------------------*/ -static int -_dwarf_pro_get_opc(Dwarf_Unsigned addr_adv, int line_adv) -{ - int opc; - - addr_adv = addr_adv / MIN_INST_LENGTH; - if (line_adv == 0 && addr_adv == 0) - return OPC_INCS_ZERO; - if (line_adv >= LINE_BASE && line_adv < LINE_BASE + LINE_RANGE) { - opc = - (line_adv - LINE_BASE) + (addr_adv * LINE_RANGE) + - OPCODE_BASE; - if (opc > 255) - return OPC_OUT_OF_RANGE; - return opc; - } else - return LINE_OUT_OF_RANGE; -} - -/*----------------------------------------------------------------------- - Handles abbreviations. It takes a die, searches through - current list of abbreviations for matching one. If it - finds one, it returns a pointer to it, and if it doesnt, - it returns a new one. Upto the user of this function to - link it up to the abbreviation head. If its a new one, - abb_idx has 0. ------------------------------------------------------------------------*/ -static Dwarf_P_Abbrev -_dwarf_pro_getabbrev(Dwarf_P_Die die, Dwarf_P_Abbrev head) -{ - Dwarf_P_Abbrev curabbrev; - Dwarf_P_Attribute curattr; - int res1; - int nattrs; - int match; - Dwarf_ufixed *forms = 0; - Dwarf_ufixed *attrs = 0; - - curabbrev = head; - while (curabbrev) { - if ((die->di_tag == curabbrev->abb_tag) && - ((die->di_child != NULL && - curabbrev->abb_children == DW_CHILDREN_yes) || - (die->di_child == NULL && - curabbrev->abb_children == DW_CHILDREN_no)) && - (die->di_n_attr == curabbrev->abb_n_attr)) { - - /* There is a chance of a match. */ - curattr = die->di_attrs; - match = 1; /* Assume match found. */ - while (match && curattr) { - res1 = _dwarf_pro_match_attr(curattr, - curabbrev, - (int) curabbrev-> - abb_n_attr); - if (res1 == 0) - match = 0; - curattr = curattr->ar_next; - } - if (match == 1) - return curabbrev; - } - curabbrev = curabbrev->abb_next; - } - - /* no match, create new abbreviation */ - if (die->di_n_attr != 0) { - forms = (Dwarf_ufixed *) - _dwarf_p_get_alloc(die->di_dbg, - sizeof(Dwarf_ufixed) * die->di_n_attr); - if (forms == NULL) - return NULL; - attrs = (Dwarf_ufixed *) - _dwarf_p_get_alloc(die->di_dbg, - sizeof(Dwarf_ufixed) * die->di_n_attr); - if (attrs == NULL) - return NULL; - } - nattrs = 0; - curattr = die->di_attrs; - while (curattr) { - attrs[nattrs] = curattr->ar_attribute; - forms[nattrs] = curattr->ar_attribute_form; - nattrs++; - curattr = curattr->ar_next; - } - - curabbrev = (Dwarf_P_Abbrev) - _dwarf_p_get_alloc(die->di_dbg, sizeof(struct Dwarf_P_Abbrev_s)); - if (curabbrev == NULL) - return NULL; - - if (die->di_child == NULL) - curabbrev->abb_children = DW_CHILDREN_no; - else - curabbrev->abb_children = DW_CHILDREN_yes; - curabbrev->abb_tag = die->di_tag; - curabbrev->abb_attrs = attrs; - curabbrev->abb_forms = forms; - curabbrev->abb_n_attr = die->di_n_attr; - curabbrev->abb_idx = 0; - curabbrev->abb_next = NULL; - - return curabbrev; -} - -/*------------------------------------------------------------------ - Tries to see if given attribute and form combination - exists in the given abbreviation --------------------------------------------------------------------*/ -static int -_dwarf_pro_match_attr(Dwarf_P_Attribute attr, - Dwarf_P_Abbrev abbrev, int no_attr) -{ - int i; - int found = 0; - - for (i = 0; i < no_attr; i++) { - if (attr->ar_attribute == abbrev->abb_attrs[i] && - attr->ar_attribute_form == abbrev->abb_forms[i]) { - found = 1; - break; - } - } - return found; -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_section.h b/usr/src/tools/ctf/dwarf/common/pro_section.h deleted file mode 100644 index b37ade44dc..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_section.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - - - -/* relocation section names */ -extern char *_dwarf_rel_section_names[]; - -/* section names */ -extern char *_dwarf_sectnames[]; - -/* struct to hold relocation entries. Its mantained as a linked - list of relocation structs, and will then be written at as a - whole into the relocation section. Whether its 32 bit or - 64 bit will be obtained from Dwarf_Debug pointer. -*/ - - - - - -/* - struct stores a chunk of data pertaining to a section -*/ -struct Dwarf_P_Section_Data_s { - int ds_elf_sect_no; /* elf section number */ - char *ds_data; /* data contained in section */ - unsigned long ds_nbytes; /* bytes of data used so far */ - unsigned long ds_orig_alloc; /* bytes allocated originally */ - Dwarf_P_Section_Data ds_next; /* next on the list */ -}; - -/* Used to allow a dummy initial struct (which we - drop before it gets used - This must not match any legitimate 'section' number. -*/ -#define MAGIC_SECT_NO -3 - -/* Size of chunk of data allocated in one alloc - Not clear if this is the best size. - Used to be just 4096 for user data, the section data struct - was a separate malloc. -*/ -#define CHUNK_SIZE (4096 - sizeof (struct Dwarf_P_Section_Data_s)) - -/* - chunk alloc routine - - if chunk->ds_data is nil, it will alloc CHUNK_SIZE bytes, - and return pointer to the beginning. If chunk is not nil, - it will see if there's enoungh space for nbytes in current - chunk, if not, add new chunk to linked list, and return - a char * pointer to it. Return null if unsuccessful. -*/ -Dwarf_Small *_dwarf_pro_buffer(Dwarf_P_Debug dbg, int sectno, - unsigned long nbytes); - -#define GET_CHUNK(dbg,sectno,ptr,nbytes,error) \ - { \ - (ptr) = _dwarf_pro_buffer((dbg),(sectno),(nbytes)); \ - if ((ptr) == NULL) { \ - DWARF_P_DBG_ERROR(dbg,DW_DLE_CHUNK_ALLOC,-1); \ - } \ - } - - - -int - _dwarf_transform_arange_to_disk(Dwarf_P_Debug dbg, - Dwarf_Error * error); - -/* These are for creating ELF section type codes. -*/ -#if defined(linux) || defined(__BEOS__) || !defined(SHT_MIPS_DWARF) -/* Intel's SoftSdv accepts only this */ -#define SECTION_TYPE SHT_PROGBITS -#else -#define SECTION_TYPE SHT_MIPS_DWARF -#endif diff --git a/usr/src/tools/ctf/dwarf/common/pro_types.c b/usr/src/tools/ctf/dwarf/common/pro_types.c deleted file mode 100644 index 1f3f93280c..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_types.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#include -#include -#ifdef HAVE_ELFACCESS_H -#include -#endif -#include "pro_incl.h" -#include "pro_section.h" - - -/* - This function adds another type name to the - list of type names for the given Dwarf_P_Debug. - It returns 0 on error, and 1 otherwise. -*/ -Dwarf_Unsigned -dwarf_add_typename(Dwarf_P_Debug dbg, - Dwarf_P_Die die, - char *type_name, Dwarf_Error * error) -{ - return - _dwarf_add_simple_name_entry(dbg, die, type_name, - dwarf_snk_typename, error); -} - -/* - The following is the generic 'add a simple name entry' - for any of the simple name sections. - - See enum dwarf_sn_kind in pro_opaque.h - -*/ -Dwarf_Unsigned -_dwarf_add_simple_name_entry(Dwarf_P_Debug dbg, - Dwarf_P_Die die, - char *entry_name, - enum dwarf_sn_kind entrykind, - Dwarf_Error * error) -{ - Dwarf_P_Simple_nameentry nameentry; - Dwarf_P_Simple_name_header hdr; - char *name; - int uword_size; - - if (dbg == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return (0); - } - - if (die == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL); - return (0); - } - - - nameentry = (Dwarf_P_Simple_nameentry) - _dwarf_p_get_alloc(dbg, - sizeof(struct Dwarf_P_Simple_nameentry_s)); - if (nameentry == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (0); - } - - name = _dwarf_p_get_alloc(dbg, strlen(entry_name) + 1); - if (name == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (0); - } - strcpy(name, entry_name); - - nameentry->sne_die = die; - nameentry->sne_name = name; - nameentry->sne_name_len = strlen(name); - uword_size = dbg->de_offset_size; - - hdr = &dbg->de_simple_name_headers[entrykind]; - if (hdr->sn_head == NULL) - hdr->sn_head = hdr->sn_tail = nameentry; - else { - hdr->sn_tail->sne_next = nameentry; - hdr->sn_tail = nameentry; - } - hdr->sn_count++; - hdr->sn_net_len += uword_size + nameentry->sne_name_len + 1; - - return (1); -} - - - -/* - _dwarf_transform_simplename_to_disk writes - ".rel.debug_pubnames", - ".rel.debug_funcnames", sgi extension - ".rel.debug_typenames", sgi extension - ".rel.debug_varnames", sgi extension - ".rel.debug_weaknames", sgi extension - to disk. - section_index indexes one of those sections. - entrykind is one of those 'kind's. - -*/ -int -_dwarf_transform_simplename_to_disk(Dwarf_P_Debug dbg, enum dwarf_sn_kind entrykind, int section_index, /* in - de_elf_sects - etc - */ - Dwarf_Error * error) -{ - - - /* Used to fill in 0. */ - const Dwarf_Signed big_zero = 0; - - /* Used to scan the section data buffers. */ - Dwarf_P_Section_Data debug_sect; - - Dwarf_Signed debug_info_size; - - Dwarf_P_Simple_nameentry nameentry_original; - Dwarf_P_Simple_nameentry nameentry; - Dwarf_Small *stream_bytes; - Dwarf_Small *cur_stream_bytes_ptr; - Dwarf_Unsigned stream_bytes_count; - Dwarf_Unsigned adjusted_length; /* count excluding length field - */ - - - int uword_size = dbg->de_offset_size; - int extension_size = dbg->de_64bit_extension ? 4 : 0; - - Dwarf_P_Simple_name_header hdr; - - - /* ***** BEGIN CODE ***** */ - - debug_info_size = 0; - for (debug_sect = dbg->de_debug_sects; debug_sect != NULL; - debug_sect = debug_sect->ds_next) { - /* We want the size of the .debug_info section for this CU - because the dwarf spec requires us to output it below so we - look for it specifically. */ - if (debug_sect->ds_elf_sect_no == dbg->de_elf_sects[DEBUG_INFO]) { - debug_info_size += debug_sect->ds_nbytes; - } - } - - hdr = &dbg->de_simple_name_headers[entrykind]; - /* Size of the .debug_typenames (or similar) section header. */ - stream_bytes_count = extension_size + uword_size + /* Size of - length - field. */ - sizeof(Dwarf_Half) + /* Size of version field. */ - uword_size + /* Size of .debug_info offset. */ - uword_size; /* Size of .debug_names. */ - - - - nameentry_original = hdr->sn_head; - nameentry = nameentry_original; - /* add in the content size */ - stream_bytes_count += hdr->sn_net_len; - - /* Size of the last 0 offset. */ - stream_bytes_count += uword_size; - - /* Now we know how long the entire section is */ - GET_CHUNK(dbg, dbg->de_elf_sects[section_index], - stream_bytes, (unsigned long) stream_bytes_count, error); - if (stream_bytes == NULL) { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (0); - } - cur_stream_bytes_ptr = stream_bytes; - - if (extension_size) { - Dwarf_Unsigned x = DISTINGUISHED_VALUE; - - WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, - (const void *) &x, sizeof(x), extension_size); - cur_stream_bytes_ptr += extension_size; - - } - /* Write the adjusted length of .debug_*names section. */ - adjusted_length = stream_bytes_count - uword_size - extension_size; - WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, - (const void *) &adjusted_length, - sizeof(adjusted_length), uword_size); - cur_stream_bytes_ptr += uword_size; - - /* Write the version as 2 bytes. */ - { - Dwarf_Half verstamp = CURRENT_VERSION_STAMP; - - WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, - (const void *) &verstamp, - sizeof(verstamp), sizeof(Dwarf_Half)); - cur_stream_bytes_ptr += sizeof(Dwarf_Half); - } - - /* Write the offset of the compile-unit. */ - WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, - (const void *) &big_zero, - sizeof(big_zero), uword_size); - cur_stream_bytes_ptr += uword_size; - - /* now create the relocation for the compile_unit offset */ - { - int res = dbg->de_reloc_name(dbg, - section_index, - extension_size + uword_size + - sizeof(Dwarf_Half) - /* r_offset */ - , - /* debug_info section name symbol */ - dbg->de_sect_name_idx[DEBUG_INFO], - dwarf_drt_data_reloc, - uword_size); - - if (res != DW_DLV_OK) { - { - _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (0); - } - } - } - - /* Write the size of .debug_info section. */ - WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, - (const void *) &debug_info_size, - sizeof(debug_info_size), uword_size); - cur_stream_bytes_ptr += uword_size; - - - for (nameentry = nameentry_original; - nameentry != NULL; nameentry = nameentry->sne_next) { - - /* Copy offset of die from start of compile-unit. */ - WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, - (const void *) &nameentry->sne_die->di_offset, - sizeof(nameentry->sne_die->di_offset), - uword_size); - cur_stream_bytes_ptr += uword_size; - - /* Copy the type name. */ - strcpy((char *) cur_stream_bytes_ptr, nameentry->sne_name); - cur_stream_bytes_ptr += nameentry->sne_name_len + 1; - } - - WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, - (const void *) &big_zero, - sizeof(big_zero), uword_size); - - - - - return (int) dbg->de_n_debug_sect; -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_types.h b/usr/src/tools/ctf/dwarf/common/pro_types.h deleted file mode 100644 index 817609215b..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_types.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - -/* pro_types.h */ - - -int _dwarf_transform_simplename_to_disk(Dwarf_P_Debug dbg, enum dwarf_sn_kind entrykind, int section_index, /* in - de_elf_sects - etc - */ - Dwarf_Error * error); diff --git a/usr/src/tools/ctf/dwarf/common/pro_util.h b/usr/src/tools/ctf/dwarf/common/pro_util.h deleted file mode 100644 index 56bde8bda6..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_util.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - - -#define IS_64BIT(dbg) ((dbg)->de_flags & DW_DLC_SIZE_64 ? 1 : 0) -#define ISA_IA64(dbg) ((dbg)->de_flags & DW_DLC_ISA_IA64 ? 1 : 0) - -/* definition of sizes of types, given target machine */ -#define sizeof_sbyte(dbg) sizeof(Dwarf_Sbyte) -#define sizeof_ubyte(dbg) sizeof(Dwarf_Ubyte) -#define sizeof_uhalf(dbg) sizeof(Dwarf_Half) -/* certain sizes not defined here, but set in dbg record. - See pro_init.c -*/ - -/* Computes amount of padding necessary to align n to a k-boundary. */ -/* Important: Assumes n, k both GREATER than zero. */ -#define PADDING(n, k) ( (k)-1 - ((n)-1)%(k) ) - -/* The following defines are only important for users of the -** producer part of libdwarf, and such should have these -** defined correctly (as necessary) -** by the #include done in pro_incl.h -** before the #include "pro_util.h". -** For others producer macros do not matter so 0 is a usable value, and -** zero values let compilation succeed on more non-MIPS architectures. -** A better approach would be welcome. -*/ -/* R_MIPS* are #define so #ifndef works */ -/* R_IA_64* are not necessarily #define (might be enum) so #ifndef - is useless, we use the configure script generating - HAVE_R_IA_64_DIR32LSB and HAVE_R_IA64_DIR32LSB. -*/ -#ifndef R_MIPS_64 -#define R_MIPS_64 0 -#endif -#ifndef R_MIPS_32 -#define R_MIPS_32 0 -#endif -#ifndef R_MIPS_SCN_DISP -#define R_MIPS_SCN_DISP 0 -#endif - -/* R_IA_64_DIR32LSB came before the now-standard R_IA64_DIR32LSB - (etc) was defined. This now deals with either form, - preferring the new form if available. */ -#ifdef HAVE_R_IA64_DIR32LSB -#define DWARF_PRO_R_IA64_DIR32LSB R_IA64_DIR32LSB -#define DWARF_PRO_R_IA64_DIR64LSB R_IA64_DIR64LSB -#define DWARF_PRO_R_IA64_SEGREL64LSB R_IA64_SEGREL64LSB -#define DWARF_PRO_R_IA64_SEGREL32LSB R_IA64_SEGREL32LSB -#endif -#if defined(HAVE_R_IA_64_DIR32LSB) && !defined(HAVE_R_IA64_DIR32LSB) -#define DWARF_PRO_R_IA64_DIR32LSB R_IA_64_DIR32LSB -#define DWARF_PRO_R_IA64_DIR64LSB R_IA_64_DIR64LSB -#define DWARF_PRO_R_IA64_SEGREL64LSB R_IA_64_SEGREL64LSB -#define DWARF_PRO_R_IA64_SEGREL32LSB R_IA_64_SEGREL32LSB -#endif -#if !defined(HAVE_R_IA_64_DIR32LSB) && !defined(HAVE_R_IA64_DIR32LSB) -#define DWARF_PRO_R_IA64_DIR32LSB 0 -#define DWARF_PRO_R_IA64_DIR64LSB 0 -#define DWARF_PRO_R_IA64_SEGREL64LSB 0 -#define DWARF_PRO_R_IA64_SEGREL32LSB 0 -#endif - -/* - * The default "I don't know" value can't be zero. - * Because that's the sentinel value that means "no relocation". - * In order to use this library in 'symbolic relocation mode we - * don't care if this value is the right relocation value, - * only that it's non-NULL. So at the end, we define it - * to something sensible. - */ - - - -#if defined(sun) -#if defined(sparc) -#define Get_REL64_isa(dbg) (R_SPARC_UA64) -#define Get_REL32_isa(dbg) (R_SPARC_UA32) -#define Get_REL_SEGREL_isa(dbg) (R_SPARC_NONE) /* I don't know! */ -#else /* i386 */ -#define Get_REL64_isa(dbg) (R_386_32) /* Any non-zero value is ok */ -#define Get_REL32_isa(dbg) (R_386_32) -#define Get_REL_SEGREL_isa(dbg) (R_386_NONE) /* I don't know! */ -#endif /* sparc || i386 */ -#else /* !sun */ -#ifdef HAVE_SYS_IA64_ELF_H -#define Get_REL64_isa(dbg) (ISA_IA64(dbg) ? \ - DWARF_PRO_R_IA64_DIR64LSB : R_MIPS_64) -#define Get_REL32_isa(dbg) (ISA_IA64(dbg) ? \ - DWARF_PRO_R_IA64_DIR32LSB : R_MIPS_32) - - -/* ia64 uses 32bit dwarf offsets for sections */ -#define Get_REL_SEGREL_isa(dbg) (ISA_IA64(dbg) ? \ - DWARF_PRO_R_IA64_SEGREL32LSB : R_MIPS_SCN_DISP) -#else /* HAVE_SYS_IA64_ELF_H */ - -#if !defined(linux) && !defined(__BEOS__) -#define Get_REL64_isa(dbg) (R_MIPS_64) -#define Get_REL32_isa(dbg) (R_MIPS_32) -#define Get_REL_SEGREL_isa(dbg) (R_MIPS_SCN_DISP) -#else -#define Get_REL64_isa(dbg) (1) -#define Get_REL32_isa(dbg) (1) /* these are used on linux */ -#define Get_REL_SEGREL_isa(dbg) (1) /* non zero values, see comments above */ -#endif - -#endif /* HAVE_SYS_IA64_ELF_H */ -#endif /* !sun */ - - diff --git a/usr/src/tools/ctf/dwarf/common/pro_vars.c b/usr/src/tools/ctf/dwarf/common/pro_vars.c deleted file mode 100644 index 3e75a9d9af..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_vars.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#include -#include -#ifdef HAVE_ELFACCESS_H -#include -#endif -#include "pro_incl.h" -#include "pro_section.h" - -/* - This function adds another variable name to the - list of variable names for the given Dwarf_P_Debug. - It returns 0 on error, and 1 otherwise. -*/ -Dwarf_Unsigned -dwarf_add_varname(Dwarf_P_Debug dbg, - Dwarf_P_Die die, char *var_name, Dwarf_Error * error) -{ - return - _dwarf_add_simple_name_entry(dbg, die, var_name, - dwarf_snk_varname, error); - - -} diff --git a/usr/src/tools/ctf/dwarf/common/pro_weaks.c b/usr/src/tools/ctf/dwarf/common/pro_weaks.c deleted file mode 100644 index 8c74bf08ca..0000000000 --- a/usr/src/tools/ctf/dwarf/common/pro_weaks.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - - Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ - - - -#include "config.h" -#include "libdwarfdefs.h" -#include -#include -#ifdef HAVE_ELFACCESS_H -#include -#endif -#include "pro_incl.h" -#include "pro_section.h" - -/* - This function adds another weak name to the - list of weak names for the given Dwarf_P_Debug. - It returns 0 on error, and 1 otherwise. -*/ -Dwarf_Unsigned -dwarf_add_weakname(Dwarf_P_Debug dbg, - Dwarf_P_Die die, - char *weak_name, Dwarf_Error * error) -{ - return - _dwarf_add_simple_name_entry(dbg, die, weak_name, - dwarf_snk_weakname, error); -} diff --git a/usr/src/tools/ctf/libctf/Makefile b/usr/src/tools/ctf/libctf/Makefile new file mode 100644 index 0000000000..8ea6ae181f --- /dev/null +++ b/usr/src/tools/ctf/libctf/Makefile @@ -0,0 +1,46 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../../Makefile.tools + +HDRS = libctf.h +HDRDIR = common + +SUBDIRS = $(MACH) + +all := TARGET = all +clean := TARGET = clean +clobber := TARGET = clobber +install := TARGET = install +lint := TARGET = lint + +.KEEP_STATE: + +all clean clobber install lint: $(SUBDIRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: diff --git a/usr/src/tools/ctf/libctf/Makefile.com b/usr/src/tools/ctf/libctf/Makefile.com new file mode 100644 index 0000000000..89769c5521 --- /dev/null +++ b/usr/src/tools/ctf/libctf/Makefile.com @@ -0,0 +1,51 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2018 Joyent, Inc. +# + +include $(SRC)/lib/libctf/Makefile.shared.com +include ../../Makefile.ctf + +CSTD = $(CSTD_GNU99) +C99LMODE = -Xc99=%all + +CPPFLAGS += -I$(SRC)/lib/libctf/common/ \ + -I$(SRC)/lib/libdwarf/common/ \ + -I$(SRC)/lib/mergeq \ + -include ../../common/ctf_headers.h \ + -DCTF_OLD_VERSIONS \ + -DCTF_TOOLS_BUILD +LDLIBS += -lc -lelf -L$(ROOTONBLDLIBMACH) -ldwarf -lavl +DYNFLAGS += '-R$$ORIGIN/../../lib/$(MACH)' + +.KEEP_STATE: + +all: $(LIBS) + +install: all $(ROOTONBLDLIBMACH)/libctf.so.1 $(ROOTONBLDLIBMACH)/libctf.so + +$(ROOTONBLDLIBMACH)/%: % + $(INS.file) + +$(ROOTONBLDLIBMACH)/$(LIBLINKS): $(ROOTONBLDLIBMACH)/$(LIBLINKS)$(VERS) + $(INS.liblink) + +# +# Just like with libdwarf, we can't actually add ctf to ourselves, +# because we're part of the tools for creating CTF. +# +$(DYNLIB) := CTFMERGE_POST= : +CTFCONVERT_O= : + +include $(SRC)/lib/Makefile.targ +include $(SRC)/lib/libctf/Makefile.shared.targ diff --git a/usr/src/tools/ctf/libctf/i386/Makefile b/usr/src/tools/ctf/libctf/i386/Makefile new file mode 100644 index 0000000000..a926f22084 --- /dev/null +++ b/usr/src/tools/ctf/libctf/i386/Makefile @@ -0,0 +1,18 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015, Joyent, Inc. +# + +include ../Makefile.com + +all: $(LIBS) diff --git a/usr/src/tools/ctf/libctf/sparc/Makefile b/usr/src/tools/ctf/libctf/sparc/Makefile new file mode 100644 index 0000000000..a926f22084 --- /dev/null +++ b/usr/src/tools/ctf/libctf/sparc/Makefile @@ -0,0 +1,18 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015, Joyent, Inc. +# + +include ../Makefile.com + +all: $(LIBS) diff --git a/usr/src/tools/make/lib/bsd/Makefile b/usr/src/tools/make/lib/bsd/Makefile index 3dff341075..d9f7398611 100644 --- a/usr/src/tools/make/lib/bsd/Makefile +++ b/usr/src/tools/make/lib/bsd/Makefile @@ -28,4 +28,8 @@ install: all lint: +# We can't create CTF in the tools build because of a bootstrap bug with the new CTF +$(DYNLIB) := CTFMERGE_POST= : +CTFCONVERT_O= : + include $(SRC)/lib/Makefile.targ diff --git a/usr/src/tools/make/lib/makestate/Makefile.com b/usr/src/tools/make/lib/makestate/Makefile.com index 7f2324264c..1bf0d1d89a 100644 --- a/usr/src/tools/make/lib/makestate/Makefile.com +++ b/usr/src/tools/make/lib/makestate/Makefile.com @@ -37,4 +37,8 @@ $(ROOTONBLDLIBMACH)/%: % $(ROOTONBLDLIBMACH64)/%: % $(INS.file) +# We can't create CTF in the tools build because of a bootstrap bug with the new CTF +$(DYNLIB) := CTFMERGE_POST= : +CTFCONVERT_O= : + include $(SRC)/lib/Makefile.targ diff --git a/usr/src/tools/make/lib/mksh/Makefile b/usr/src/tools/make/lib/mksh/Makefile index 418cb43cb5..b351b488bb 100644 --- a/usr/src/tools/make/lib/mksh/Makefile +++ b/usr/src/tools/make/lib/mksh/Makefile @@ -29,4 +29,8 @@ install: all lint: +# We can't create CTF in the tools build because of a bootstrap bug with the new CTF +$(DYNLIB) := CTFMERGE_POST= : +CTFCONVERT_O= : + include $(SRC)/lib/Makefile.targ diff --git a/usr/src/tools/make/lib/vroot/Makefile b/usr/src/tools/make/lib/vroot/Makefile index e119349178..7965de5fde 100644 --- a/usr/src/tools/make/lib/vroot/Makefile +++ b/usr/src/tools/make/lib/vroot/Makefile @@ -50,4 +50,8 @@ install: all lint: +# We can't create CTF in the tools build because of a bootstrap bug with the new CTF +$(DYNLIB) := CTFMERGE_POST= : +CTFCONVERT_O= : + include $(SRC)/lib/Makefile.targ diff --git a/usr/src/uts/Makefile.uts b/usr/src/uts/Makefile.uts index d1121d25ff..8f341807e1 100644 --- a/usr/src/uts/Makefile.uts +++ b/usr/src/uts/Makefile.uts @@ -643,3 +643,11 @@ PRIVS_DEF = $(SRC)/uts/common/os/priv_defs # USBDEVS_AWK = $(SRC)/uts/common/io/usb/usbdevs2h.awk USBDEVS_DATA = $(SRC)/uts/common/io/usb/usbdevs + + +# +# If we're using the newer CTF tools, then we need to make sure that we +# are building with the private -X option to ctfconvert which allows us +# to fixup the struct cpu to account for machcpu. +# +$(BUILD_NEW_CTF_TOOLS)CTFCVTFLAGS += -X diff --git a/usr/src/uts/common/ctf/ctf_mod.c b/usr/src/uts/common/ctf/ctf_mod.c index b34cf400cd..421b922c96 100644 --- a/usr/src/uts/common/ctf/ctf_mod.c +++ b/usr/src/uts/common/ctf/ctf_mod.c @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include #include #include @@ -115,6 +113,15 @@ ctf_version(int version) return (_libctf_version); } +/*ARGSUSED*/ +ctf_file_t * +ctf_fdcreate_int(int fd, int *errp, ctf_sect_t *ctfp) +{ + if (errp != NULL) + *errp = ENOTSUP; + return (NULL); +} + /*ARGSUSED*/ ctf_file_t * ctf_modopen(struct module *mp, int *error) diff --git a/usr/src/uts/common/sys/ctf.h b/usr/src/uts/common/sys/ctf.h index 065e985b82..2e41cf9a0e 100644 --- a/usr/src/uts/common/sys/ctf.h +++ b/usr/src/uts/common/sys/ctf.h @@ -22,13 +22,13 @@ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2018 Joyent, Inc. */ #ifndef _CTF_H #define _CTF_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include #ifdef __cplusplus @@ -220,11 +220,13 @@ typedef struct ctf_type { #define CTF_TYPE_NAME(stid, offset) \ (((stid) << 31) | ((offset) & 0x7fffffff)) -#define CTF_TYPE_ISPARENT(id) ((id) < 0x8000) -#define CTF_TYPE_ISCHILD(id) ((id) > 0x7fff) +#define CTF_CHILD_START (0x8000) +#define CTF_TYPE_ISPARENT(id) ((id) < CTF_CHILD_START) +#define CTF_TYPE_ISCHILD(id) ((id) >= CTF_CHILD_START) -#define CTF_TYPE_TO_INDEX(id) ((id) & 0x7fff) -#define CTF_INDEX_TO_TYPE(id, child) ((child) ? ((id) | 0x8000) : (id)) +#define CTF_TYPE_TO_INDEX(id) ((id) & (CTF_CHILD_START - 1)) +#define CTF_INDEX_TO_TYPE(id, child) \ + ((child) ? ((id) | CTF_CHILD_START) : (id)) #define CTF_PARENT_SHIFT 15 #define CTF_STRTAB_0 0 /* symbolic define for string table id 0 */ diff --git a/usr/src/uts/common/sys/ctf_api.h b/usr/src/uts/common/sys/ctf_api.h index 04d73c3181..073cc4f0d6 100644 --- a/usr/src/uts/common/sys/ctf_api.h +++ b/usr/src/uts/common/sys/ctf_api.h @@ -24,7 +24,7 @@ * Use is subject to license terms. */ /* - * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright 2018 Joyent, Inc. */ /* @@ -60,6 +60,65 @@ extern "C" { typedef struct ctf_file ctf_file_t; typedef long ctf_id_t; +#define ECTF_BASE 1000 /* base value for libctf errnos */ + +enum { + ECTF_FMT = ECTF_BASE, /* file is not in CTF or ELF format */ + ECTF_ELFVERS, /* ELF version is more recent than libctf */ + ECTF_CTFVERS, /* CTF version is more recent than libctf */ + ECTF_ENDIAN, /* data is different endian-ness than lib */ + ECTF_SYMTAB, /* symbol table uses invalid entry size */ + ECTF_SYMBAD, /* symbol table data buffer invalid */ + ECTF_STRBAD, /* string table data buffer invalid */ + ECTF_CORRUPT, /* file data corruption detected */ + ECTF_NOCTFDATA, /* ELF file does not contain CTF data */ + ECTF_NOCTFBUF, /* buffer does not contain CTF data */ + ECTF_NOSYMTAB, /* symbol table data is not available */ + ECTF_NOPARENT, /* parent CTF container is not available */ + ECTF_DMODEL, /* data model mismatch */ + ECTF_MMAP, /* failed to mmap a data section */ + ECTF_ZMISSING, /* decompression library not installed */ + ECTF_ZINIT, /* failed to initialize decompression library */ + ECTF_ZALLOC, /* failed to allocate decompression buffer */ + ECTF_DECOMPRESS, /* failed to decompress CTF data */ + ECTF_STRTAB, /* string table for this string is missing */ + ECTF_BADNAME, /* string offset is corrupt w.r.t. strtab */ + ECTF_BADID, /* invalid type ID number */ + ECTF_NOTSOU, /* type is not a struct or union */ + ECTF_NOTENUM, /* type is not an enum */ + ECTF_NOTSUE, /* type is not a struct, union, or enum */ + ECTF_NOTINTFP, /* type is not an integer or float */ + ECTF_NOTARRAY, /* type is not an array */ + ECTF_NOTREF, /* type does not reference another type */ + ECTF_NAMELEN, /* buffer is too small to hold type name */ + ECTF_NOTYPE, /* no type found corresponding to name */ + ECTF_SYNTAX, /* syntax error in type name */ + ECTF_NOTFUNC, /* symtab entry does not refer to a function */ + ECTF_NOFUNCDAT, /* no func info available for function */ + ECTF_NOTDATA, /* symtab entry does not refer to a data obj */ + ECTF_NOTYPEDAT, /* no type info available for object */ + ECTF_NOLABEL, /* no label found corresponding to name */ + ECTF_NOLABELDATA, /* file does not contain any labels */ + ECTF_NOTSUP, /* feature not supported */ + ECTF_NOENUMNAM, /* enum element name not found */ + ECTF_NOMEMBNAM, /* member name not found */ + ECTF_RDONLY, /* CTF container is read-only */ + ECTF_DTFULL, /* CTF type is full (no more members allowed) */ + ECTF_FULL, /* CTF container is full */ + ECTF_DUPMEMBER, /* duplicate member name definition */ + ECTF_CONFLICT, /* conflicting type definition present */ + ECTF_REFERENCED, /* type has outstanding references */ + ECTF_NOTDYN, /* type is not a dynamic type */ + ECTF_ELF, /* elf library failure */ + ECTF_MCHILD, /* cannot merge child container */ + ECTF_LABELEXISTS, /* label already exists */ + ECTF_LCONFLICT, /* merged labels conflict */ + ECTF_ZLIB, /* zlib library failure */ + ECTF_CONVBKERR, /* CTF conversion backend error */ + ECTF_CONVNOCSRC, /* No C source to convert from */ + ECTF_NOCONVBKEND /* No applicable conversion backend */ +}; + /* * If the debugger needs to provide the CTF library with a set of raw buffers * for use as the CTF data, symbol table, and string table, it can do so by @@ -143,19 +202,24 @@ typedef struct ctf_lblinfo { typedef int ctf_visit_f(const char *, ctf_id_t, ulong_t, int, void *); typedef int ctf_member_f(const char *, ctf_id_t, ulong_t, void *); typedef int ctf_enum_f(const char *, int, void *); -typedef int ctf_type_f(ctf_id_t, void *); +typedef int ctf_type_f(ctf_id_t, boolean_t, void *); typedef int ctf_label_f(const char *, const ctf_lblinfo_t *, void *); +typedef int ctf_function_f(const char *, ulong_t, ctf_funcinfo_t *, void *); +typedef int ctf_object_f(const char *, ctf_id_t, ulong_t, void *); +typedef int ctf_string_f(const char *, void *); extern ctf_file_t *ctf_bufopen(const ctf_sect_t *, const ctf_sect_t *, const ctf_sect_t *, int *); extern ctf_file_t *ctf_fdopen(int, int *); extern ctf_file_t *ctf_open(const char *, int *); extern ctf_file_t *ctf_create(int *); +extern ctf_file_t *ctf_fdcreate(int, int *); extern ctf_file_t *ctf_dup(ctf_file_t *); extern void ctf_close(ctf_file_t *); extern ctf_file_t *ctf_parent_file(ctf_file_t *); extern const char *ctf_parent_name(ctf_file_t *); +extern const char *ctf_parent_label(ctf_file_t *); extern int ctf_import(ctf_file_t *, ctf_file_t *); extern int ctf_setmodel(ctf_file_t *, int); @@ -165,23 +229,34 @@ extern void ctf_setspecific(ctf_file_t *, void *); extern void *ctf_getspecific(ctf_file_t *); extern int ctf_errno(ctf_file_t *); +extern uint_t ctf_flags(ctf_file_t *); extern const char *ctf_errmsg(int); extern int ctf_version(int); +extern ctf_id_t ctf_max_id(ctf_file_t *); +extern ulong_t ctf_nr_syms(ctf_file_t *); + extern int ctf_func_info(ctf_file_t *, ulong_t, ctf_funcinfo_t *); +extern int ctf_func_info_by_id(ctf_file_t *, ctf_id_t, ctf_funcinfo_t *); extern int ctf_func_args(ctf_file_t *, ulong_t, uint_t, ctf_id_t *); +extern int ctf_func_args_by_id(ctf_file_t *, ctf_id_t, uint_t, ctf_id_t *); extern ctf_id_t ctf_lookup_by_name(ctf_file_t *, const char *); extern ctf_id_t ctf_lookup_by_symbol(ctf_file_t *, ulong_t); +extern char *ctf_symbol_name(ctf_file_t *, ulong_t, char *, size_t); + extern ctf_id_t ctf_type_resolve(ctf_file_t *, ctf_id_t); extern ssize_t ctf_type_lname(ctf_file_t *, ctf_id_t, char *, size_t); extern char *ctf_type_name(ctf_file_t *, ctf_id_t, char *, size_t); extern char *ctf_type_qname(ctf_file_t *, ctf_id_t, char *, size_t, const char *); +extern char *ctf_type_cname(ctf_file_t *, ctf_id_t, char *, size_t, + const char *); extern ssize_t ctf_type_size(ctf_file_t *, ctf_id_t); extern ssize_t ctf_type_align(ctf_file_t *, ctf_id_t); extern int ctf_type_kind(ctf_file_t *, ctf_id_t); +extern const char *ctf_kind_name(ctf_file_t *, int); extern ctf_id_t ctf_type_reference(ctf_file_t *, ctf_id_t); extern ctf_id_t ctf_type_pointer(ctf_file_t *, ctf_id_t); extern int ctf_type_encoding(ctf_file_t *, ctf_id_t, ctf_encoding_t *); @@ -201,37 +276,50 @@ extern int ctf_label_info(ctf_file_t *, const char *, ctf_lblinfo_t *); extern int ctf_member_iter(ctf_file_t *, ctf_id_t, ctf_member_f *, void *); extern int ctf_enum_iter(ctf_file_t *, ctf_id_t, ctf_enum_f *, void *); -extern int ctf_type_iter(ctf_file_t *, ctf_type_f *, void *); +extern int ctf_type_iter(ctf_file_t *, boolean_t, ctf_type_f *, void *); extern int ctf_label_iter(ctf_file_t *, ctf_label_f *, void *); +extern int ctf_function_iter(ctf_file_t *, ctf_function_f *, void *); +extern int ctf_object_iter(ctf_file_t *, ctf_object_f *, void *); +extern int ctf_string_iter(ctf_file_t *, ctf_string_f *, void *); extern ctf_id_t ctf_add_array(ctf_file_t *, uint_t, const ctf_arinfo_t *); -extern ctf_id_t ctf_add_const(ctf_file_t *, uint_t, ctf_id_t); +extern ctf_id_t ctf_add_const(ctf_file_t *, uint_t, const char *, ctf_id_t); extern ctf_id_t ctf_add_enum(ctf_file_t *, uint_t, const char *); extern ctf_id_t ctf_add_float(ctf_file_t *, uint_t, const char *, const ctf_encoding_t *); extern ctf_id_t ctf_add_forward(ctf_file_t *, uint_t, const char *, uint_t); -extern ctf_id_t ctf_add_function(ctf_file_t *, uint_t, - const ctf_funcinfo_t *, const ctf_id_t *); +extern ctf_id_t ctf_add_funcptr(ctf_file_t *, uint_t, const ctf_funcinfo_t *, + const ctf_id_t *); extern ctf_id_t ctf_add_integer(ctf_file_t *, uint_t, const char *, const ctf_encoding_t *); -extern ctf_id_t ctf_add_pointer(ctf_file_t *, uint_t, ctf_id_t); +extern ctf_id_t ctf_add_pointer(ctf_file_t *, uint_t, const char *, ctf_id_t); extern ctf_id_t ctf_add_type(ctf_file_t *, ctf_file_t *, ctf_id_t); extern ctf_id_t ctf_add_typedef(ctf_file_t *, uint_t, const char *, ctf_id_t); -extern ctf_id_t ctf_add_restrict(ctf_file_t *, uint_t, ctf_id_t); +extern ctf_id_t ctf_add_restrict(ctf_file_t *, uint_t, const char *, ctf_id_t); extern ctf_id_t ctf_add_struct(ctf_file_t *, uint_t, const char *); extern ctf_id_t ctf_add_union(ctf_file_t *, uint_t, const char *); -extern ctf_id_t ctf_add_volatile(ctf_file_t *, uint_t, ctf_id_t); +extern ctf_id_t ctf_add_volatile(ctf_file_t *, uint_t, const char *, ctf_id_t); extern int ctf_add_enumerator(ctf_file_t *, ctf_id_t, const char *, int); -extern int ctf_add_member(ctf_file_t *, ctf_id_t, const char *, ctf_id_t); +extern int ctf_add_member(ctf_file_t *, ctf_id_t, const char *, ctf_id_t, + ulong_t); + + +extern int ctf_add_function(ctf_file_t *, ulong_t, const ctf_funcinfo_t *, + const ctf_id_t *); +extern int ctf_add_object(ctf_file_t *, ulong_t, ctf_id_t); +extern int ctf_add_label(ctf_file_t *, const char *, ctf_id_t, uint_t); extern int ctf_set_array(ctf_file_t *, ctf_id_t, const ctf_arinfo_t *); +extern int ctf_set_root(ctf_file_t *, ctf_id_t, const boolean_t); +extern int ctf_set_size(ctf_file_t *, ctf_id_t, const ulong_t); extern int ctf_delete_type(ctf_file_t *, ctf_id_t); extern int ctf_update(ctf_file_t *); extern int ctf_discard(ctf_file_t *); extern int ctf_write(ctf_file_t *, int); +extern void ctf_dataptr(ctf_file_t *, const void **, size_t *); #ifdef _KERNEL diff --git a/usr/src/uts/intel/ctf/Makefile b/usr/src/uts/intel/ctf/Makefile index 207a5ff8ea..97457d0c0c 100644 --- a/usr/src/uts/intel/ctf/Makefile +++ b/usr/src/uts/intel/ctf/Makefile @@ -22,6 +22,8 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2018 Joyent, Inc. +# UTSBASE = ../.. @@ -36,6 +38,8 @@ ALL_TARGET = $(BINARY) LINT_TARGET = $(MODULE).lint INSTALL_TARGET = $(BINARY) $(ROOTMODULE) +C99LMODE= -Xc99=%all + CPPFLAGS += -I$(SRC)/common/ctf -DCTF_OLD_VERSIONS LDFLAGS += $(BREDUCE) -M$(UTSBASE)/common/ctf/mapfile -dy diff --git a/usr/src/uts/sparc/ctf/Makefile b/usr/src/uts/sparc/ctf/Makefile index bb40cd9d28..0f463684dd 100644 --- a/usr/src/uts/sparc/ctf/Makefile +++ b/usr/src/uts/sparc/ctf/Makefile @@ -22,6 +22,8 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2018 Joyent, Inc. +# UTSBASE = ../.. @@ -36,6 +38,8 @@ ALL_TARGET = $(BINARY) LINT_TARGET = $(MODULE).lint INSTALL_TARGET = $(BINARY) $(ROOTMODULE) +C99LMODE= -Xc99=%all + CFLAGS += $(CCVERBOSE) CPPFLAGS += -I$(SRC)/common/ctf -DCTF_OLD_VERSIONS LDFLAGS += $(BREDUCE) -M$(UTSBASE)/common/ctf/mapfile -dy -- cgit v1.2.3